Your AI Agent Can Be Hacked via Plugins: How to Secure Claude Code and Codex Skills in Production
I’m Denis Shokhirev, Agentic AI Systems Architect in Freiburg im Breisgau, Germany, running DennisCraft AI Studio. My stack is Claude, Supabase, n8n, Doppler, and self-hosted Postgres. I’ve caught real SQL injection bugs in production plugins—generated by Claude Code—on B2B projects where demos looked clean, but live traffic exposed the risk. The Attack Surface: Plugins and LLM-Generated Skills Autonomous AI agents in production typically rely on plugins or custom “skills”—small modules in Py
I’m Denis Shokhirev, Agentic AI Systems Architect in Freiburg im Breisgau, Germany, running DennisCraft AI Studio. My stack is Claude, Supabase, n8n, Doppler, and self-hosted Postgres. I’ve caught real SQL injection bugs in production plugins—generated by Claude Code—on B2B projects where demos looked clean, but live traffic exposed the risk.
The Attack Surface: Plugins and LLM-Generated Skills
Autonomous AI agents in production typically rely on plugins or custom “skills”—small modules in Python or JS, often generated by LLMs via Claude Code or Codex. In my last 11 projects, 80% of plugin code was LLM-generated (internal audit, 2024). If you skip targeted review, vulnerabilities like SQL injection (CWE-89), SSRF, or RCE can slip straight into prod.
Common Vulnerability Patterns in Claude Code and Codex
- SQL injection: LLM-generated code that builds SQL queries from user input without parameterization.
- Insecure deserialization: Plugins loading data from untrusted sources without validation.
- SSRF: LLM code that allows agents to fetch arbitrary internal URLs.
- Shell command injection: Generated code using unsafe
evalorsubprocesscalls.
On a recent deployment, Claude generated this plugin code, which reviewers missed because it was “auto-generated”:
def get_user_data(user_id):
query = f"SELECT * FROM users WHERE id = {user_id}"
cursor.execute(query)
return cursor.fetchall()
This code made its way into production and was a live SQL injection entry point.
Securing the Pipeline: How I Catch These Bugs Before Prod
In my agent stacks, I use a three-stage pipeline:
- Static code analysis (semgrep, bandit, gitleaks)
- Sandboxed payload testing
- Human review—only for critical plugins
Static Analysis: semgrep + bandit
semgrep can catch patterns like f"SELECT ..." and unsafe calls. bandit is tuned for Python security. Here’s a semgrep rule for SQL injection:
rules:
- id: possible-sql-injection
pattern: cursor.execute(f"...")
message: "Possible SQL injection via f-string"
severity: ERROR
bandit integrates with any CI/CD pipeline:
bandit -r ./plugins/
gitleaks is essential for catching leaked secrets and tokens in plugin code.
Sandbox Payload Testing: Simulate the Attacker
I run every new plugin in an isolated environment with malicious payloads—' OR '1'='1 for SQL, file:///etc/passwd for SSRF. Test endpoints and mock databases are critical.
# Unit test example to catch SQL injection
def test_sql_injection():
result = get_user_data("' OR '1'='1")
assert "admin" not in result
Responding to Production Incidents: Patch Fast, Log Everything
If a vulnerability hits prod, you need rollback and rapid patching mechanisms. My approach: maintain a separate branch for “critical” plugins, deployable outside the main release cycle, with a dedicated audit log.
Log every incoming payload and link it to the plugin version. This lets you pinpoint which code ran during an attack.
| Stage | Tool | Purpose |
|---|---|---|
| Static analysis | semgrep, bandit | Catch known patterns |
| Secret scanning | gitleaks | Remove tokens from code |
| Sandbox tests | pytest, custom scripts | Test with real payloads |
LLM Sandboxing: Know the Limits
Claude Code and Codex often run under restricted permissions in production (sandboxed execution). But by default, many frameworks let agents generate arbitrary Python code—including shell commands. Don’t assume “sandbox by default.” The Anthropic docs explicitly recommend whitelisting allowed functions and validating outputs before execution.
# Example: restricting functions in Claude Code
allowed_functions = {"get_user_data", "send_email"}
if requested_function not in allowed_functions:
raise Exception("Function not allowed")
If you’re building agents with n8n, every custom node—especially if LLM-generated—is a risk point.
FAQ
What tool best detects SQL injection in LLM-generated code?
semgrep is the most flexible; you can write custom rules and integrate it into almost any pipeline.
Can I fully trust bandit or semgrep?
No. They only catch known patterns. In production, I’ve seen bugs that slipped past both—especially when eval or complex function chains are involved.
Should I do human review for all plugins?
No, not if you generate >10 per week. I only review manually for plugins with access to critical data or external APIs.
How do I protect self-hosted Postgres from LLM agents?
Move all queries to parameterized procedures. Don’t give agents raw SQL access. In Supabase, use Row Level Security (RLS).
What if a vulnerability escapes to production?
Keep a critical-patch branch and an audit log of payloads, so you can quickly scope and mitigate attacks.
Which stage in your LLM pipeline catches the most issues in prod—static analysis, runtime sandbox, or human review? I’d genuinely like to know.
I run a free 30-min stack audit for DACH founders building AI in regulated markets. DM me on LinkedIn or write to @ger_dennis_ai.
Turn your process into an AI system
Fixed price. Production quality. DACH B2B focus.