Skip to content

URL-sourced manifests can read host environment credentials #20

Description

@liamcrumm

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.

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions