Workspace agentId scoping + role-marker stripping in injected files
2026-05-07
What We Built
Two compound findings. (1) IDOR: agentId query param on /workspace/files endpoints accepted from request without validation against authenticated caller — any tenant API key could read/write/delete ANY agent's files in that tenant, including SOUL.md. (2) Prompt-injection: workspace files concatenated into system prompt without sanitization. Compounds with #1 — attacker writing to another agent's SOUL.md could inject role-override instructions.
Why It Matters
IDOR was within-tenant privilege escalation; prompt-injection turned it into system-prompt override. Fixed: derive agentId from authenticated \_agentIdentity OR require admin/operator scope; new stripRoleMarkers() utility deny-lists [SYSTEM]/[ASSISTANT]/[USER]/[INSTRUCTION], ChatML markers, Anthropic Human:/Assistant:, OpenAI developer:/system:, ### INSTRUCTION/SYSTEM headers.
How It Works
9 IDOR regression tests + 4 sanitization tests + 10 unit tests on prompt-sanitizer.ts. Backward-compat preserved: callers omitting agentId or passing their own continue to work.
Lockstep Checklist
- [x] No API route changes (middleware/internal — lockstep N/A)
- [x] No SDK changes
- [x] No MCP tool changes
- [x] Regression test included (test-first invariant per /quality-fleet protocol)
- [x] Linked to /quality-fleet R1 dashboard at
.quality/dashboard.md
Provenance
Auto-found by /quality-fleet R1 (2026-05-07) scanner round, fixed in fix-agent batch under "go for all of it" autonomy grant. PR #208 merged to main as commit 1c1b5acef. Finding(s) tracked at .quality/findings.jsonl (entries: "7c4b2a9e5f81", "5b9f2d1e4c78"). Production-deployed via ECS task-def revision 732 series.