COSE HeaderMap: header() and equality use Map reference equality; build() creates duplicate label entries

Open
#482 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
70/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
typescript
Domain
security

Research direction

Start with packages/evolution/src/cose/Header.ts, especially header() and [Equal.symbol], then inspect packages/evolution/src/cose/Key.ts around EdDSA25519Key.build(). Add the described regression test for a text label, and verify that header() returns the bytes, structurally equal HeaderMaps compare correctly, and setHeader does not leave duplicate logical labels.

Written by the indexing model from the issue text.

Description

enhancement external-review

Summary

HeaderMap stores headers in a JS Map keyed by Label objects, but Label uses structural equality while Map.get/Map.set use reference equality. As a result:

  • (a) the public header() accessor calls this.headers.get(label) with a freshly built Label, so it always returns undefined;
  • (b) HeaderMap [Equal.symbol] looks up keys from this in that's map by reference, so two structurally-equal HeaderMaps never compare equal;
  • (c) setAlgorithmId followed by setHeader(labelFromInt(1n), ...) inserts two distinct Label objects for logical key 1, leaving two entries in the map.

No functional or security impact today: the security paths (verifyData, algorithmId, keyId) iterate the map manually with Equal.equals and are unaffected, header() is unused, and the duplicate label-1 entries collapse to a single correct entry on CBOR encode (encode re-keys by primitive value). Latent correctness / cleanup.

Affected

packages/evolution/src/cose/Header.ts

  • header() (L260-262): this.headers.get(label) uses reference equality -> always undefined
  • [Equal.symbol] (L43-51): that.headers.get(key) uses reference equality -> HeaderMaps never equal

packages/evolution/src/cose/Key.ts

  • EdDSA25519Key.build() (L248-252): setAlgorithmId(1n) then setHeader(labelFromInt(1n), ...) create two entries at logical key 1

Fix

Stop keying a JS Map by objects with custom equality. Either intern Label instances so structurally-equal labels share a reference, or replace the map lookups (header(), equality, setHeader overwrite) with Equal.equals-based iteration (as the working accessors already do). Making setHeader overwrite an existing logical key also removes the duplicate label-1 entries in build().

Regression test

  • given: a HeaderMap built with setHeader(labelFromText("address"), bytes)
  • before fix: hm.header(labelFromText("address")) returns undefined
  • after fix: returns the bytes
    Must FAIL on main today and PASS after the fix.

Reference

Reported informally (HeaderMap reference-equality). No live security impact; cleanup for a broken public accessor and a fragile build path.

Dominant language
TypeScript
Stars
22
Forks
30
Avg merge
13h
Merged PRs (30d)
14

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from IntersectMBO/evolution-sdk

All issues in IntersectMBO/evolution-sdk

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.