Avoid dynamic evaluation. During architecture and implementation, refactor the design so it does not need eval or equivalent dynamic code evaluation.
Use strict allowlist validation. Treat all input as potentially malicious and accept only values that strictly conform to the specification. Check relevant properties including length, type, complete value range, missing or extra fields, syntax, consistency between related fields, and business rules. Reject nonconforming input or transform it into a conforming representation. Do not rely exclusively on denylists, although denylists can help identify attacks or reject obviously malformed input.
Canonicalize before validation. Decode and canonicalize input into the application's current internal representation before validating it. Avoid decoding the same input more than once, since double-decoding or related errors can bypass an allowlist. Canonicalization controls such as the OWASP ESAPI Canonicalization control may be used. Repeated canonicalization until the input stops changing can address double-decoding, but may alter inputs that legitimately contain encoded dangerous content.
Python-specific caution. ast.literal_eval is often suggested instead of eval because it is designed not to execute code. However, deeply nested input can still cause excessive memory or stack consumption, and the Python documentation discourages using it with untrusted data.