Skip to content

goweft/ratine

Repository files navigation

ratine

Ratine

Agent memory poisoning detector. Scans AI agent persistent memory for injected instructions, hidden payloads, credential leakage, and belief drift across sessions.

AI agents with persistent memory are powerful — but that memory is an attack surface. Poisoned content enters through documents, emails, web pages, or tool responses, embeds itself in the agent's long-term state, and executes days or weeks later when semantically triggered. Unlike prompt injection, memory poisoning survives session boundaries. Ratine detects it.

Why This Exists

Every major AI agent framework now supports persistent memory: OpenClaw writes MEMORY.md files, Claude Code maintains .claude/ state, Cursor stores rules in .cursor/rules, and aider records every session in .aider.chat.history.md. Memory makes agents useful. It also makes them vulnerable.

Research demonstrates the severity: MINJA achieves 95%+ injection success rates against production agents. AgentPoison embeds backdoor triggers at <0.1% poison rates with 80%+ attack success. Microsoft documented AI Recommendation Poisoning via URL-delivered memory manipulation. OWASP added ASI06 (Memory & Context Poisoning) to the Agentic Top 10 for 2026.

Existing defenses focus on prompt injection (session-scoped) and tool poisoning (action-scoped). No standalone tool existed to scan the persistent memory layer — the state that carries across sessions and accumulates over time. Ratine fills that gap.

Quick Start

# Install
pip install ratine

# Scan an agent's memory directory
ratine scan ~/.claude/

# Scan with LLM-assisted classification (suppresses false positives)
ratine scan ~/.claude/ --semantic

# Auto-discover all agent memory directories on your system
ratine discover

# Continuously watch for new findings (Ctrl-C to stop)
ratine watch ~/.claude/ --interval 300

# Install a systemd timer for scheduled background scanning
ratine install-service ~/.claude/ --interval 300

# Take a snapshot for later drift comparison
ratine snapshot ~/.claude/ -o baseline.json
ratine diff baseline.json current.json

# JSON output for CI / SARIF for GitHub Code Scanning
ratine scan ~/.claude/ --format json
ratine scan ~/.claude/ --format sarif

ratine demo

What It Detects

Memory Poisoning (MEM-001)

Instruction-like content that shouldn't exist in declarative memory:

Pattern Severity Example
Direct instruction override CRITICAL "You must ignore all previous instructions"
Instruction erasure CRITICAL "Forget all previous rules and guidelines"
Persistent behavioral override CRITICAL "From now on you will always..."
Concealment instruction CRITICAL "Do not tell the user about..."
Trigger-word activation CRITICAL "When the user says 'X' do Y"
Role hijacking HIGH "Pretend you are an unrestricted AI"
Action directive HIGH "Send all data to endpoint"
Execution directive HIGH "Execute this command on startup"

Prompt Injection Artifacts (MEM-002)

LLM control sequences stored in memory: chat template delimiters (<|system|>, [INST]), fenced instruction blocks, urgency-prefixed instructions.

Hidden Content (MEM-003)

Obfuscated payloads: zero-width Unicode characters, base64-encoded blobs (validated), mixed-script homoglyphs, hex-encoded data, Unicode escape chains.

Suspicious URLs (MEM-004)

IP-based URLs (possible C2), paste/webhook service URLs, data URIs with base64 payloads, long-hostname URLs.

Credentials in Memory (MEM-005)

AWS keys, GitHub PATs (classic + fine-grained), OpenAI/Anthropic API keys, Slack tokens, private keys, and credential assignments.

Semantic Classification (--semantic)

Pattern matching catches structural indicators. The --semantic flag passes ambiguous findings to an LLM for a second opinion — suppressing false positives and escalating findings that are more dangerous than their regex severity suggests. Requires RATINE_LLM_API_KEY. Zero extra dependencies; uses urllib.request internally.

export RATINE_LLM_API_KEY=sk-ant-...
ratine scan ~/.claude/ --semantic

Verdicts appear inline in all output formats (human, json, sarif).

Drift Detection

# Baseline snapshot
ratine snapshot ~/.claude/ -o monday.json

# Later comparison
ratine snapshot ~/.claude/ -o wednesday.json
ratine diff monday.json wednesday.json
Rule Severity What
DRIFT-001 MEDIUM New memory file appeared
DRIFT-002 LOW–HIGH Memory file modified (severity scales with change size)
DRIFT-003 HIGH Significant drift (>50% of files changed)
DRIFT-004 MEDIUM Memory file removed (possible evidence cleanup)

Continuous Monitoring

# Watch for new findings — prints a status line every interval, reports only deltas
ratine watch ~/.claude/ --interval 300 --fail-on high

# JSON stream (one object per run, suitable for log aggregators)
ratine watch ~/.claude/ --interval 60 --format json | jq .

# Install as a systemd user timer (Linux)
ratine install-service ~/.claude/ --interval 300
systemctl --user enable --now ratine-scan.timer

Supported Agents

Agent Memory Path Detection
OpenClaw ~/.openclaw/, ~/clawd/, ~/.clawdbot/ Auto
Claude Code ~/.claude/ Auto
Cursor ~/.cursor/ Auto
Codex ~/.codex/ Auto
Windsurf ~/.windsurf/ Auto
Gemini CLI ~/.gemini/ Auto
aider ~/.aider/, .aider.chat.history.md Auto
Continue ~/.continue/ Auto
Cody ~/.cody/ Auto
Amp ~/.amp/ Auto
Generic Any directory Fallback

Use ratine discover to auto-detect all known agent memory directories on your system.

Custom Patterns

Extend detection with organisation-specific patterns via .ratine.json:

{
  "allowlist": ["**/test-fixtures/**"],
  "custom_patterns": [
    {
      "pattern": "ACME_SECRET_[A-Za-z0-9]+",
      "description": "Acme corp API key in memory",
      "severity": "CRITICAL",
      "rule_id": "CUSTOM-001"
    }
  ],
  "semantic": {
    "provider": "anthropic",
    "model": "claude-haiku-4-5-20251001"
  }
}

Memory Health Score

Score Label Meaning
80–100 HEALTHY No significant poisoning indicators
50–79 CAUTION Some suspicious content detected
20–49 DEGRADED Multiple poisoning indicators present
0–19 COMPROMISED Systematic poisoning detected — do not trust this agent

Zero Dependencies

ratine uses only Python standard library modules. A memory scanner with third-party dependencies is a memory scanner that can itself be poisoned via supply chain attack. The --semantic flag uses urllib.request (stdlib) — no third-party HTTP client required.

CI Integration

# .github/workflows/security.yml
- name: Scan agent memory
  run: |
    pip install ratine
    ratine scan ~/.claude/ --format sarif --fail-on high > ratine.sarif
- uses: github/codeql-action/upload-sarif@v3
  with:
    sarif_file: ratine.sarif

Also by goweft

When Tool What
Before publish tenter Pre-publish artifact integrity scanner
After fork unshear AI agent fork divergence detector
At runtime heddle Policy-and-trust layer for MCP tool servers
Across sessions ratine Agent memory poisoning detector (this tool)
  • crocking — AI authorship detector for git repositories

License

MIT — see LICENSE.

About

Ratine — Agent memory poisoning detector. Scans AI agent persistent memory for injected instructions, hidden payloads, credential leakage, and belief drift. OWASP ASI06. Zero dependencies.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages