memlineage v0.1.0: defensa de dos capas contra memory poisoning en agentes LLM

작성자

카테고리:

← 피드로
DEV Community · Fenix · 2026-07-15 개발(SW)
Cover image for memlineage v0.1.0: defensa de dos capas contra memory poisoning en agentes LLM

Fenix

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 KeyRegistry vincula 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 SensitiveActionGate bloquea (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 sigue untrusted, 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

Links

¿Dónde encaja esto en tu stack de agentes? Comentarios abiertos.

Licencia: AGPL-3.0-or-later. Autor: Pedro Sordo Martínez.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다