Skip to content

fix: security hardening — policyHash min, SPA nonce, PolicyGrant signing, cumulative budget, hash binding#39

Merged
naory merged 1 commit intomainfrom
fix/security-hardening
Mar 14, 2026
Merged

fix: security hardening — policyHash min, SPA nonce, PolicyGrant signing, cumulative budget, hash binding#39
naory merged 1 commit intomainfrom
fix/security-hardening

Conversation

@naory
Copy link
Copy Markdown
Collaborator

@naory naory commented Mar 14, 2026

Summary

  • policyHash minimum raised from 6 → 12 hex chars; Full Profile SHOULD use SHA-256 (64 chars)
  • SPA nonce field added (nonce?: string); createSignedPaymentAuthorization() auto-generates a UUID nonce for one-time-use replay tracking
  • PolicyGrant signing — new src/protocol/policyGrant.ts with createSignedPolicyGrant() / verifyPolicyGrantSignature(); verifier enforces signature when MPCP_POLICY_GRANT_SIGNING_PUBLIC_KEY_PEM is set (opt-in, backward compatible)
  • Cumulative budget enforcementcumulativeSpentMinor?: string added to SettlementVerificationContext; budget check becomes alreadySpent + current > maxAmountMinor when provided
  • Hash binding indicatorhashBindingChecked?: boolean on VerificationReport; CLI outputs Hash binding: CHECKED (Full Profile) or NOT CHECKED (Lite Profile — intentHash absent)
  • Synthesized decision flaggingdecisionFromSpa() marks result _synthesized: true; bundleToContext() warns; CLI shows ⚠ Policy decision: SYNTHESIZED FROM SPA
  • docs/reference/sdk.md updated with createSignedPolicyGrant, cumulative budget usage, 3 new env var rows

New env vars

Variable Purpose
MPCP_POLICY_GRANT_SIGNING_PRIVATE_KEY_PEM Sign PolicyGrants
MPCP_POLICY_GRANT_SIGNING_PUBLIC_KEY_PEM Verify PolicyGrant signatures (unsigned grants rejected when set)
MPCP_POLICY_GRANT_SIGNING_KEY_ID Key ID (default: mpcp-policy-grant-signing-key-1)

Test plan

  • npm run build — clean
  • npm test — 180 tests, 21 files, all pass
  • New test/protocol/policyGrant.test.ts — 9 tests covering sign/verify/tamper/enforcement
  • New cumulative budget overflow test in test/protocol/sba.test.ts
  • New hashBindingChecked tests in test/verify/verify.test.ts
  • Updated test/cli/formatReport.test.ts with hash binding and synthesized decision tests
  • All existing policyHash fixtures updated to 12-char minimum

🤖 Generated with Claude Code

…ing, cumulative budget, hash binding indicator

- Raise policyHashSchema minimum from 6 to 12 hex chars (Full Profile SHOULD use SHA-256 / 64 chars)
- Add SPA nonce field (auto-generated UUID on createSignedPaymentAuthorization)
- Add PolicyGrant signing: createSignedPolicyGrant / verifyPolicyGrantSignature; verifier enforces
  signature when MPCP_POLICY_GRANT_SIGNING_PUBLIC_KEY_PEM is set (opt-in, backward compatible)
- Expose cumulativeSpentMinor in SettlementVerificationContext; thread through pipeline so
  verifier can enforce alreadySpent + currentPayment <= maxAmountMinor
- Add hashBindingChecked to VerificationReport and pipeline output; CLI shows
  "Hash binding: CHECKED" / "NOT CHECKED (Lite Profile)" accordingly
- Flag synthesized PaymentPolicyDecision (_synthesized: true) with console.warn + CLI warning
- Update all test policyHash fixtures to 12-char minimum; add new tests for all new features
- Update docs/reference/sdk.md with createSignedPolicyGrant, cumulative budget note, new env vars

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

1 participant