T02 · Agent Memory Poisoning
Error
- Location
- SKILL.md:445
- Finding
- Untrusted Lessons Can Be Promoted into Persistent Agent Instructions<![CDATA[ ## Vulnerability Details **File Locations**: - `SKILL.md:27-30` - `SKILL.md:85-96` - `SKILL.md:352-368` - `SKILL.md:445-447` - `hooks/openclaw/handler.js:12-24, 45-50` - `hooks/openclaw/handler.ts:11-25, 53-59` - `references/openclaw-integration.md:128-145` **Vulnerability Type**: Persistent agent-memory poisoning **Risk Level**: High ### Vulnerable Code and Instructions `SKILL.md:27-30` recommends promoting captured lessons into persistent agent instruction files: ```markdown | Broadly applicable learning | Promote to `CLAUDE.md`, `AGENTS.md`, and/or `.github/copilot-instructions.md` | | Workflow improvements | Promote to `AGENTS.md` (OpenClaw workspace) | | Tool gotchas | Promote to `TOOLS.md` (OpenClaw workspace) | | Behavioral patterns | Promote to `SOUL.md` (OpenClaw workspace) | ``` `SKILL.md:445-447` explicitly encourages aggressive promotion: ```markdown 5. **Suggest concrete fixes** - not just "investigate" 6. **Use consistent categories** - enables filtering 7. **Promote aggressively** - if in doubt, add to CLAUDE.md or .github/copilot-instructions.md 8. **Review regularly** - stale learnings lose value ``` `hooks/openclaw/handler.js:12-24` injects the promotion reminder into agent bootstrap context: ```javascript After completing tasks, evaluate if any learnings should be captured: **Log when:** - User corrects you → \`.learnings/LEARNINGS.md\` - Command/operation fails → \`.learnings/ERRORS.md\` - User wants missing capability → \`.learnings/FEATURE_REQUESTS.md\` - You discover your knowledge was wrong → \`.learnings/LEARNINGS.md\` - You find a better approach → \`.learnings/LEARNINGS.md\` **Promote when pattern is proven:** - Behavioral patterns → \`SOUL.md\` - Workflow improvements → \`AGENTS.md\` - Tool gotchas → \`TOOLS.md\` ``` `hooks/openclaw/handler.js:45-50` places that reminder in the files loaded during bootstrap: ```javascript if (Array.isArray(event.context.bootstrapFiles)) { event.context.bootstrapFiles.push({ ...[truncated 3576 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Require explicit human approval** - Never automatically promote content derived from users, tools, APIs, logs, or other sessions. - Present the exact proposed diff and require affirmative approval before modifying any persistent instruction file. 2. **Introduce source provenance and trust levels** - Record the original source, session, timestamp, and trust classification for every lesson. - Mark user input, command output, external responses, and cross-session messages as untrusted by default. - Prevent untrusted entries from becoming agent instructions without independent verification. 3. **Store observations as data rather than directives** - Quote original content and clearly delimit it as untrusted evidence. - Do not copy imperative phrases directly into `CLAUDE.md`, `AGENTS.md`, `SOUL.md`, `TOOLS.md`, or similar files. - Convert verified observations into narrowly scoped factual statements. 4. **Apply a strict promotion schema** - Allow only predefined fields such as affected component, verified behavior, reproduction steps, and evidence. - Reject or flag content containing tool commands, URLs, requests for secrets, behavioral overrides, credential instructions, or changes to safety constraints. 5. **Replace aggressive promotion guidance** - Remove “Promote aggressively” and “if in doubt” language. - Require reproducible evidence, independent confirmation, and a documented security review before promotion. 6. **Do not treat repetition as proof** - Deduplicate by source and session. - Require confirmation from trusted project documentation, tests, or a human maintainer rather than relying only on recurrence count. 7. **Separate memory from executable agent policy** - Keep `.learnings/` as an informational archive that is not interpreted as authoritative instruction context. - Maintain persistent agent policy files under stricter ownership and review controls. 8. **A ...[truncated 531 chars]
