Skip to content

fix(supervisor): classify credential placeholders in request bodies - #3246

Open
johntmyers wants to merge 1 commit into
mainfrom
fix/2904-placeholder-body-classification/johntmyers
Open

fix(supervisor): classify credential placeholders in request bodies#3246
johntmyers wants to merge 1 commit into
mainfrom
fix/2904-placeholder-body-classification/johntmyers

Conversation

@johntmyers

Copy link
Copy Markdown
Collaborator

Summary

Tool output containing credential-placeholder syntax can poison conversation history and block every subsequent model request. Classify REST body placeholders against a request-scoped credential snapshot so unknown literals and valid references bound to another endpoint pass unchanged, while destination-bound and uncertain references remain denied.

Related Issue

Closes #2904. Includes the foreign-provider reproduction consolidated from #3237.

Changes

  • Track classification metadata independently of usable secret values, including retained keys, credential identities, revisions, and endpoint bindings.
  • Inspect complete canonical and provider-shaped tokens across fixed-length and chunked bodies, including percent encoding. Preserve permitted bytes and bound candidate buffering to 4096 wire bytes.
  • Return a local HTTP 403 with credential_placeholder_in_request_body, emit controlled OCSF denial reasons, and discard rejected upstream requests. Apply the handling to CONNECT and forward-proxy paths.
  • Add classifier, streaming, diagnostic, built-in profile, and sandbox conversation-replay regressions. Update policy documentation, the security architecture overview, and inference troubleshooting guidance.

Testing

  • mise run pre-commit passes, including the commit hook.
  • mise run test passes.
  • mise run ci passes.
  • Affected Rust crate tests: 1,775 passed, 2 existing ignored tests.
  • OPENSHELL_E2E_DOCKER_TEST=credential_gating mise run e2e:docker passes: CLI conformance smoke and the credential-gating E2E test.

The Docker run built the supervisor from this source tree and exercised both conversation-history cases and replay through a real sandbox. Built-in Codex, Claude Code, Copilot, and GitHub profile definitions are covered by deterministic tests. Live agent/model API smoke tests were not run; Podman is not installed on this host.

The full test/CI commands used a command-scoped tag.gpgSign=false Git override because the temporary-repository tag fixtures otherwise inherit local tag-signing configuration. No global Git settings were changed.

Checklist

  • Follows Conventional Commits.
  • Commit is signed off for DCO.
  • Architecture and user-facing documentation updated.

Closes #2904

Signed-off-by: John Myers <johntmyers@users.noreply.github.com>
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

@johntmyers

Copy link
Copy Markdown
Collaborator Author

🏗️ build-from-issue-agent

E2E Test Attestation

Local Docker E2E passed against the supervisor built from the committed source tree.

Field Value
Commit 293d18e777917295e6744ef7ae59056cdfc679e5
Command OPENSHELL_E2E_DOCKER_TEST=credential_gating mise run e2e:docker
Gateway mode Docker, local macOS ARM64 host with Linux ARM64 supervisor
Result Passed

Tests Executed

  • CLI conformance smoke — passed: authenticated status, sandbox create, get-ready, list-visible, exec, delete, and list-empty checks.
  • e2e/rust/tests/credential_gating.rs::credentialed_endpoint_gates_work_end_to_end — passed. Covers existing destination-bound denial and credential rewrite/admission behavior, plus unknown literal and foreign-provider conversation bodies, each replayed twice through a sandbox.

Rust E2E result: 1 passed, 0 failed, 0 ignored, 45.35 seconds. Conformance reported passed: true. No E2E tests were skipped in this targeted run.

Live model/agent API smoke tests were not run. Podman is not installed on this host. Built-in agent profile coverage is provided by the Rust tests reported in the PR description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(supervisor): literal and foreign-provider placeholders in conversation history block inference

1 participant