Summary
The scanner detects direct use of exec(), but misses the same execution behavior when the function is resolved dynamically through getattr().
Original:
import base64
decrypted_data = base64.b64decode('just a test')
exec(decrypted_data.decode('utf-8'))
Result:
HIGH: AST1 - exec() call detected
Confidence: 85%
Variant:
import base64
import builtins
decrypted_data = base64.b64decode('just a test')
_runner = getattr(builtins, ''.join(['e','x','e','c']))
_runner(decrypted_data.decode('utf-8'))
Result:
LOW: AST7 - Dynamic attribute access via getattr()
Confidence: 50%
Expected Behavior
The variant should still trigger the high-severity exec() finding because the dynamically constructed attribute resolves to builtins.exec.
Impact
Dynamic builtin resolution downgrades the finding from HIGH arbitrary code execution to a generic LOW getattr() warning.
Suggested Fix
Add constant folding and builtin resolution for getattr() calls, including statically constructed names such as ''.join(['e','x','e','c']).
Summary
The scanner detects direct use of
exec(), but misses the same execution behavior when the function is resolved dynamically throughgetattr().Original:
Result:
Variant:
Result:
Expected Behavior
The variant should still trigger the high-severity
exec()finding because the dynamically constructed attribute resolves tobuiltins.exec.Impact
Dynamic builtin resolution downgrades the finding from
HIGHarbitrary code execution to a genericLOWgetattr()warning.Suggested Fix
Add constant folding and builtin resolution for
getattr()calls, including statically constructed names such as''.join(['e','x','e','c']).