Your Python, made secure.

Install es-python and run your Python code without the fear of being hacked.

  • Surface vulnerabilities no other tool can detect.
  • Run Python without privilege escalation.
  • Run a server without command injection, SQL injection, deserialization, and more.
  • See exactly what an attacker could have exploited against your own code.
the problems it solves

Your problem, and what es-python does about it

Every problem es-python solves

proof, not a hypothesis

What it surfaced in Django, it can surface in your website

EyalSec surfaced two unauthenticated SQL-injection flaws inside Django. Django's security team fixed both, with our thanks, and credits Eyal Gabay of EyalSec.

CVE-2024-42005, step by step

  1. SourceA crafted JSON keySent to a JSONField model, no login needed.
  2. TrackedUsed as a column aliasPassed to QuerySet.values().
  3. SinkIt reaches the SQLes-python reported the flow: SQL injection in Django itself.
  4. FixedReported, fixed, creditedFixed in Django 5.0.8 and 4.2.15. Their advisory credits Eyal Gabay of EyalSec.
CVE-2024-42005CISA rates it 9.8 · Critical

SQL injection via crafted JSON keys used as column aliases in QuerySet.values() / values_list(). NVD rates it 7.3 High.

CVE-2025-57833CVSS 8.1 · High (NVD)

SQL injection via FilteredRelation column aliases in annotate() / alias() with **kwargs expansion.

NVD record at nvd.nist.gov
how it compares

A remote code execution (RCE) bug, and what each tool does about it

app.pyRCE
TOOLS = {"local": os.system,
         "remote": ssh_run}

@app.route("/check")
def check():
    host = request.args["host"]
    run = TOOLS[request.args["via"]]
    run("ping -c 1 " + host)

Sandboxing / isolation

Limits what the process can reach.

Still an RCE: the attacker can escalate, change the site and attack visitors.

Protected by EyalSec: it catches the command before it runs.

WAF / edge

Blocks odd-looking strings in requests.

Still an RCE: the attack can look like normal input, so it passes.

Protected by EyalSec: it judges where the text lands, not how it looks.

EDR / runtime threat

Watches processes on the host.

Still an RCE: it sees a shell start, not that a web request built it.

Protected by EyalSec: it stops the command and names the request and the line.

RASP

Hooks risky calls inside the app.

Still an RCE: it cannot tell which data reached the call, so no alert.

Protected by EyalSec: it follows the request text to the command and stops it.

SAST

Scans source for known patterns.

Still an RCE: its simple patterns are rare in real code, and run(...) is not one.

Protected by EyalSec: it sees the real call to os.system and stops it.

DAST / fuzzing

Sends odd inputs, waits for a crash.

Still an RCE: the command runs, nothing crashes, nothing is reported.

Protected by EyalSec: it stops the request that tried it, and reports it.

SCA / dependency

Lists libraries with known CVEs.

Still an RCE: the bug is your own code, so no CVE names it.

Protected by EyalSec: it catches the bug in your own code.

how to use

Two small steps: no rewrite, no lock-in

Your code stays as it is. Run it with python3, the way you already do.

your server
# step 1 · add a card, then a machine; the dashboard gives this command
$ . <(curl -sSL -d "secret=YOUR_TOKEN" https://eyalsec.com/install.sh)
# step 2 · run your code, checks on
$ python3 app.py
Serving on http://0.0.0.0:8080
how it works

Taint in, sink out

01 Sources
Marked at the read

Network sockets, files, stdin, data is marked untrusted the moment it enters.

# from the requesthost = "8.8.8.8;id"
02 Tracked
Follows the data

The taint follows the value as it's copied and transformed through your program.

# still marked after the joincmd = "ping -c 1 8.8.8.8;id"
03 Sinks
Logged, and optionally stopped

exec, eval, compile, os.system, subprocess, pickle, sqlite3, ctypes, …

# marked data reached a sinkos.system(cmd)
safe to run

It's Python, with a seatbelt

What each event carries, and how the dashboard protects it, is on the security page.