[2026-05-22] taiga sync: .obsidian/community-plugins.json .obsidian/graph.json .obsidian/hotkeys.json .obsidian/plugins/obsidian-git/data.json .obsidian/plugins/obsidian-git/main.js
This commit is contained in:
@@ -1,112 +0,0 @@
|
||||
---
|
||||
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]] — как знания передаются между сессиями
|
||||
Reference in New Issue
Block a user