SC002: NoInsecureFunctions

Overview

Property Value
ID SC002
Name NoInsecureFunctions
Group security
Severity WARNING

Description

Uses AST analysis to detect potentially dangerous function calls that can lead to code injection, arbitrary code execution, or insecure deserialization vulnerabilities.

What it checks

The check scans all Python files for:

eval() and exec()

These built-in functions execute arbitrary Python code and are dangerous when used with untrusted input:

# Dangerous: allows code injection
result = eval(user_input)
exec(user_provided_code)

pickle.load() and pickle.loads()

Pickle deserialization can execute arbitrary code during unpickling:

# Dangerous: arbitrary code execution during load
import pickle
data = pickle.load(untrusted_file)

subprocess with shell=True

Shell execution can lead to command injection:

# Dangerous: shell injection possible
subprocess.run(f"ls {user_input}", shell=True)

Result states

  • PASSED: No insecure function calls found
  • FAILED: One or more insecure function calls detected (with line numbers)

How to fix

Replace eval() with safer alternatives

# Bad: eval() for math
result = eval("2 + 2")

# Good: use ast.literal_eval() for safe literal evaluation
import ast
result = ast.literal_eval("{'key': 'value'}")

# Good: use operator module for simple math
import operator
ops = {'+': operator.add, '-': operator.sub}
result = ops['+'](2, 2)

Replace pickle with JSON

# Bad: pickle (insecure)
import pickle
data = pickle.load(f)

# Good: JSON (safe for data serialization)
import json
data = json.load(f)

Avoid shell=True in subprocess

# Bad: shell=True with user input
subprocess.run(f"ls {directory}", shell=True)

# Good: pass arguments as list
subprocess.run(["ls", directory])

# Good: use shlex for complex cases
import shlex
subprocess.run(shlex.split(f"ls {shlex.quote(directory)}"))

Why WARNING severity?

This check is a WARNING because:

  • These functions have legitimate use cases in controlled environments
  • Not all uses are necessarily insecure
  • Some codebases may need them for specific functionality

However, each occurrence should be carefully reviewed.

Configuration

Skip this check

[tool.pycmdcheck]
skip = ["SC002"]

CLI

pycmdcheck --skip SC002