Skip to content

Follow RFC 9597 for CWT Claims in COSE headers - #708

Merged
dajiaji merged 1 commit into
dajiaji:mainfrom
achamayou:achamayou-rfc9597-cwt-claims-plan
Nov 9, 2026
Merged

dajiaji merged 1 commit into
dajiaji:mainfrom
achamayou:achamayou-rfc9597-cwt-claims-plan

Conversation

@achamayou

@achamayou achamayou commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

draft-ietf-cose-cwt-claims-in-headers-06, which python-cwt implements, was published as RFC 9597 (Standards Track, June 2024). This PR proposes bringing the library in line with the final RFC. It was written with the help of AI, but I reviewed all changes and believe them to be correct.

Label reassignment (breaking change)

During IETF Last Call, IANA noted that the label requested by draft-06, 13, had already been assigned, so draft-07 moved the request to the next free label, 15.

Label draft-06 IANA registry today
13 requested for CWT Claims kcwt (RFC 9528, EDHOC)
15 – CWT Claims (RFC 9597 §2), map
  • COSEHeaders.CWT_CLAIMS changes from 13 to 15.
  • Label 13 is no longer interpreted as CWT Claims, since it now means kcwt. Previously, a kcwt-shaped (non-map) value under 13 made CWT.decode() raise an AttributeError. This PR does not attempt to add RFC 9528 support.
  • Tokens that put claims under 13 are no longer cross-checked and should be re-issued with 15. README and CHANGES call this out.

Checks required by RFC 9597 §2

These requirements are the same in draft-06 and the RFC, but were only partly implemented:

Requirement Before After
Claim values in the header and payload are identical Only the protected header of the innermost COSE layer was checked, using Python == Protected and unprotected headers of every layer of a nested CWT are checked, comparing CBOR data items (1, 1.0 and True differ; map key order does not matter)
The parameter occurs only once, in either the protected or unprotected header Not checked on decode ValueError
The value is a map AttributeError ValueError

The error message for a protected-header mismatch is unchanged. no_verify=True still skips these checks, and a claim that appears only in the header is still accepted. Headers of individual signers and recipients are not checked.

Not included

  • Rejecting duplicate labels across protected and unprotected headers for all labels in COSE.decode*. This would be a broader behaviour change.
  • Named support for kcwt (13) and kccs (14) from RFC 9528, and typ (16) from RFC 9596.

Docs

  • RFC 9597 replaces draft-06 in both spec lists, without the "experimental" label.
  • The README section states the label, explains the reassignment, describes what decode() checks, and links to the RFC's recommendations.
  • CHANGES (Unreleased) and the CWT.decode docstring are updated.

Testing

  • New tests in tests/test_cwt.py cover:
    • label 15 on the wire, and label 13 being ignored;
    • protected and unprotected matches and mismatches;
    • the parameter in both headers, and non-map values;
    • claims absent from the payload, and structured values;
    • no_verify;
    • outer and inner layers of nested CWTs;
    • strict CBOR comparison.
  • 17 of the new tests fail against the current main.
  • Locally, on Python 3.10 and 3.14:
    • 1531 tests pass, with 100% coverage of cwt/cwt.py and cwt/enums.py;
    • pre-commit run --all-files passes;
    • the Sphinx build with -n -W passes;
    • poetry build succeeds.

@codecov

codecov Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.07%. Comparing base (2173bbb) to head (79453cf).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #708      +/-   ##
==========================================
+ Coverage   97.06%   97.07%   +0.01%     
==========================================
  Files          32       32              
  Lines        3476     3490      +14     
==========================================
+ Hits         3374     3388      +14     
  Misses        102      102              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@achamayou
achamayou marked this pull request as draft November 8, 2026 16:39
draft-ietf-cose-cwt-claims-in-headers-06 is now RFC 9597. IANA assigned
label 15 to the CWT Claims header parameter; the draft's requested label
13 went to kcwt (RFC 9528). COSEHeaders.CWT_CLAIMS is now 15 and 13 is
no longer interpreted as CWT Claims.

CWT.decode() now checks the CWT Claims header parameter in both the
protected and unprotected headers of every COSE layer of a nested CWT,
not only the protected header of the innermost layer. Header and payload
claim values must be identical CBOR data items. A parameter that is not
a map, or that occurs in both the protected and unprotected header, is
rejected with ValueError.

Update README and CHANGES accordingly.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@achamayou
achamayou force-pushed the achamayou-rfc9597-cwt-claims-plan branch from 5cac2f4 to 79453cf Compare November 8, 2026 16:52
@achamayou
achamayou marked this pull request as ready for review November 8, 2026 16:55
@dajiaji

dajiaji commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Thanks @achamayou! Verified locally: all tests pass with both cbor2 5.x and 6.x, and pre-commit is clean. No major issues, so I'm merging this.

Since the label change is breaking, I plan to release it as v4.0.0. Let me know if that's a problem for CCF.

@dajiaji
dajiaji merged commit e3ac4f2 into dajiaji:main Nov 9, 2026
17 checks passed
@achamayou

Copy link
Copy Markdown
Contributor Author

Thanks @achamayou! Verified locally: all tests pass with both cbor2 5.x and 6.x, and pre-commit is clean. No major issues, so I'm merging this.

Since the label change is breaking, I plan to release it as v4.0.0. Let me know if that's a problem for CCF.

Thank you, yes a 4.0.0 makes sense, I agree. It is not at all a problem for CCF, we will update as soon as it's available.

@dajiaji

dajiaji commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Hi @achamayou, I've released v4.0.0, which includes your RFC 9597 and RFC 9864 updates. Thanks for your contributions! Since it's a major release, I also took the chance to include several changes that are hard to make outside a major version bump, such as dropping Python 3.10.

@achamayou

Copy link
Copy Markdown
Contributor Author

@dajiaji many thanks for releasing so quickly, and for reviewing and accepting the PRs! I will pick up the update on the CCF side now.

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.

2 participants