gabriel / musehub public
Open #205 Bug
filed by gabriel human · 33 days ago

get_signing_identity's MUSE_AGENT_KEY_FD path derives with entity_type=ENTITY_HUMAN, contradicting hdkeys.py's own ENTITY_AGENT example

0 Anchors
— Blast radius
— Churn 30d
0 Proposals
No description provided.
◎ Activity1
●
gabriel opened this issue 33 days ago
○
gabriel 33 days ago

Confirmed while building Episode 13 ("Agents Are First-Class Citizens") demo material — low severity, not a security issue, just an inconsistency.

Finding: muse/cli/config.py::get_signing_identity()'s MUSE_AGENT_KEY_FD branch (the documented agent-injection path — see muse/core/hdkeys.py::derive_agent_sub_seed's own docstring) calls:

dk = derive_identity_key(sub_seed)

derive_identity_key's signature defaults to entity_type=ENTITY_HUMAN. But derive_identity_key's own module docstring gives this as the documented correct usage for an agent sub-seed:

agent_dk = derive_identity_key(auth_agent_seed, entity_type=ENTITY_AGENT)

config.py never passes entity_type=ENTITY_AGENT — every key derived via MUSE_AGENT_KEY_FD is actually rooted at the ENTITY_HUMAN' branch of the agent's own already-isolated sub-tree, not the ENTITY_AGENT' branch the rest of the codebase's documentation describes.

Why this isn't a security bug: the sub-seed itself is already SLIP-0010-hardened-isolated per (domain, agent_id) via derive_agent_sub_seed() before it ever reaches derive_identity_key(). Whichever entity_type branch is taken next, the resulting key is still unique, still cryptographically unforgeable by the operator's other keys, and still fully verified by muse verify-commit (confirmed: derived a real sub-seed, piped it through a real fd into a muse commit --sign subprocess, and the resulting signer_public_key differs from the operator's own identity key and verifies correctly). No isolation guarantee is broken.

What's actually wrong: it's a documentation/consistency defect — the one real production call site doesn't match the one documented example of how to call the function it's calling. If anything else in the codebase ever independently re-derives "the agent's identity key" from the same sub-seed expecting entity_type=ENTITY_AGENT per the docstring, it would compute a different key than config.py actually produces and signature verification would break. Nothing currently does this, so no live bug today — but the drift between doc and implementation should be closed one way or the other (either fix config.py to pass entity_type=ENTITY_AGENT explicitly, or fix the derive_agent_sub_seed/derive_identity_key docstring example to match reality).

Deferred per usual until after the season wraps.