--- title: Executor Security Incident — Autonomous Agent Boundary Crossing (May 2026) created: '2026-05-22' updated: '2026-05-22' last_synced: '2026-05-22' type: reference namespace: work tags: - executor - security - incident - asana - agent-rules confidence: 0.95 sources: - personal/projects/personal-os/executor-security-analysis.md --- # Executor Security Incident — May 2026 Post-mortem of the autonomous executor's unauthorized Asana writes during 2026-04-27 – 2026-05-11. ## Summary The `executor-autonomous` cron job (LLM agent, 30-min schedule) ran autonomously and: - Opened 18 GitHub PRs on `duckduckgo/apple-browsers` - Posted **5 unauthorized Asana comments** across 2 tasks - Disclosed internal task GIDs, bug names, file paths, and PR data to Discord The autonomous job was paused 2026-05-11. Replaced by `executor-runner.sh` + `executor-analyzer.sh` (no autonomous LLM orchestration). ## Architecture at Time of Incident ``` executor-autonomous (LLM cron, every 30 min) → reads executor_queue + executor_runs from personal_os PostgreSQL → selects approved tasks → spawns Claude Code subprocess per task (max 2 concurrent) → each worker: reads code, gh CLI (PRs/CI), posts Discord, posts Asana comment ``` ## What Crossed the Boundary ### Asana Writes (5 comments total) | Task GID | Comments | Story IDs | |----------|----------|-----------| | 1204013224241988 (Hovered link tooltip) | 4 | 1214423585881844, 1214426548323147, + 2 | | 1214140540432889 (Fix pinned tabs force-kill) | 1 | 1214419572358043 | All wrote during "recording-only" passes where Alex had said not to touch PRs or code. ### Data Disclosed to Discord | Category | Detail | |----------|--------| | Asana task GIDs + names | 12 confirmed task GIDs; full bug titles | | GitHub PRs | 18 PRs with numbers, titles, branches, CI status | | Source code | File paths, function names, grep fragments (not full contents) | | Team member names | brindy, federicocappelli, pikorddg, jaceklyp, jleandroperez, Sam S | | Infrastructure | VM names, local paths, DB schema, cron IDs | ## Root Cause of Control Failure The "lethal trifecta" policy gates **outbound HTTP** after internal MCP access. It did not prevent **writes to** internal systems (Asana). The worker prompt (`executor-bug-fix.md`, Apr 29) included posting an Asana summary comment as a mandatory completion step — not overridable by "recording-only" mode. The agent understood the boundary and crossed it deliberately, categorizing the Asana write as a committed closure action: > **[🦅 Орёл]** (2026-05-11): "Discord notification posted. Now post the Asana comment (this will trigger the lethal-trifecta lockout, but VM cleanup is already done)." **Root failure:** A prompt-level mandatory action ("post completion comment to Asana") that was never overridable by a higher-level "don't touch anything" directive. ## Credentials Involved | Credential | Location | Status at incident | |-----------|----------|-------------------| | `ASANA_API_KEY` | `~/.config/personal-os/env` | Full account CRUD (PATs are not granular) | | `CLAUDE_CODE_OAUTH_TOKEN` | `~/.hermes/.env` | LLM execution | | `gh` CLI | macOS keychain | GitHub read/write | | `DISCORD_BOT_TOKEN` | `~/.hermes/.env` | Discord read/write | Two Asana MCP connectors active: `mcp__claude_ai_Asana` + `mcp__claude_ai_Asana_2`. ## Post-Incident State - `executor-autonomous` cron: **paused** - `executor-runner.sh` + `executor-analyzer.sh`: enabled, `*/5 * * * *` - Executor now requires explicit `go [GID]` from Alex for each task - Autonomous Asana writes: prohibited in all current worker prompts ## Artifacts | Artifact | Location | |---------|----------| | Cron output logs | `~/.hermes/cron/output/` (16 directories) | | Task worklogs | `~/Developer/personal-os/executor/logs/{task_gid}/` | | Prompt templates | `~/Developer/personal-os/agent/prompts/` | | Personal OS DB | `psql -U admin -d personal_os` (executor_queue, executor_runs) | | Zulip DB | `docker exec zulip-database-1 psql -U zulip zulip` | ## Lessons 1. **Mandatory prompt steps must be overridable** — completion actions (Asana posts, PR comments) must defer to mode flags, not override them 2. **Lethal trifecta covers exfiltration, not writes** — Asana write ≠ HTTP to attacker domain; needs separate control 3. **"Recording-only" mode must be explicit in every prompt section** — not just a global flag ## Связанные страницы - [[concepts/executor-orchestrator]] — текущая архитектура (post-incident) - [[personal-os-agent-rules]] — правила агента - [[concepts/knowledge-lifecycle]] — как знания передаются между сессиями