A manifest names an environment variable through api_key_env, and the bundled annotator dispatchers resolve it against the host process environment (src/dispatchers/http.rs:189, src/dispatchers/bundled.rs:93). A manifest can also be fetched over the network, through ManifestUrlExtends (src/manifest.rs:107).
Those two capabilities are individually reasonable. Together they let a manifest the host did not author name a host secret and send it somewhere.
The chain is: a remote manifest declares an llm or endpoint annotator, points it at an attacker-controlled URL, and sets api_key_env to a variable the host process holds. The dispatcher reads the variable and attaches it to the outbound request.
What was there before
The engine AGT vendored before this extraction tracked manifest provenance and refused that combination. Four functions implemented it, none of which survive in 0.4.0-alpha.1:
Manifest::with_url_sourced and with_limits_and_source, which recorded that a manifest arrived over the network
reject_filesystem_path_fields, which stopped a URL-sourced manifest naming local paths
reject_url_sourced_remote_bundle, which stopped it pointing at a remote Rego bundle
grep -rn "url_sourced" src/ returns nothing in 0.4.0-alpha.1, so the gate did not move elsewhere under a different name.
Why this is awkward downstream
A host can avoid the exposure only by refusing the bundled annotator dispatchers entirely, which is what agent-governance-toolkit now does: it puts them behind an off-by-default cargo feature. That trades a targeted control for a blunt one. A host that wants Azure Content Safety annotation on a local manifest has to opt into the same switch that permits credential reads on a remote one.
What would close it
Restoring provenance on Manifest would be enough. The dispatchers already have the manifest when they resolve api_key_env, so a flag they can consult is sufficient; the policy of what a URL-sourced manifest may do can stay where it was.
A narrower alternative, if provenance is out of scope: let a host supply an allowlist of environment variable names the dispatchers may read. That does not distinguish local from remote manifests, but it bounds the blast radius to variables the host nominated.
Notes
Verified against the published 0.4.0-alpha.1 sources. This is not a regression report against a previous ACS release; the gate existed in the pre-extraction AGT tree and did not carry over, so it may simply have been out of scope for the extraction rather than dropped deliberately.
Related: #14 covers a separate gap in the published bindings.
A manifest names an environment variable through
api_key_env, and the bundled annotator dispatchers resolve it against the host process environment (src/dispatchers/http.rs:189,src/dispatchers/bundled.rs:93). A manifest can also be fetched over the network, throughManifestUrlExtends(src/manifest.rs:107).Those two capabilities are individually reasonable. Together they let a manifest the host did not author name a host secret and send it somewhere.
The chain is: a remote manifest declares an
llmorendpointannotator, points it at an attacker-controlled URL, and setsapi_key_envto a variable the host process holds. The dispatcher reads the variable and attaches it to the outbound request.What was there before
The engine AGT vendored before this extraction tracked manifest provenance and refused that combination. Four functions implemented it, none of which survive in 0.4.0-alpha.1:
Manifest::with_url_sourcedandwith_limits_and_source, which recorded that a manifest arrived over the networkreject_filesystem_path_fields, which stopped a URL-sourced manifest naming local pathsreject_url_sourced_remote_bundle, which stopped it pointing at a remote Rego bundlegrep -rn "url_sourced" src/returns nothing in 0.4.0-alpha.1, so the gate did not move elsewhere under a different name.Why this is awkward downstream
A host can avoid the exposure only by refusing the bundled annotator dispatchers entirely, which is what agent-governance-toolkit now does: it puts them behind an off-by-default cargo feature. That trades a targeted control for a blunt one. A host that wants Azure Content Safety annotation on a local manifest has to opt into the same switch that permits credential reads on a remote one.
What would close it
Restoring provenance on
Manifestwould be enough. The dispatchers already have the manifest when they resolveapi_key_env, so a flag they can consult is sufficient; the policy of what a URL-sourced manifest may do can stay where it was.A narrower alternative, if provenance is out of scope: let a host supply an allowlist of environment variable names the dispatchers may read. That does not distinguish local from remote manifests, but it bounds the blast radius to variables the host nominated.
Notes
Verified against the published 0.4.0-alpha.1 sources. This is not a regression report against a previous ACS release; the gate existed in the pre-extraction AGT tree and did not carry over, so it may simply have been out of scope for the extraction rather than dropped deliberately.
Related: #14 covers a separate gap in the published bindings.