fix: make credentialStatus and expiry non-strippable at issuance - #108
Conversation
Selective disclosure lets the holder omit any statement the issuer did not mark mandatory, and the credential still verifies. `credentialStatus` and the end of the validity window were not mandatory, so a holder could derive them away and present a revoked or expired credential that verifies completely clean: issued with credentialStatus index 5 (revoked) holder derives -> credentialStatus present? false presenting the stripped credential -> SIGNED DOCUMENT_INTEGRITY: VALID / DOCUMENT_STATUS: VALID / ISSUER_IDENTITY: VALID The removal is undetectable. The derived proof records nothing about what was withheld (a stripped credential and one that never had a status decode to the same shape), and dropping the then-unused status-list `@context` entry leaves the canonical RDF — and so the signature — intact. Verification cannot catch this; issuance is the only defence. `coreMandatoryPointers` already forced `/issuer` and `/validFrom`, covering who issued a credential and when it started, but not when it stops being usable. Add, each only when the credential carries the field: - `/validUntil` (v2.0) - `/expirationDate` (v1.1) - `/credentialStatus` This also closes a second bypass found while fixing the tests: the TransferableRecords prohibition was itself strippable. The presentation tests signed fixtures carrying a TransferableRecords status and derived it away, so the guard never fired — a transferable record could be presented as an ordinary credential, sidestepping on-chain ownership entirely. The presentable-credential helper now drops that status before signing; the dedicated rejection block keeps it. Note this changes derivation output: credentials with a status or an expiry now disclose those fields whether or not the holder selected them. That is the point, but it is visible to existing consumers. It is also not retroactive — anything already signed stays strippable and must be reissued. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthrough
ChangesMandatory field preservation
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install timed out. The project may have too many dependencies for the sandbox. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
## [2.4.2](https://github.com/TrustVC/w3c/compare/@trustvc/w3c-vc@2.4.1...@trustvc/w3c-vc@2.4.2) (2026-08-06) ### Bug Fixes * make credentialStatus and expiry non-strippable at issuance ([#108](#108)) ([63fc8b5](63fc8b5))
|
🎉 This PR is included in version 2.4.2 🎉 The release is available on: Your semantic-release bot 📦🚀 |
## [2.4.2](https://github.com/TrustVC/w3c/compare/@trustvc/w3c@2.4.1...@trustvc/w3c@2.4.2) (2026-08-06) ### Bug Fixes * make credentialStatus and expiry non-strippable at issuance ([#108](#108)) ([63fc8b5](63fc8b5))
|
🎉 This PR is included in version 2.4.2 🎉 The release is available on: Your semantic-release bot 📦🚀 |



Summary by CodeRabbit