T02 · Agent Memory Poisoning
- Location
SKILL.md:95- Finding
Persistent Agent Memory Is Injected into Future Sessions Without a Trust Boundary
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a coherent local memory service, but it asks users to run persistent, mutable agent memory infrastructure with weak scoping and security guidance.
Install only if you intentionally want long-lived local agent memory. Before use, pin the package or container version, bind the service to 127.0.0.1, add authentication or network isolation, avoid storing secrets or regulated data, review any migration or ingestion input, and treat recalled memories as untrusted notes rather than instructions for the agent to follow.
SKILL.md:95Persistent Agent Memory Is Injected into Future Sessions Without a Trust Boundary
SKILL.md:29Documented Deployment Can Expose a Mutable Memory API Without Authentication
SKILL.md:8Installation Instructions Use Unpinned Executable Dependencies and a Mutable Container Tag
references/openclaw-setup.md:9Always-Restarting Service Configuration Creates Cross-Session Persistence Without Hardening
The description is broad enough to trigger on many generic requests about memory, learning, recall, or long-term context, increasing the chance the skill is invoked in contexts where persistent storage is not appropriate. Over-broad activation is dangerous here because the skill is explicitly designed to store and later reinject prior task data into prompts.
The skill promotes storing experiences, facts, and skills persistently, but the warning language does not clearly emphasize that task data, agent-generated content, and potentially sensitive workspace-derived information will be written to disk and reused later. Users may unknowingly persist secrets, proprietary code details, or personal data beyond the current session.
The skill instructs users to pull a Docker image using the mutable latest tag, which prevents reproducible builds and allows upstream image changes to silently alter what gets executed later. If the registry account or tag is compromised, users may run an unexpected or malicious image without noticing.
The docker run example executes the same unpinned image reference, so runtime behavior depends on whatever image the mutable tag resolves to at that moment. This creates supply-chain risk and weakens auditability and rollback safety.
The quick-reference 'Write Memory' guidance normalizes persistent storage of task-derived information without surrounding boundaries on what should not be retained. In a skill centered on memory, this increases the likelihood of indiscriminate retention of sensitive session content across runs.
curl -X POST http://localhost:9100/memory/episodic \
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
curl -X POST http://localhost:9100/memory/episodic \
-H "Content-Type: application/json" \
-d '{
"type": "experience",
The session-boot recall pattern instructs agents to fetch prior memories and inject them directly into prompts, which can cause sensitive or stale information to be reintroduced into unrelated future tasks. Without minimization, scoping, or sensitivity filtering, this creates cross-task data leakage and prompt-context contamination risks.
The guidance to log learnings after tasks and migrate existing workspace memory encourages broad retention of historical inputs and logs into a persistent store, potentially sweeping in secrets, credentials, proprietary information, or personal data. Because the skill is for long-term memory, overcollection here materially increases privacy and data-governance exposure.
Adding a workspace boot script that automatically recalls and prints stored context at every session start creates persistent cross-session state injection without strong user review. This can surface sensitive historical data in new sessions and cause the agent to act on stale, over-broad, or attacker-planted memories.
Add a boot script to your workspace (see references/openclaw-setup.md for a full example):
# boot_aoms.py — call at session start
The API reference encourages persistent storage and retrieval of free-form memory content, including experiences, titles, outcomes, and tags, without any warning about storing sensitive, personal, or secret data. In a long-term agent memory system, users may unknowingly persist credentials, proprietary context, or regulated data, increasing confidentiality and compliance risk over time.
The documented GET /memory/browse/{path} endpoint exposes arbitrary module-tree browsing and file content access, which is outside the core memory-service purpose and creates a strong risk of local file disclosure. In an agent-integrated service, this is especially dangerous because agents may be induced to read secrets, source files, tokens, or other sensitive local data through a seemingly legitimate memory API.
The document ingestion and entity extraction endpoints accept full document text and optionally store extracted relations, but the documentation does not warn that sensitive content may be transmitted to the service and retained or processed by external components such as Ollama. Because these endpoints are designed for broad contextual ingestion, they increase the chance of bulk exposure of confidential documents and metadata.
The setup instructs users to automatically run a boot script every session that retrieves persistent memory context and displays it to the agent/operator. In an agent setting, this creates durable cross-session context injection and may reintroduce stale, sensitive, or adversarially planted content into future sessions without fresh validation.
Create a boot script in your workspace:
# boot_aoms.py
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.
import httpx, sys
try:
r = httpx.post("http://localhost:9100/recall", json={
"task": "session boot — what's recent and relevant",
"token_budget": 300,
"format": "markdown"
No suspicious patterns detected.