Skip to content

v8.1.19 - Security fix: eval() sandbox escape in QASMParser

Choose a tag to compare

@tatopenn-cell tatopenn-cell released this 21 Jul 11:02

Security

Fixed a code-execution vulnerability affecting every previously published version.

QASMParser's gate-parameter evaluator (_eval_param, used for expressions like rx(...), p(...)) called eval() with {'__builtins__': {}} as its only protection. That blocks direct builtin names (open, len, __import__, ...) but does not block attribute/dunder traversal of the live Python object graph (().__class__.__bases__[0].__subclasses__()...), which needs no builtin name at all — from there, any class loaded in the process is reachable, including ones whose __globals__ reference os/subprocess.

Verified directly: a crafted gate-parameter expression, passed through the public QASMParser.parse() entry point — the primary entry point of the whole library (dashboard, Qiskit/PennyLane interop bridge, direct usage) — executed successfully. Anyone parsing untrusted QASM text was affected.

Fixed by replacing eval() with an AST node-type whitelist evaluator (_eval_ast_node) — only literals, +-*/%** arithmetic, and calls/lookups restricted to the documented math environment (pi, sin, sqrt, ...) are ever evaluated; an attribute access is structurally impossible to reach, not blocklisted. _resolve_int_expr (QASM3 for-loop bounds) used the same pattern but was already protected by a separate pre-filter — verified safe before this fix — now migrated to the same evaluator for consistency, so no raw eval()/exec() remains anywhere in the codebase.

No behavior change for legitimate expressions — every previously-supported parameter syntax evaluates identically.

If you parse QASM text from any source you don't fully trust, upgrade immediately.

PyPI: https://pypi.org/project/dense-evolution/8.1.19/