flower
/
All feedback
Bug planned #41 routed · orchestrator

OpenRouter API key leaks into failed_jobs stack traces (AiSegmentSummarizer passes key as a method arg)

flower-orchestrator · submitted 4 days ago

detail

What they reported

A SegmentSession failure stores the full exception stack trace in failed_jobs.exception, and AiSegmentSummarizer::decodeJsonCompletionResponse receives the API key as a positional argument (sk-or-v1-...), so the key appears verbatim in every captured stack trace (failed_jobs, and potentially logs). #35 added Sentry payload scrubbing, but the DB failed_jobs.exception column and laravel.log are not scrubbed. Fix: don't pass the key as a method arg (inject via the client/config, or wrap so it's not in the signature), and/or scrub secrets from stored exception traces. Also consider purging existing failed_jobs rows that contain the key. Found while diagnosing docs-embed failures 2026-07-01.

context

Structured context

{
    "routed": {
        "target": "orchestrator",
        "todo_id": 381,
        "authority": "autonomous",
        "routed_at": "2026-07-03T13:19:16+00:00",
        "routed_by": "operator:mike",
        "project_id": 16,
        "solo_todo_id": "701",
        "solo_project_id": "49",
        "coordination_queue": {
            "kind": "route_feedback",
            "drain": "orchestrator_recall_signals",
            "status": "pending",
            "latency": "<= one orchestrator heartbeat",
            "signal_id": 16
        },
        "default_project_id": 16,
        "coordination_signal_id": 16,
        "fix_spec_scratchpad_id": 372,
        "orchestrator_daemon_id": 12,
        "solo_fix_spec_scratchpad_id": "1063",
        "orchestrator_solo_process_id": 1015
    },
    "promotion_ledger": [
        {
            "at": "2026-07-03T13:19:16+00:00",
            "action": "orchestrator_routed",
            "target": "orchestrator",
            "todo_id": 381,
            "actor_ref": "operator:mike",
            "cycle_key": "2026070313",
            "fix_spec_scratchpad_id": 372
        }
    ]
}

state · operator override

Lifecycle

created
4d ago
triaged
4d ago
resolved
resolved by
flower-ops

resolution
CONFIRMED LIVE SECURITY LEAK: OpenRouter key present in ALL 10 failed_jobs.exception stack traces (verified by count, key not printed). Root: key passed as positional arg to AiSegmentSummarizer::decodeJsonCompletionResponse → captured in every trace. 969-filed + owns code fix (#35 added Sentry-payload scrub; failed_jobs/logs still leak). Mitigations flagged to 969 + operator: (1) ROTATE key, (2) scrub/flush leaked rows, (3) stop passing key as positional arg. HIGH severity.

Delete permanently?