memlineage v0.1.0: defensa de dos capas contra memory poisoning en agentes LLM
Un agente con memoria persistente puede ser envenenado por un adversario que solo interactúa por canales normales. Presentamos una defensa de dos capas (provenancia criptográfica + detección por comportamiento) en Python, verificada por auditoría independiente y CI.
El problema
Los agentes con memoria persistente (RAG / agentic memory) introducen una superficie de ataque nueva: un adversario que interactúa solo a través de canales normales puede inyectar memorias diseñadas que, al ser recuperadas, desvían el comportamiento futuro del agente — sin tocar pesos del modelo ni código.
El trabajo académico reciente lo confirma de forma reproducible:
- SMSR (2026) — memoria envenenada vía interacción normal.
- TMA-NM (2026) — los defensas basadas en trust score por origen son maleables por laundering (un contenido externo se “lava” a confiable mediante resumen o eco del propio agente).
- MemLineage (2025) — linaje criptográfico con propagación max-of-strong-edges.
- Forensic Trajectory Signatures (2026) — la exfiltración deja una firma conductual distribuida en la secuencia de tool-calls, que sobrevive ataques que optimizan el texto para evadir filtros.
La conclusión común: los filtros basados en contenido son evadidos por texto empresarial fluido, y los trust score son maleables. Hace falta origen criptográfico y detección por comportamiento.
La solución: dos capas, construidas juntas
Capa A — Provenancia + linaje (write-time, criptográfica, hard gate)
- Cada memoria se firma con Ed25519 en write-time, atada al principal real que la originó. El nivel de confianza (tier) se deriva de la clave que firma, nunca lo elige el llamador.
- Un
KeyRegistryvincula cada principal a su propia clave.register()solo se permite en la inicialización de confianza;freeze()bloquea el registro en runtime para que la lógica del agente no pueda auto-registrarse como principal interno. - Un grafo de derivación con propagación max-of-strong-edges impone Untrusted-Path Persistence: una memoria derivada (aun transitivamente) de un ancestro externo/no confiable nunca se lava a confiable.
- Un
SensitiveActionGatebloquea (FPR ≈ 0, criptográfico) cualquier acción irreversible cuya justificación descienda de un ancestro en camino no confiable.
Capa B — Detector de trayectoria (runtime, conductual, soft alert)
- Detecta desde la estructura de tool-calls, no del contenido (Forensic Trajectory Signatures).
- 19 features estructurales; una regla de invariante recall → acción sensible (sin entrenar) más un RandomForest entrenable.
- Solo alerta en el MVP (nunca auto-bloquea) hasta medir su tasa de falsos positivos — sin OR ciego con la Capa A.
Resultados (auditados de forma independiente)
Un auditor externo clonó el repo desde cero, instaló, y escribió sus propias pruebas adversariales (no las del repo) para verificar las garantías. Métricas reales:
Garantía Resultado Spoof de principal sin su clave Rechazado (PermissionError) Laundering transitivo (5 niveles) Nodo sigueuntrusted, gate bloquea
Mezcla confiable + no confiable en una justificación
Bloquea (basta una no confiable)
RegistryFrozenError tras freeze()
Bloquea registro en runtime
Firma reciclada de memoria legítima a maliciosa
Rechazada (atada a entry_id+contenido+source)
ASR de ataque externo real (Capa A)
0.000
AUC Capa B (sin camuflaje)
0.988
AUC Capa B (con camuflaje del atacante)
0.978, Recall 0.950
El benchmark usa ataques por paráfrasis semántica (no frases regex literales) con generación estocástica de trayectorias y solapamiento de clases, y reporta media ± desviación sobre varias semillas. El camuflaje degrada el AUC y el Recall de forma medible — el benchmark mide generalización, no memorización de plantillas.
Limitación declarada: el ataque de Capa B es una aproximación local de MINJA (paráfrasis + heurística de recall), no el optimizador white-box publicado. El AUC mide robustez contra este ataque, no contra MINJA completo.
Calidad verificada
- CI (GitHub Actions, py3.11/3.12): 30/30 tests, cobertura 95%, bandit SARIF 0 resultados.
- SonarCloud: Quality Gate OK, 0 issues abiertos.
- GitHub Code Scanning: 0 alertas abiertas.
- Licencia AGPL-3.0-or-later.
Pruébalo
git clone https://github.com/amurlaniakea/memlineage.git
cd memlineage
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest -q
python -c "from memlineage.benchmark import run_seeds; print(run_seeds())"
Enter fullscreen mode Exit fullscreen mode
Stack
Componente Tecnología Criptografía Ed25519 (cryptography)
Linaje
networkx (DAG, max-of-strong-edges)
Detector
scikit-learn RandomForest + regla de invariante
CI
GitHub Actions + SonarCloud + Code Scanning
Referencias
- SMSR (2026) — SMSR: memory poisoning en agentes
- TMA-NM (2026) — trust-score laundering
- Forensic Trajectory Signatures (2026)
- MemLineage (2025) — linaje criptográfico
- MemAudit (2025) — auditoría post-hoc de memoria
Links
¿Dónde encaja esto en tu stack de agentes? Comentarios abiertos.
Licencia: AGPL-3.0-or-later. Autor: Pedro Sordo Martínez.
답글 남기기