Skip to content

fix(sdk): authenticate empty AES-GCM payloads in portable runtimes - #574

Merged
ty-everett merged 1 commit into
mainfrom
codex/sdk-empty-aes-portable
Sep 23, 2026
Merged

ty-everett merged 1 commit into
mainfrom
codex/sdk-empty-aes-portable

Conversation

@ty-everett

@ty-everett ty-everett commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

Program and scope

Fixes #573. Portable AES-GCM rejected an authenticated empty ciphertext before checking its tag. A valid 48-byte SymmetricKey envelope produced by Node or the portable encryptor therefore failed in browser/mobile runtimes. Remove only that premature rejection and retain the complete authentication path and historical encryption bytes.

Impact

  • Public package source or manifest changed: @bsv/sdk 2.8.0 → 2.8.1 (patch).
  • Browser/mobile behavior and a security-sensitive boundary changed.
  • Documentation, generated API section, changelog and SDK release metadata updated.

No API, encrypted envelope, account-data or ciphertext migration. No service deployment. Single-package release scope: existing consumers accept the compatible patch; dependent packages are not being repacked or published in this PR.

The old padding comment incorrectly claimed incompatible tags. GHASH starts at zero, so its historical leading zero block, including the additional empty-ciphertext zero block, leaves that initial state unchanged. The formatter itself remains untouched; independent Node AES-128/192/256 tests verify identical ciphertext and tags with 12-/32-byte IVs and 0/1/15/16/17/64-byte payloads.

Verification

  • Regression before the implementation change: 7 failures, 30 passes. All failures were empty-payload decryption, including forced-portable SymmetricKey.
  • After repair: focused suite 85/85; complete SDK coverage suite 7,366/7,366, 207/207 suites.
  • Passed: pnpm health:check, lint, format:check, build, typecheck, audit:security, check-versions, docs:facts:check.
  • Passed: SDK pack:check (conditional/wildcard exports, maps, strict types, clean CJS/ESM consumers) and test:browser (Vite, esbuild, UMD and committed budgets).
  • Negative coverage: every tag byte changed, missing/truncated/overlong tags, wrong key/IV, changed ciphertext and truncated SymmetricKey envelopes. Node's fast path is explicitly disabled for the wrapper regression.
  • Generated primitives documentation: ran the configured ts2md generator and materialized only its AESGCM section, retaining unrelated generated sections.
  • Exact-head CI, CodeQL and Conformance passed, including all four dependent regression shards, packed/platform consumers, strict zero-new-finding Sonar gate, Codecov and final merge gate. All 29 successful checks plus 9 scope-validated skips are terminal; zero open PR CodeQL alerts and zero unresolved review threads.
  • Complete diff self-reviewed for correctness, security, compatibility, artifacts, dependencies, docs and operations.
  • All exact-head hosted checks are terminal and successful.

Security and dependencies

  • No dependency/lockfile change, override, suppression, advisory dismissal or skipped test.
  • Negative tests cover the changed authentication boundary.
  • Audit reports no known vulnerabilities.
  • Exact-head CodeQL has no new alert.
  • Repository quality gate reports zero new Sonar findings and unreviewed hotspots.

Dependency evidence

No external dependency upgrade. Native Node crypto is an independent test oracle only and does not enter the package runtime. The packed consumer and browser checks pass; no budget was raised.

Release and operations

  • No npm publication from the workstation or this PR.
  • SDK patch version and current documentation/migration metadata included.
  • npm still reports SDK 2.8.0; 2.8.1 was absent at preflight. Publish only after reviewed merge and exact-main acceptance through the protected single-package workflow, then verify provenance and registry integrity.
  • A forward patch is the rollback path; never modify a published version.

Completion evidence

  • Hosted gates, security analyses and review conversations complete.
  • One qualified maintainer approval is sufficient; no last-pusher restriction assumed.
  • Publication and downstream wallet releases remain separate, explicitly pending steps.

@sonarqubecloud

Copy link
Copy Markdown

@codecov

codecov Bot commented Sep 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ty-everett
ty-everett marked this pull request as ready for review September 23, 2026 16:08
@ty-everett

Copy link
Copy Markdown
Collaborator Author

Maintainer review for exact head fc050fb0835c358b7fda449e6791da264774108a: re-read the complete 12-file diff, including generated API output and release metadata. The only runtime change removes the premature empty-ciphertext rejection; IV/key validation, tag length/equality authentication and ciphertext encoding remain unchanged. Independent native AES vectors and forced-portable wrapper tests cover valid empty data and rejection of altered, truncated or missing authentication. Full SDK tests, affected dependents, packed/browser/mobile consumers and the exact-head merge gate passed. Zero open PR CodeQL alerts, zero new Sonar findings/unreviewed hotspots, and no unresolved review threads. No remaining actionable finding from this self-review; this is not an independent review. Proceeding under the authorized maintainer/admin merge policy; SDK-only protected publication remains a separate step after main passes.

@ty-everett
ty-everett merged commit e095155 into main Sep 23, 2026
38 checks passed
@ty-everett
ty-everett deleted the codex/sdk-empty-aes-portable branch September 23, 2026 16:08
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.

SDK portable AES-GCM rejects valid encrypted empty fields across Node and mobile runtimes

1 participant