Authenticate interception server via INTERCEPTION_SECRET#1180
Conversation
76a352c to
630515f
Compare
mikasenghaas
left a comment
There was a problem hiding this comment.
couple nits, once resolved, can merge from my side
| Newer and more experimental environment classes include: | ||
|
|
||
| - **`GymEnv`** — universal runner for Gym-compatible environments (OpenAI Gym / Gymnasium API) | ||
| - **`CliAgentEnv`** — runs custom agent code inside sandboxes, intercepting API requests. Accepts sandbox configuration parameters including `docker_image`, `cpu_cores`, `memory_gb`, `disk_size_gb`, `gpu_count`, `gpu_type`, `timeout_minutes`, `environment_vars`, and `labels` for sandbox categorization. Also accepts retry tuning (like `max_retries`) and connection pooling (like `sandbox_client_max_workers`) parameters via `SandboxMixin`. Subclasses can override `get_sandbox_resources(state)` for per-instance resource allocation and `build_env_vars(state)` for custom environment variables (`PROTECTED_ENV_VARS` cannot be overridden). VMs are auto-enabled when `gpu_count > 0` |
There was a problem hiding this comment.
i don think this needs to be in public docs
There was a problem hiding this comment.
actually it alr seems to have way more details than it should have for an overview
| env_vars.setdefault("HTTPX_TIMEOUT", "3600") | ||
| secret = os.environ.get("INTERCEPTION_SECRET") | ||
| if secret: | ||
| env_vars["OPENAI_API_KEY"] = secret |
There was a problem hiding this comment.
question that just popped in my head: the way we hijack OPENAI_BASE_URL and OPENAI_API_KEY means the agent can never run a request to the actual OAI API, right? e.g. if i wanted my agent to run vf-eval against OAI API directly
this is alr not working before this PR i believe so not a concern, but is this correct?
d498de9 to
5f726f0
Compare
- InterceptionServer accepts optional `secret` parameter; validates Authorization header with hmac.compare_digest when set - CliAgentEnv reads INTERCEPTION_SECRET at startup and injects it as OPENAI_API_KEY into sandbox env vars, overriding any dummy value Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Check Authorization header before rollout lookup to prevent ID enumeration (401 is now indistinguishable from 404 to unauthenticated callers) - Treat empty string INTERCEPTION_SECRET as no secret (consistent between server and build_env_vars) - Document INTERCEPTION_SECRET in docs/environments.md Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5f726f0 to
f96ff0e
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit f96ff0e. Configure here.
| env_vars.setdefault("HTTPX_TIMEOUT", "3600") | ||
| secret = os.environ.get("INTERCEPTION_SECRET") | ||
| if secret: | ||
| env_vars["OPENAI_API_KEY"] = secret |
There was a problem hiding this comment.
RLM harness overrides injected secret causing 401 failures
Medium Severity
When INTERCEPTION_SECRET is set, build_env_vars correctly injects it as OPENAI_API_KEY into sandbox environment variables. However, the existing RLM harness in verifiers/envs/experimental/composable/harnesses/rlm.py hardcodes export OPENAI_API_KEY=intercepted in its shell run command, overriding the framework-injected secret at runtime. The agent then sends Bearer intercepted instead of Bearer <actual_secret>, and the interception server rejects every request with a 401.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit f96ff0e. Configure here.
The RLM harness hardcoded `export OPENAI_API_KEY=intercepted` in its shell run command, a placeholder that made sense when the interception proxy did no auth. After #1180, build_env_vars injects the real INTERCEPTION_SECRET as OPENAI_API_KEY; the hardcoded export clobbered it, causing every agent request to hit the proxy with `Bearer intercepted` and get rejected with 401. Use `${OPENAI_API_KEY:-intercepted}` shell default-expansion: the framework-injected secret wins when present, and the literal "intercepted" placeholder preserves the pre-auth path when build_env_vars declines to set the key (INTERCEPTION_SECRET unset or empty). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rnesses Both harnesses previously hardcoded the literal "intercepted" as the agent's OpenAI API key — a placeholder from when the interception proxy did no auth. After #1180, build_env_vars injects the real INTERCEPTION_SECRET as OPENAI_API_KEY; the hardcoded values clobbered it and every agent request hit the proxy with `Bearer intercepted` → 401. Use bash-style default expansion `${OPENAI_API_KEY:-intercepted}` in both the RLM run command and the opencode.json config. Preserves the pre-auth path when no secret is configured. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rnesses (#1213) Both harnesses previously hardcoded the literal "intercepted" as the agent's OpenAI API key — a placeholder from when the interception proxy did no auth. After #1180, build_env_vars injects the real INTERCEPTION_SECRET as OPENAI_API_KEY; the hardcoded values clobbered it and every agent request hit the proxy with `Bearer intercepted` → 401. Use bash-style default expansion `${OPENAI_API_KEY:-intercepted}` in both the RLM run command and the opencode.json config. Preserves the pre-auth path when no secret is configured. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>


Summary
InterceptionServeraccepts an optionalsecretparameter; when set, validates theAuthorization: Bearer <secret>header on every request usinghmac.compare_digest— auth check runs before rollout lookup to prevent ID enumerationCliAgentEnvreadsINTERCEPTION_SECRETfrom the host environment and injects it asOPENAI_API_KEYinto sandbox env vars, overriding any dummy value (e.g."intercepted")OPENAI_API_KEYadded toPROTECTED_ENV_VARSINTERCEPTION_SECRETtreated as unset in both server and env (consistent behaviour)CliAgentEnvis backward compatible: ifINTERCEPTION_SECRETis unset the server accepts all requests as beforeTest plan
INTERCEPTION_SECRET=<secret>and run a rollout end-to-end🤖 Generated with Claude Code
Note
Medium Risk
Adds authentication gating to the interception HTTP server and propagates the shared secret into sandbox env vars; misconfiguration could cause rollouts to fail with 401s or inadvertently run unauthenticated if the secret is unset/empty.
Overview
Adds optional request authentication to
InterceptionServer: whenINTERCEPTION_SECRETis set, every intercepted request must includeAuthorization: Bearer <secret>(constant-time compared) and unauthorized requests return401before rollout lookup.Updates
CliAgentEnvto readINTERCEPTION_SECRET, pass it intoInterceptionServer, and (when non-empty) inject it asOPENAI_API_KEYinto sandbox env vars while protectingOPENAI_API_KEYfrom being overridden by subclasses.Reviewed by Cursor Bugbot for commit f96ff0e. Bugbot is set up for automated code reviews on this repo. Configure here.