Do not use compile()

ID

python.no_use_compile

Severity

low

Resource

Risky Values

Language

Python

Tags

CWE:94, NIST.SP.800-53, OWASP:2021:A3, PCI-DSS:6.5.1

Description

Avoid using the compile() function with untrusted input as it can lead to code injection vulnerabilities when paired with eval() or exec().

Rationale

The compile() function in Python transforms a string of code into a code object that can be executed using exec() or evaluated with eval(). While this function by itself does not execute code, it becomes dangerous when it’s used with input that originates from users or other untrusted sources, especially if the output is then passed to exec() or eval().

This pattern forms the basis of a classic code injection vulnerability (CWE-94: Improper Control of Generation of Code). Attackers can inject arbitrary code, leading to full compromise of the system if executed.

The following example demonstrates a vulnerable use:

user_input = input("Enter Python code: ")
code = compile(user_input, '<string>', 'exec')
exec(code)

In this scenario, an attacker could enter:

__import__('os').system('rm -rf /')

Which would be compiled and then executed, leading to a critical system operation.

Another variation, using eval:

user_input = input("Enter an expression: ")
code = compile(user_input, '<string>', 'eval')
result = eval(code)
print(result)

This similarly allows for arbitrary code evaluation.

Remediation

Avoid using compile() altogether with untrusted input. If dynamic code execution is absolutely required, strongly validate and sanitize the input before compiling or evaluating it. Prefer structured alternatives like ast.literal_eval() or safer expression evaluators when applicable.

When you must allow limited user input for evaluations (e.g., mathematical expressions), use the ast module to parse and validate the code structure before executing it.

Key remediation points: - Never compile or execute user-controlled strings directly. - Use safe evaluation libraries when dynamic evaluation is needed. - Rely on strict input validation and structural code checks (e.g., via AST).

Blocking or flagging all uses of compile() in a SAST tool is a strong preventative control, especially when paired with contextual data flow analysis to detect if the source is user-controlled.

Configuration

This detector does not need any configuration.

References