mutated × unstructured — blows up live on input you didn't expect

Aliased-Default Type Confusion

A function's mutable default is shared across calls; one caller seeds it with a wrong-typed value, and a later caller crashes operating on it.

01the recipe

In the wild

example.py
# SMELL: a shared mutable default accumulates state across calls.
# (aliasing mutable defaults x type errors)
def collect(item, into=[]):     # one list, shared by every call
    into.append(item)
    return sum(into)            # crashes once a non-number slips in

collect(1); collect(2)          # fine
collect("x")                    # TypeError on the NEXT caller's sum(into)

# RIGHT: a fresh container per call; the type stays local and predictable.
def collect(item, into=None):
    into = [] if into is None else into
    into.append(item)
    return sum(into)
The default list is created once and aliased by every call, so values -- and their types -- leak between callers. One caller appending a string poisons the shared default; a later caller's sum() hits incompatible types, a crash with no obvious owner. Default to None and build a fresh container inside.
// observed
shared: TypeError in a caller that never touched a string
right: each call owns its list; types stay local
02weakness catalog

Mapped weaknesses (CWE)

On its own, this defect is catalogued by MITRE as one or more of these weaknesses. The exploitable vulnerability usually appears only when it chains or combines with another.