T09 · Insecure Skill Coding Practices
- Location
__init__.py:152- Finding
Arbitrary Python Code Execution Through calculate() Fallback
- Content
View full analysis
Vulnerability Details
File Location:
__init__.py:152-172
Vulnerability Type: Unsafe expression interpolation leading to arbitrary code execution
Risk Level: CriticalVulnerable Code:
python def calculate(expression: str) -> Dict[str, Any]: try: # First attempt safe evaluation result = safe_eval(expression) if result["success"]: return result # If safe evaluation fails, execute it with Python return run_python(f"print({expression})")Technical Analysis
safe_eval()uses an AST allowlist, butcalculate()does not reject expressions that fail that validation. Instead, it interpolates the original expression directly into Python source and passes it torun_python(), which executes it usingpython3 -c.Consequently, the AST validation is only a preliminary attempt rather than a security boundary. Any valid Python expression rejected by the allowlist can reach unrestricted Python execution. For example:
python calculate('__import__("os").system("id")')The import expression is rejected by
safe_eval(), after which the application constructs and executes:python print(__import__("os").system("id"))No shell metacharacters are required because the injected value is executed directly as Python source.
Attack Path
- An attacker supplies a calculation expression containing non-allowlisted Python functionality.
safe_eval()parses the input and returns a failure because the expression contains an unsupported AST node or function.calculate()inserts the unchanged input intoprint(...).run_python()invokespython3 -cwith the generated source.- The payload executes with the operating-system permissions of the skill process.
- The attacker can use Python modules to execute processes, access files, or communicate over the network.
Impact Assessment
Successful ...[truncated 509 chars]
- Remediation
View remediation
Remediation Suggestions
- Remove the fallback to
run_python()completely. Ifsafe_eval()rejects an expression, return the validation error. - Add required mathematical functions and operators individually to a strict AST allowlist rather than invoking a general-purpose interpreter.
- Never interpolate user-controlled expressions into Python source.
- Apply input-length, AST-depth, operand-size, result-size, memory, and execution-time limits.
- Run calculation workers under a dedicated low-privilege account with no sensitive filesystem or network access.
- Add regression tests proving that payloads involving
__import__, attributes, comprehensions, lambdas, and other unsupported nodes cannot execute.
- Remove the fallback to
