read before it was ever written

Improper Initialization

A binding read before it is assigned, a field a constructor forgot, a resource left at its default: the undefined → defined transition is where state begins, and skipping it makes illegal states representable from the very first line.

The first state transition — undefined to defined — is the purest mutated-state bug: use a value before it exists and every later read inherits garbage.

01in the wild

In the wild

Used Before Assigned

A variable or field read before anything wrote to it hands back whatever was already there.

example.c
// SMELL: local is never initialized -- reads indeterminate memory
int total() {
    int sum;                 // garbage value
    for (int i = 0; i < 10; i++)
        sum += i;            // adds to garbage; result is nonsense
    return sum;
}

// RIGHT: initialize at the point of declaration
int total() {
    int sum = 0;             // a defined starting state
    for (int i = 0; i < 10; i++)
        sum += i;
    return sum;
}
An uninitialized automatic variable holds whatever bytes were on the stack. Reading it is undefined behavior; initialize at declaration so the starting state is real.
// observed
uninit: sum += i over garbage -> nonsense
init:   sum starts at 0 -> 45
example.go
// SMELL: the zero value of a map is nil, and writing to nil panics
var counts map[string]int          // nil, not empty
counts["a"]++                      // panic: assignment to entry in nil map

// RIGHT: make() gives a real, writable map
counts := make(map[string]int)     // initialized
counts["a"]++                      // 1

// (reading a nil map is fine -- it's the WRITE that needs init)
Go zero-values everything, but a map's zero value is nil and only readable. You must make() it before writing, or the first assignment panics.
// observed
nil map:  counts["a"]++ -> panic
made map: counts["a"]++ -> 1

Insecure Default Initialization

A field left at a permissive default — or a constructor that skips it — is a security hole, not just a bug.

example.py
class Session:
    def __init__(self, user):
        self.user = user
        # SMELL: is_admin never set; some paths read it -> AttributeError,
        # or a __getattr__ shim quietly returns a truthy default
    def can_delete(self):
        return self.is_admin          # AttributeError, or worse: True

# RIGHT: initialize every field to a safe, explicit default
class Session:
    def __init__(self, user):
        self.user = user
        self.is_admin = False         # deny by default
A field the constructor forgets is either a crash or, with a permissive fallback, an open door. Initialize every field — and make the default the safe one.
// observed
missing: self.is_admin -> AttributeError / unsafe
default: is_admin = False -> deny by default
example.js
// SMELL: a half-built object escapes before it's fully set up
function makeUser(req) {
  const u = {};
  u.name = req.name;
  save(u);                 // saved with role === undefined
  u.role = "member";       // too late -- the saved copy is broken
  return u;
}

// RIGHT: build the whole value, then let it escape
function makeUser(req) {
  return { name: req.name, role: "member" };   // fully initialized
}
Letting a partially-initialized object escape (saved, passed, returned) exposes the undefined window. Construct the complete value first, then release it.
// observed
leaked: save() sees role === undefined
whole:  object is complete before it escapes
02cross-pollination

Where this compounds

03weakness 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.