Skip to content

Handle mismatched id values in standalone key documents #963

Description

@dahlia

When resolveFetchedKey in packages/fedify/src/sig/key.ts fetches the document at a keyId URL and parses it as a standalone CryptographicKey or Multikey, it does not check whether the object's id matches the requested URL:

let key: T | null = null;
if (object instanceof cls) key = object;
else if (isActor(object)) {
  // …iterates keys and matches k.id?.href === keyId
}

The actor branch compares each candidate with k.id?.href === keyId before accepting it. The standalone branch skips that check. A document served at one URL can therefore declare a different id and still be cached under the requested URL.

This came from a security report, but we closed the report because the mismatch does not provide a way to impersonate another actor. The verification path does not use the key document's id to establish the actor's identity. It checks the key's owner or controller against the activity's actor.

The current behavior is nevertheless confusing: key.id may differ from the keyId used for the lookup and cache entry. For a standalone key with a present but mismatched id, we could reject the document or emit a warning.

The actor branch intentionally allows one related case. When the requested keyId has no fragment and the actor exposes exactly one key, it accepts that key without an exact id match:

const keyIdUrl = new URL(keyId);
if (key == null && keyIdUrl.hash === "" && length === 1) {
  key = lastKey;
}

A change to the standalone path should account for this existing tolerance rather than making the result depend unexpectedly on whether the response is an actor or a key document. I am not yet sure whether a mismatch should be an error. Logging it is less likely to break interoperability, but rejecting it keeps the fetched key's identity aligned with its cache key.

Acceptance criteria:

  • A standalone key document with a present id that differs from the requested keyId is rejected or handled according to a documented and tested rule.
  • The fragmentless single-key tolerance in the actor branch continues to work.
  • A regression test covers a standalone key document with a mismatched id.

Metadata

Metadata

Assignees

No one assigned

    Type

    Fields

    Priority

    Low

    Effort

    Low

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions