memshield
A drop-in Python library that wraps any vector store to provide two things simultaneously:
- Memory poisoning defense — validates every retrieved chunk before it reaches your LLM, blocking injected instructions disguised as knowledge
- EU AI Act Article 12 audit logging — per-inference tamper-evident records of what your AI retrieved, with RFC 3161 timestamps, Ed25519 signatures, and GDPR crypto-shredding
One line of code. Same interface as your existing store.
store = shield.wrap(your_chroma_or_pinecone_store)
docs = store.similarity_search("what medication is the patient on?")
# poisoned entries blocked; Article 12 audit record written automatically
Why this exists
Security: Memory poisoning corrupts agent behavior permanently. Unlike prompt injection (attacker must be present each session), a poisoned vector store entry affects every future query across all users. Red-teaming tools find the vulnerability — MemShield blocks it at runtime.
Compliance: EU AI Act Article 12 (enforceable August 2026) requires high-risk AI systems to automatically generate tamper-evident logs of what data was retrieved at inference time, retained for at least 6 months. No RAG framework produces this natively.
Both problems share the same interception point: the retrieval layer.
Install
pip install memshield # core (no deps)
pip install memshield[openai] # OpenAI/Ollama provider
pip install memshield[audit] # Article 12 audit log (requires cryptography + rfc3161ng)
pip install memshield[audit,openai] # both
pip install memshield[all] # everything
Quick start
Poisoning defense only
from memshield import MemShield
from memshield.strategies import KeywordHeuristicStrategy, ConsensusStrategy, EnsembleStrategy
from memshield.adapters.openai_provider import OpenAIProvider
shield = MemShield(
strategy=EnsembleStrategy([
KeywordHeuristicStrategy(),
ConsensusStrategy(OpenAIProvider(model="gpt-4o-mini")),
])
)
store = shield.wrap(your_vectorstore)
docs = store.similarity_search("company refund policy")
# poisoned entries are blocked; clean entries pass through unchanged
With Article 12 audit logging
from memshield import MemShield, AuditConfig
from memshield.strategies import EnsembleStrategy, KeywordHeuristicStrategy, ConsensusStrategy
from memshield.adapters.openai_provider import OpenAIProvider
shield = MemShield(
strategy=EnsembleStrategy([
KeywordHeuristicStrategy(),
ConsensusStrategy(OpenAIProvider()),
]),
audit=AuditConfig(
store="./audit.db",
knowledge_base_id="kb_prod_v3",
pii_fields=["query", "content"], # AES-256-GCM encrypted at rest
key_store="./keys.db",
tsa_url="https://timestamp.sectigo.com", # RFC 3161, free, no account needed
),
)
store = shield.wrap(your_vectorstore)
docs = store.similarity_search(
"what medication is the patient on?",
user_id="u_123",
inference_id="req_xyz", # optional — correlate with your own request logs
)
record = shield.audit_log.last_record()
print(record.inference_id) # req_xyz
print(record.chain_hash) # sha256:8b3e...
print(record.timestamp_rfc3161) # base64-encoded TSA proof from Sectigo
GDPR right-to-erasure
# Deletes the user's encryption key. Ciphertext becomes permanently unreadable.
# Chain hashes, timestamps, and doc IDs remain intact for audit continuity.
shield.audit_log.erase_user(user_id="u_123")
Audit log schema
Every inference produces one record, aligned to ISO/IEC DIS 24970:2025:
{
"inference_id": "req_xyz",
"timestamp_iso": "2026-03-10T09:00:00.000Z",
"timestamp_rfc3161": "<base64 DER token from Sectigo TSA>",
"key_id": "<sha256 fingerprint of Ed25519 signing key>",
"user_id": "u_123",
"query_hash": "sha256:a3f8...",
"query_encrypted": "<aes-256-gcm ciphertext>",
"knowledge_base_id": "kb_prod_v3",
"retrieved": [
{
"doc_id": "doc_456", "chunk_index": 3,
"content_hash": "sha256:c9d2...", "content_encrypted": "<aes-256-gcm ciphertext>",
"score": 0.94, "verdict": "clean", "trust_level": "verified"
}
],
"blocked": [
{
"content_hash": "sha256:f1a9...", "content_encrypted": "<aes-256-gcm ciphertext>",
"verdict": "poisoned", "confidence": 0.97, "attack_type": "T1_instruction_override"
}
],
"chain_hash": "sha256:8b3e...",
"previous_chain_hash": "sha256:2d7a...",
"signature": "ed25519:...",
"iso24970_event_type": "retrieval",
"iso24970_schema_version": "DIS-2025"
}
Tamper evidence: append-only SQLite (WAL mode), SHA-256 hash chain, Ed25519 signature per record, RFC 3161 timestamp token. Expired records (default 180-day retention) are replaced with tombstones that preserve chain continuity.
CLI
memshield audit verify --db ./audit.db
memshield audit export --db ./audit.db --from 2026-01-01 --format jsonl
memshield audit inspect --db ./audit.db --inference-id req_xyz
memshield audit erase-user --db ./audit.db --key-store ./keys.db \
--user-id u_123 --knowledge-base-id kb_prod_v3
memshield keys rotate --key-file ./memshield.key
MCP server
Any MCP-compatible agent (Claude Code, Cursor) can use MemShield with one config entry:
{
"mcpServers": {
"memshield": {
"command": "memshield",
"args": ["mcp", "--audit-db", "./audit.db"]
}
}
}
Tools exposed: audit_inspect(inference_id), audit_verify(), audit_export(from_date?).
Supported vector stores
| Store | How to use |
|---|---|
| Chroma | shield.wrap(chroma_collection) |
| LangChain vectorstores | shield.wrap(langchain_vectorstore) |
| LlamaIndex retrievers | LlamaIndexRetrieverAdapter(retriever) then shield.wrap(...) |
| Pinecone | PineconeStoreAdapter(index, embed_fn) then shield.wrap(...) |
| pgvector | PgVectorStoreAdapter(conn, embed_fn) then shield.wrap(...) |
| Qdrant | QdrantStoreAdapter(client, collection, embed_fn) then shield.wrap(...) |
Validation strategies
from memshield.strategies import KeywordHeuristicStrategy, ConsensusStrategy, EnsembleStrategy
# Instant, zero-cost — catches obvious injection patterns
KeywordHeuristicStrategy()
# LLM-based consensus (A-MemGuard approach) — catches subtle attacks
ConsensusStrategy(OpenAIProvider(model="gpt-4o-mini"))
# Ensemble — flag if either detects poisoning (maximum recall)
EnsembleStrategy([KeywordHeuristicStrategy(), ConsensusStrategy(provider)], mode="any_poisoned")
# Ensemble — majority vote (balanced precision/recall)
EnsembleStrategy([KeywordHeuristicStrategy(), ConsensusStrategy(provider)], mode="majority")
Benchmark
memshield-bench — 1,178 labeled entries across 10 attack types, including AgentPoison (NeurIPS 2024) data:
| Strategy | Precision | Recall | F1 |
|---|---|---|---|
| Keyword heuristic | 100% | 14.5% | 25.4% |
| LLM consensus | 97.1% | 98.6% | 97.8% |
| Ensemble (majority) | 100% | 100% | 100% |
| Ensemble (any_poisoned) | 94.5% | 100% | 97.2% |
Keyword heuristic catches 0% of AgentPoison attacks — sophisticated attacks are disguised as reasoning traces with no obvious instruction patterns. LLM consensus is required.
Configuration
from memshield import ShieldConfig, FailurePolicy
config = ShieldConfig(
confidence_threshold=0.7,
failure_policy=FailurePolicy.BLOCK, # or ALLOW_WITH_WARNING, ALLOW_WITH_REVIEW
enable_provenance=True,
enable_drift_detection=True,
)
shield = MemShield(strategy=..., config=config)
What MemShield is not
- Not a full EU AI Act compliance solution. Article 12 logging covers what was retrieved. It does not produce Annex IV technical documentation or Article 9 risk management plans. For complete Article 12 coverage pair with an LLM observability tool (Langfuse, Helicone).
- Not a managed service. Self-hosted only.
- Not a TypeScript library. Python only.
Alternatives
Most AI security products operate at the prompt/response boundary. MemShield operates at the retrieval layer — where poisoning actually happens.
Closest alternatives: NVIDIA NeMo Guardrails (retrieval rails, broader scope), Daxa (pre-vectorization scanning, complementary).
Development
git clone https://github.com/npow/memshield.git
cd memshield
pip install -e ".[dev]"
pytest
License
Metadata
Release files for memshield 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| memshield-0.2.0.tar.gz | 534.2 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| memshield-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 585.2 kB
Release files / memshield-0.2.0.tar.gz
| Download URL | memshield-0.2.0.tar.gz |
|---|---|
| Size | 534.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
2ecfe4b2e533d3bc1181fcfbd4b60590ea4adbd276040ea90c234bd1343be597
|
|
BLAKE2b-256 checksum How to use checksums |
0482cbc7e7a19959d84e4533cc0b9a40d2028dd61ba9f71417aa9c006ee81d50
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 9, 2026.
Transparency logRelease files / memshield-0.2.0-py3-none-any.whl
| Download URL | memshield-0.2.0-py3-none-any.whl |
|---|---|
| Size | 51.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
216a4b6ab88a8271b3861cb734e97c7db4884a3fe524558b0ad671d4854cc509
|
|
BLAKE2b-256 checksum How to use checksums |
bfe56d8dfeb601678e39371d415e4ab3b13d26f9695a8b72b07244d68c023a53
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 9, 2026.
Transparency logSecurity for memshield 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for memshield-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 9, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.