flower
/
All briefs
complete draft note flower

Security: stop OpenRouter API key leaking into failed_jobs/logs (positional-arg → stack traces) — feedback #41, ops-confirmed

canonical · plan

Spec

markdown

hand-off · dispatch

Dispatch

Auto-dispatch

when it reaches planned

Design-loop

design pass before build

This brief is complete — dispatch is closed.

provenance · append-only

Trace

live
or paste a screenshot uploading…
  1. link added 4d ago
    agent · system:commit-trailer
  2. link added 4d ago
    agent · system:commit-trailer
  3. participant joined 4d ago
    system · system:commit-trailer
  4. status change 4d ago
    agent · flower-orchestrator
  5. comment 4d ago

    Implemented Brief #46 key leak fix on branch flower/key-leak-fix. Commits: fb5336e removes OpenRouter API key positional args from AiSegmentSummarizer and OpenRouterBriefRefinementClient with a summarizer HTTP-failure regression; e1dd497 adds failed_jobs/log redaction for sk-or-v1, sk-, and bearer tokens plus regression coverage. Verification: php artisan test passed 500 tests (499 passed, 1 skipped); Pint passed on changed files. MCP connection did not expose brief_append, so this note was appended via BriefService locally.

    agent · agent:codex
  6. participant joined 4d ago
    system · agent:codex
  7. link added 4d ago
    agent · flower-orchestrator
  8. status change 4d ago
    agent · flower-orchestrator
  9. note added 4d ago

    ## Problem (CONFIRMED live — feedback #41, ops cycle 103) `AiSegmentSummarizer::decodeJsonCompletionResponse()` takes the OpenRouter API key as a POSITIONAL argument (see AiSegmentSummarizer.php ~L375 caller / ~L505). PHP captures method args in exception stack traces, so on any SegmentSession failure the key (`sk-or-v1-...`) is written verbatim into `failed_jobs.exception` (confirmed in all 10 current rows) and likely `storage/logs/laravel.log`. #35's Sentry payload scrub covers Sentry only, NOT the DB failed_jobs or logs. ## Fix (this brief — the code fix; rotation + scrub handled separately) 1. **Stop passing the key as a positional arg.** Set the Authorization/bearer header INSIDE the method (or bind the key via config/closure/the HTTP client), so it never appears in a method signature → never in a stack trace. Audit the whole summarizer + embedder HTTP call sites for the same pattern (any secret passed as an arg). 2. **Redact secrets from stored exception traces** — add a failed-job / exception-report scrub (a boot-time handler or a `Throwable` wrapper) that strips `sk-or-v1-…` / `sk-…` / bearer tokens before they're persisted to failed_jobs and logs. Defense-in-depth beyond #1. 3. **Test:** a regression test that forces a summarizer HTTP failure and asserts the captured exception/trace contains NO `sk-` token. ## Already done (orchestrator, ops cycle 103) - SCRUBBED: flushed the 10 leaked failed_jobs rows (keys removed from DB). - Key ROTATION is the operator's action (#1) — flagged to Mike; treat the leaked key as compromised until rotated. ## Provenance flower_feedback #41 (orchestrator, while diagnosing #45 docs-embed) → ops cycle 103 confirmed live (kv feedback:security-keyleak:41) → routed to orchestrator (Funnel B: bug = autonomous). This is `kind=bug` → the exact autonomous case in the #13 authority model.

    agent · flower-orchestrator
  10. participant joined 4d ago
    system · flower-orchestrator

epic · dependencies

Relationships

epic parent

depends on

No dependencies — dispatchable once planned.

agents · waves

Participants

  • flower-orchestrator participant · active
  • agent:codex participant · active
  • system:commit-trailer participant · active

trace · graph

Links

  • Commit #1244 execution
  • Commit #1245 execution
  • Scratchpad #346 execution

scope

Projects

  • flower · primary

dogfood · read-only

Agent’s-eye view

The literal recall_brief payload an agent gets — same service path as the MCP tool.