Skip to content

FIR-429 credential injection - #295

Draft
nappa85 wants to merge 39 commits into
mainfrom
marconapetti/fir-429-pai-credential-injection
Draft

FIR-429 credential injection#295
nappa85 wants to merge 39 commits into
mainfrom
marconapetti/fir-429-pai-credential-injection

Conversation

@nappa85

@nappa85 nappa85 commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Why

firma run needs to keep real secret values out of the agent while still letting
sanctioned tools use them: an agent should be able to fetch and use a secret
without the plaintext ever passing through the agent (or the LLM). This introduces
a Cedar-driven secret interception and redaction mechanism at the process
stdio boundary — the one transport-agnostic point where a vault CLI's plaintext
reliably appears. Full design: docs/architecture/secrets-interception.md (FIR-429).

What Changed

  • One mechanism, two behaviors, all policy-driven: intercept catches a vault CLI's stdout, swaps each secret for a firma-secret://<provider>/<name> placeholder, and stores the real value in an out-of-sandbox, run-scoped, zeroized broker dictionary; redact rehydrates placeholders → secrets on a sanctioned tool's stdin and masks secrets → placeholders on its stdout. No tool is special-cased in code — a new vault CLI is just a new policy.
  • Cedar is the source of truth: new secret.mediate action plus @mode/@matcher/@match_value/@match_name/@match_pattern/@placeholder/@transform annotations, modeled as a SecretMediation enum (Intercept { matcher, placeholder } / Redact { transform }) so illegal combinations are unrepresentable. Matchers (JSONPath or regex) and transforms (raw, mcp-jsonrpc) are validated at bundle-load — a bad pattern fails the bundle closed.
  • PDP/PEP split: the Sidecar stays the only Cedar evaluator (PDP); the firma-run broker (PEP) asks it per-launch over the existing local-exec governance socket — off the network hot path — then applies the decision. Generic stdio interposition via shims + SCM_RIGHTS fd-passing, made unavoidable by bind-over-path; shims hold no secrets.
  • firma.toml holds only the mechanism residue: a per-profile shims executable list (which commands to interpose on). All behavior stays in Cedar, so the config is not secret-specific.
  • End-to-end delivery: broker (dictionary, Aho-Corasick masking, UDS + fd-passing), the intercept path (json/regex extraction + minting), both redact transforms (raw streaming with overlap buffers, mcp-jsonrpc line-framed JSON-aware rewrite), shims config + PATH/bind-over-path shim injection, and Playwright MCP as the first redact target — with the design doc, docs-site, and llms.txt updated.

Risks / Notes

  • Fail-closed throughout: broker unreachable → deny; transform/extract error → block the stream (never forward plaintext or an unrehydrated placeholder); unknown placeholder on a redact stdin is not substituted (tool gets no secret); malformed/unparseable annotations reject the whole bundle at load.
  • Trust boundary: all plaintext and the dictionary live in the broker, out-of-sandbox. Real plaintext appears in the sandbox only transiently on one tool's stdio fd (unavoidable — the vault CLI writes it, or a sanctioned tool reads it), never in the agent process or a shim.
  • Accepted residual exposures (documented in the threat model): the vault CLI's own credential (e.g. BWS_ACCESS_TOKEN) stays in-sandbox by design; stdout masking is best-effort defense-in-depth (transformed secrets — base64/hex/chunked — won't match); a hostile agent could ptrace a specific sanctioned tool to see a secret it itself routed there, but cannot enumerate the dictionary.
  • New wire surface: secret.mediate governance request/response over the existing local-exec socket (per-launch, local, off the hot path).
  • Coarse shadowing cost: shimming a launcher like npx means every launch pays a shim + governance round-trip even when ungoverned (then passes through) — keep shims lists tight.
  • Scope boundary: Linux bwrap backend only; PTY/interactive tools, VM/WSL backends, and additional vault CLIs are deferred hardening (no code changes needed for new CLIs — just new policies).

AI Assistance

claude-opus-4-8

@nappa85
nappa85 marked this pull request as draft July 15, 2026 16:45
@nappa85
nappa85 force-pushed the marconapetti/fir-429-pai-credential-injection branch 14 times, most recently from 43c9654 to 9fd5dae Compare July 22, 2026 13:15
@nappa85
nappa85 force-pushed the marconapetti/fir-429-pai-credential-injection branch 9 times, most recently from ed16939 to 088b5b2 Compare July 27, 2026 09:56
@nappa85
nappa85 force-pushed the marconapetti/fir-429-pai-credential-injection branch from 088b5b2 to b6e98bc Compare July 27, 2026 10:02
@nappa85
nappa85 force-pushed the marconapetti/fir-429-pai-credential-injection branch from 87fffd9 to 54ead3e Compare July 27, 2026 12:25
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.

1 participant