Repository navigation
fix(staging): run injection-guard only for native runtime so Scout can answer (D20) - #3079
Conversation
…n answer (D20) The 2026-10-31 Scout-staging incident had two causes. PR #3077 fixed the first (litellm was not deployed in commonly-staging, so native turns 401'd on a missing backend). This fixes the second: with litellm up, Scout turns still failed with `llm_error` "Model deepseek-v4-flash: HTTP 401" — litellm's logs show a 401 from https://api.openai.com/v1/moderations. The native runtime's default guardrail pair includes openai-moderation-enforce, which calls OpenAI's moderation API with OPENAI_API_KEY; staging's openai-api-key is an 11-byte placeholder, so that guardrail rejected every native turn before its model call. Prod (values-dev.yaml) already carries `nativeRuntimeGuardrails: "injection-guard"` for exactly this reason (its OpenAI key was the literal "placeholder"). Staging was simply missing the override — the same omission class as the missing litellm stanza. injection-guard is LiteLLM-native (no key, no external service) and keeps the prompt-injection block for untrusted input. No template change (the env is already values-driven); prod render is unchanged. Guard test asserts staging runs injection-guard only and stays in lockstep with prod. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4VWLErW29t4LnhRfUy1NH
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Configure and verify the staging guardrail k8s/helm/commonly/values-staging.yaml, backend/__tests__/unit/helm/litellmStagingEnabled.test.js |
Staging sets nativeRuntimeGuardrails to injection-guard. The unit test checks this value and verifies that it matches dev. |
Estimated code review effort: 2 (Simple) | ~8 minutes
Change: Bug fix
Possibly related issues
- Issue 541 addresses scoped prompt-injection guardrails. This change configures staging to use
injection-guard.
Possibly related PRs
- Team-Commonly/commonly#3077: This PR changes the staging LiteLLM deployment and guard test, which are also part of the staging native-runtime path.
- Team-Commonly/commonly#2748: This PR changes LiteLLM guardrail-check key selection; this change configures which guardrail runs in staging.
Merge Risk: 
Minimal · up to fa459
-
The staging guardrail configuration is consistent with the intended native-runtime behavior and introduces no actionable merge risk.
Pre-merge checks: 
4
-
Full details: Title check
-
Explanation
The title names the staging change, the injection-guard scope, and the Scout fix, which match the changeset. It is a short, single sentence and does not use vague terms. It is specific enough that a teammate scanning history understands the primary change.
Full details: Description check
-
Explanation
The description explains the incident, the placeholder OpenAI key that caused 401s from the openai-moderation-enforce guardrail, and the staging-only fix that sets nativeRuntimeGuardrails to injection-guard. It also covers prod parity and the guard test. It is directly related to the changeset.
-
Finishing Touches
-
Generate docstrings
-
- Commit to this branch
- Create a new PR
Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
|
Writer's-subagent review (D218, medium): done. It verified the mechanism end-to-end — Two findings, both latent/pre-existing and deliberately not folded into this targeted P0 fix:
Both tracked as SRE follow-ups. This PR stays minimal: one values line (prod parity) + a guard test. GATE: PASS |
lilyshen0722
left a comment
There was a problem hiding this comment.
Writer's-subagent review (D218, medium): done — mechanism verified end-to-end (nativeRuntimeGuardrails → NATIVE_RUNTIME_GUARDRAILS → nativeRuntimeService.ts:115; injection-guard exists in litellm-config; prod carries the identical override; YAML parses; assertions hold). One values line (prod parity) + a guard test. Two findings deferred as pre-existing/broader-scope (documented in the PR comment and tracked as SRE follow-ups): flip the service default to injection-guard (code, all envs), and the empty-string Helm off-switch guard. Neither is a defect in this change.
GATE: PASS
Second half of the 2026-10-31 Scout-staging incident
Sam: "is scout not working? I saw it not responding in staging." (D20)
Two causes, two fixes. PR #3077 (merged) fixed the first — litellm was not deployed in
commonly-staging, so native-runtime turns 401'd on a missing backend. After it deployed, litellm came up healthy (2/2 on default-pool) but Scout turns still failed:The native runtime's default guardrail pair (
nativeRuntimeService.ts) includesopenai-moderation-enforce, which calls OpenAI's moderation API withOPENAI_API_KEY. Staging'sapi-keys.openai-api-keyis an 11-byte placeholder, so that guardrail returned 401 on every native turn, before the model call.Fix — prod parity
Prod (
values-dev.yaml:131) already setsbackend.env.nativeRuntimeGuardrails: "injection-guard"for exactly this reason (its OpenAI key was the literal"placeholder"; the comment there notes it was "the probable cause of the native fleet's 98% July failure rate"). Staging was simply missing the override — the same omission class as the missing litellm stanza in #3077.injection-guardis LiteLLM-native (no key, no external service) and keeps the prompt-injection block for untrusted input. Restore the pair only after a real OpenAI moderation key lands in the stagingapi-keyssecret.Scope / safety
backend.env+ a guard test. No template change — the env is already values-driven (backend-deployment.yaml:654).values-dev.yamlalready carries the identical value; this PR does not touch it.deepseek-api-keyin staging is real (35 bytes), so the model call succeeds once the guardrail is out of the path — verified before shipping.injection-guardonly and stays in lockstep with prod.🤖 Generated with Claude Code
https://claude.ai/code/session_01N4VWLErW29t4LnhRfUy1NH