Skip to content

Python: taint is lost through list.extend, list.insert and += , but not list.append #22305

Description

@espressolee

Summary

CodeQL's Python taint tracking propagates through list.append, but not through list.extend, list.insert, or += on a list. A security query therefore reports a flow written one way and stays silent on the same flow written another way, where the two differ only in which list-mutation method is used.

I'm reporting the asymmetry rather than the incompleteness: append is clearly modelled, so the other three look like a gap in the same model rather than a deliberate boundary.

Reproducer

Each snippet is the same flow — a request parameter reaching subprocess.call(..., shell=True) — differing only in how the value passes through a list.

# reported
def handler():
    user = request.args.get("cmd")
    acc = [user]
    subprocess.call(acc[0], shell=True)

# reported
def handler():
    user = request.args.get("cmd")
    acc = []
    acc.append(user)
    subprocess.call(acc[0], shell=True)

# NOT reported
def handler():
    user = request.args.get("cmd")
    acc = []
    acc.extend([user])
    subprocess.call(acc[0], shell=True)

# NOT reported
def handler():
    user = request.args.get("cmd")
    acc = []
    acc.insert(0, user)
    subprocess.call(acc[0], shell=True)

# NOT reported
def handler():
    user = request.args.get("cmd")
    acc = []
    acc += [user]
    subprocess.call(acc[0], shell=True)

Results

codeql database analyze <db> codeql/python-queries:Security/CWE-078/CommandInjection.ql

construct reported
acc = [user] yes
acc.append(user) yes
acc.extend([user]) no
acc.extend(other) where other = [user] no
acc.extend([user]) then for x in acc: no
acc.insert(0, user) no
acc += [user] no

Environment

  • CodeQL CLI 2.26.2 (bundle codeql-bundle-osx64), macOS arm64
  • query: shipped Security/CWE-078/CommandInjection.ql, unmodified
  • the same asymmetry appears with Security/CWE-022/PathInjection.ql and Security/CWE-089/SqlInjection.ql

Controls

  • acc = [user] and acc.append(user) are reported, so the query, source and sink all work on these files.
  • A variant where the value comes from a local constant instead of request.args is not reported, so the rule is source-dependent rather than firing on shape.
  • All files were present in the database source archive, so the silences are misses rather than unanalysed files.

Note

append in Go is tracked as #14116. This is the Python analogue for the other three mutation forms.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions