Skip to content

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

Description

@solidsnakedev

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions