Skip to content

fix(envelope): fail closed when an authenticated decrypt surfaces no skid (#52)#55

Merged
moisesja merged 1 commit into
mainfrom
feat/authcrypt-skid-guard-52
Jul 20, 2026
Merged

fix(envelope): fail closed when an authenticated decrypt surfaces no skid (#52)#55
moisesja merged 1 commit into
mainfrom
feat/authcrypt-skid-guard-52

Conversation

@moisesja

Copy link
Copy Markdown
Owner

Closes #52.

What

Defense-in-depth guard in the authcrypt unpack branch: whenever a decrypt is authenticated, EnvelopeReader now asserts a non-empty skid and rejects with ConsistencyException otherwise — parity with the JWS branch's empty-signer-kid guard (6f393e9).

Why

The branch trusted DataProofs' definitional invariant IsAuthenticated ⟺ non-empty skid (JweParser.cs:439/572) without asserting it. Both regression shapes were traced:

  • null skid → the FR-CONSIST-01 fromskid check is silently skipped; message.From would be attacker-set on an envelope the whole stack reports as authenticated.
  • empty skidCheckAuthcryptFromMatchesSkid throws a raw ArgumentException, escaping the FR-API-07 unpack exception contract (fails closed, wrong type).

The guard covers both and fires before any trust state (authenticated/senderKid) is set.

Decisions (pre-made, per the issue)

  • ConsistencyException, as the issue specifies. The JWS branch's CryptoException asymmetry is deliberate and untouched — no scope creep into that branch, line-127 semantics, DataProofs, or the PRD.
  • Testability: the EnvelopeReader call site is unreachable through the real parser by construction (the invariant is definitional upstream; no parser seam exists, deliberately). The check therefore lives in AddressingConsistency as CheckAuthcryptSkidSurfaced and is unit-tested directly (null → throws, empty → throws, valid → passes), the same pattern as every other FR-CONSIST rule. Precedent: the JWS guard shipped without a message-level test.

Risk

Zero behavior change for any input that exists today — no legitimate flow, no currently-craftable envelope reaches the guard. Full suite green: 757 passed, 0 failed (598 core + 159 interop), no existing test modified.

🤖 Generated with Claude Code

…skid (#52)

The authcrypt unpack branch trusted DataProofs' definitional invariant
IsAuthenticated <=> non-empty skid without asserting it. Had it ever
regressed, a null skid would silently skip the FR-CONSIST-01 from<->skid
binding on an envelope still reported authenticated; an empty skid would
escape as a raw ArgumentException off the FR-API-07 contract.

Assert a surfaced skid whenever a decrypt is authenticated, rejecting
with ConsistencyException — parity with the JWS branch's signer-kid
guard (6f393e9). The check lives in AddressingConsistency as
CheckAuthcryptSkidSurfaced so it is directly unit-tested; the
EnvelopeReader call site is unreachable through today's parser by
construction, so no current input changes behavior.

Closes #52.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@moisesja moisesja self-assigned this Jul 20, 2026
@moisesja moisesja added this to the 1.3.0 milestone Jul 20, 2026
@moisesja
moisesja merged commit 660f1da into main Jul 20, 2026
2 checks passed
@moisesja
moisesja deleted the feat/authcrypt-skid-guard-52 branch July 20, 2026 22:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Defense in depth: authcrypt unpack should assert non-empty skid (parity with the JWS branch)

1 participant