Severity
P1 — hostile agent card grants implicit trust; can shadow legitimate agents.
Files
crates/librefang-api/src/routes/network.rs:721-738, 650-688
crates/librefang-runtime/src/a2a.rs:476-503
Finding
After client.discover(&url) succeeds, the card is pushed straight into
kernel.a2a_agents() with no operator approval step, no
certificate/JWS signature verification, and no name-uniqueness check. A
remote can self-declare any name and any skills[] (e.g. claim it has a
delete_file skill).
a2a_get_external_agent looks them up by name and returns the first
iteration-order match (HashMap-backed via Vec push), so a later-discovered
hostile agent can shadow or impersonate a legitimate one. There is no
revocation path, no TOFU fingerprint pinning, and no kid/iss validation.
Combined with #53, a hostile agent card whose skills appear in the local
prompt or whose name is referenced by an internal router silently grants
implicit trust to whatever URL was last discovered.
Evidence
if let Some(existing) = agents.iter_mut().find(|(u, _)| u == &url) {
existing.1 = card;
} else {
agents.push((url.clone(), card)); // no approval, no signature check
}
Suggested Fix
Require operator confirmation via the existing approvals workflow before a
discovered agent becomes addressable; persist a fingerprint of the card
(sha256 over canonical JSON) and TOFU-pin it; reject duplicate name from
a different url; verify the card's optional signature field if present
and stamp trust_level=unverified otherwise so callers can refuse to inject
untrusted skill lists into prompts.
Severity
P1 — hostile agent card grants implicit trust; can shadow legitimate agents.
Files
crates/librefang-api/src/routes/network.rs:721-738, 650-688crates/librefang-runtime/src/a2a.rs:476-503Finding
After
client.discover(&url)succeeds, the card is pushed straight intokernel.a2a_agents()with no operator approval step, nocertificate/JWS signature verification, and no name-uniqueness check. A
remote can self-declare any
nameand anyskills[](e.g. claim it has adelete_fileskill).a2a_get_external_agentlooks them up by name and returns the firstiteration-order match (HashMap-backed via
Vecpush), so a later-discoveredhostile agent can shadow or impersonate a legitimate one. There is no
revocation path, no TOFU fingerprint pinning, and no
kid/issvalidation.Combined with #53, a hostile agent card whose skills appear in the local
prompt or whose name is referenced by an internal router silently grants
implicit trust to whatever URL was last discovered.
Evidence
Suggested Fix
Require operator confirmation via the existing approvals workflow before a
discovered agent becomes addressable; persist a fingerprint of the card
(sha256 over canonical JSON) and TOFU-pin it; reject duplicate
namefroma different
url; verify the card's optionalsignaturefield if presentand stamp
trust_level=unverifiedotherwise so callers can refuse to injectuntrusted skill lists into prompts.