You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Surfaced during review of PR #1323 (agent feedback loop /wait endpoint).
The sandbox supervisor authenticates to the gateway with
`x-sandbox-secret`, validated against the server-wide
`ssh_handshake_secret` config value. The secret is a single string for
the whole gateway — not per-sandbox.
Several gRPC methods accept this auth scheme:
`SubmitPolicyAnalysis` (SANDBOX_SECRET_METHODS, existing) — request
carries a `sandbox_name` field; handler persists chunks under that
name without verifying the caller "is" that sandbox.
Other entries in SANDBOX_SECRET_METHODS follow the same pattern.
Exposure
Any process that holds the shared sandbox secret can act under any
sandbox name. Concrete impact:
Read: enumerate another sandbox's draft policy chunks
(including rationale/proposed_rule, which can leak the agent's intent
and the developer's reviewer guidance).
Write: submit policy proposals to another sandbox's draft set, with
the receiving developer seeing them in their TUI inbox as if from
their own agent.
This is symmetric across the read and write paths — both already
exist; #1323 extends the read surface as a no-net-new-attack-class
expansion. Worth fixing in one motion rather than two.
Proposed direction
Bind the sandbox secret to a sandbox identity at handshake time so the
gateway can enforce "caller name matches request name" on every
sandbox-secret-authenticated method.
Two plausible shapes:
Per-sandbox secret. Gateway issues each sandbox a unique secret
during handshake; secret carries (or is keyed on) the sandbox name.
Validation extracts the name from the secret rather than the
request.
Signed sandbox identity claim. Single shared secret, but a
short-lived signed token issued at handshake carries the sandbox
name. Sandbox includes the token alongside the secret; gateway
verifies the signature and compares to the request name.
(1) is simpler but requires per-sandbox secret storage and rotation.
(2) preserves the current single-secret deploy model but adds a
signing step.
Out of scope for this issue
Bearer-token / OIDC authz (already enforced via scopes).
Network policy on the sandbox→gateway channel.
Acceptance
All SANDBOX_SECRET_METHODS and DUAL_AUTH_METHODS handlers that name
a sandbox in the request body verify the caller is that sandbox.
Cross-sandbox call is denied with a clear error.
Migration path documented for existing deployments (existing
sandboxes can't speak the new scheme until they restart against an
upgraded gateway).
Regression tests cover at least: same-sandbox call succeeds,
cross-sandbox call fails with permission_denied.
Context
Surfaced during review of PR #1323 (agent feedback loop /wait endpoint).
The sandbox supervisor authenticates to the gateway with
`x-sandbox-secret`, validated against the server-wide
`ssh_handshake_secret` config value. The secret is a single string for
the whole gateway — not per-sandbox.
Several gRPC methods accept this auth scheme:
carries a `sandbox_name` field; handler persists chunks under that
name without verifying the caller "is" that sandbox.
/wait works under OIDC) — request carries a `name` field; handler
looks up the sandbox by name without verifying the caller's identity.
Exposure
Any process that holds the shared sandbox secret can act under any
sandbox name. Concrete impact:
(including rationale/proposed_rule, which can leak the agent's intent
and the developer's reviewer guidance).
the receiving developer seeing them in their TUI inbox as if from
their own agent.
This is symmetric across the read and write paths — both already
exist; #1323 extends the read surface as a no-net-new-attack-class
expansion. Worth fixing in one motion rather than two.
Proposed direction
Bind the sandbox secret to a sandbox identity at handshake time so the
gateway can enforce "caller name matches request name" on every
sandbox-secret-authenticated method.
Two plausible shapes:
during handshake; secret carries (or is keyed on) the sandbox name.
Validation extracts the name from the secret rather than the
request.
short-lived signed token issued at handshake carries the sandbox
name. Sandbox includes the token alongside the secret; gateway
verifies the signature and compares to the request name.
(1) is simpler but requires per-sandbox secret storage and rotation.
(2) preserves the current single-secret deploy model but adds a
signing step.
Out of scope for this issue
Acceptance
a sandbox in the request body verify the caller is that sandbox.
sandboxes can't speak the new scheme until they restart against an
upgraded gateway).
cross-sandbox call fails with permission_denied.
References
`crates/openshell-server/src/auth/oidc.rs::validate_sandbox_secret`