Debt Collector Series: §1 Manifesto: The Error Principle

§1 Manifesto: The Error Principle

Information Debt as the Root Cause of Exploitable Vulnerabilities

Author: Shrikant Bhosale (@debtcollector21)
Version: 2.0 (Formalized)
Proof Basis: A06 — [Vendor]-confirmed P2/S2 ([Vendor] Issue 533645392)


1.1 The Central Observation

Every exploitable vulnerability arises from a gap between what a programmer assumed about program state and what an attacker can make true.

This gap is not a bug. It is information debt — the entropy remaining after the programmer’s error-handling logic failed to constrain the state space.


1.2 Formal Definition

Let a program be modeled as a state-transition system:

f: S × Σ → S

Where:
– S = set of all possible program states
– Σ = set of all possible inputs (including adversarial ones)
– I ⊂ S = the invariant subspace of safe states (defined by the programmer’s intent)

A validation node is a function v_val: Σ → {0, 1} that partitions the input space into validated and unvalidated subsets:

Σ_safe = {σ ∈ Σ | v_val(σ) = 1}
Σ_unsafe = {σ ∈ Σ | v_val(σ) = 0}

The programmer’s knowledge of the state space is the extent to which they have defined Σ_safe and the handling logic for states reachable via Σ_unsafe.

Information Debt (Δℐ) is the remaining entropy of the unvalidated state space after the programmer’s handling logic is applied:

Δℐ = H(S \ I | Σ_safe)

Where H is the Shannon entropy of the reachable unsafe state space, conditioned on the subset of inputs that pass validation.

In practice, we approximate this as:

D_e = 1 - H_e

Where:
– H_e = fraction of error paths explicitly handled (by try/catch, error return checked, precondition validated, etc.)
– D_e ∈ [0, 1] = Information Debt of the function


1.3 The Quadratic Vulnerability Probability

A single unhandled error is rarely exploitable. Exploitation requires composition — the attacker must:
1. Trigger an initial fault (e.g., allocation failure, bounds bypass)
2. Exploit the corrupted state before it is detected

This is a two-stage Markov process:

P(exploit) = P(stage_1_fault) × P(stage_2_exploit | stage_1_fault)

If the programmer handles k out of n error paths, the probability of an unhandled error path existing in any given execution is:

P(unhandled_error) = D_e = 1 - k/n

For exploitation to succeed, the attacker needs TWO unhandled errors to compose:
1. One to corrupt state
2. One to leverage the corruption into control

The probability of two independent unhandled errors coexisting in the same execution path is:

P(exploit_chain) = D_e × D_e = D_e²

This is the quadratic debt-exploit relation. It is not an empirical observation — it falls out of the definition of Information Debt and the requirement for two-stage exploitation.

Empirically validated: our [Vendor] analysis found D_e >= 0.816 in all 4 subsystems. D_e² = 0.666 — meaning a 66.6% probability that any given execution path through the parser contains two unhandled errors that could compose. This is not an accident of [Vendor]’s code quality; it is a structural consequence of the error-handling architecture.


1.4 The Error Principle

A system that does not handle its errors does not know its own state, and a system that does not know its own state can be made to do anything.

This principle operates at every level:

Level Error Type Information Debt Exploitation
Function Unchecked return value D_e = % unhandled errors State corruption
Object Unvalidated invariant D_e = % unvalidated preconditions Type confusion
Subsystem Missing boundary check D_e = % unchecked inputs Privilege escalation
Application Unhandled exception D_e = % unguarded call sites Denial of service
Protocol Missing state validation D_e = % unverified transitions TOCTOU bypass

Every level compounds. D_e at the function level aggregates upward through the call graph.


1.5 The Curvature Formula

Every finding is scored by a 6-dimensional geometric projection. The dimensions are:

1.5.1 AST Validity (κ_ast)

Does the syntactic structure support the finding? A reinterpret_cast at a call site with no function context is structurally ambiguous (κ_ast low). A reinterpret_cast inside a function that processes external data is structurally precise (κ_ast high).

κ_ast = match(syntax_pattern, point_context) × context_completeness

Implementation: tree-sitter AST confirms the finding’s syntactic pattern exists in a valid function context.

1.5.2 Data Flow Integrity (κ_data_flow)

Does input actually reach sink? A null dereference on a pointer that was just allocated with new without checking may have data flow from a remote source (κ_data_flow high) or be purely local (κ_data_flow low).

κ_data_flow = 1 - (shortest_unchecked_path_length / total_path_length)

If no input traces to the sink, κ_data_flow ∈ [0.3, 0.6] (collapse zone).

1.5.3 Memory Layout Geometry (κ_memory_layout)

Does the finding involve actual memory corruption potential? An OOB write to a stack buffer has high memory_layout κ (immediate corruption). An OOB read to padding bytes has low κ (no practical corruption).

κ_memory_layout = allocation_presence × size_reference_presence × offset_reference_presence

1.5.4 Error State Integrity (κ_error_state)

This is where the Error Principle directly enters the curvature calculation.

If error detected but NOT handled: κ_error_state = κ × 1.2
If no error handling at all:      κ_error_state = κ × 1.3
If error properly handled:        κ_error_state = κ × 0.7

The multipliers reflect information debt amplification: unhandled errors increase the probability that the observed pattern is real.

1.5.5 Exploit Chainability (κ_exploit_chain)

Can this finding be linked with others to form an exploit chain?

κ_exploit_chain = f(preconditions_met, postconditions_match, chain_length)

A write primitive without a corresponding read/control primitive has low chainability. A write primitive that shares state with an adjacent use-after-free has high chainability.

1.5.6 Temporal Stability (κ_temporal)

Does the finding persist across program versions?

κ_temporal = 1 - (days_since_introduced / days_since_known)

A finding in code that hasn’t been touched in 10 years has κ_temporal = 1.0 (it’s structural, not a regression). A finding in recently refactored code has lower κ_temporal.

1.5.7 Total Curvature

κ_total = Π(κ_d)  for d ∈ {ast, data_flow, memory_layout, error_state, exploit_chain, temporal}

Collapse condition: κ_total < 0.50 OR any κ_d < 0.30

This means a finding is presumed false if any single dimension cannot support it, OR if the product of all dimensions falls below 0.50.


1.6 The Projection Collapse Theorem

Theorem: A true vulnerability persists across ALL observation dimensions. A false positive collapses in one or more dimensions.

Proof: Consider a finding F with curvature κ_total. Suppose F is a false positive — a code pattern that looks dangerous but is not exploitable. Then there exists at least one dimension d where κ_d → 0 (the pattern is structurally unsound, has no data flow, has no memory corruption potential, etc.). By the product formula, κ_total → 0. This is the collapse.

Conversely, if F is a true vulnerability, then all κ_d > 0 (the vulnerability has structural basis, data flow, memory impact, etc.), so κ_total > 0.

The threshold κ_total >= 0.50 is empirically validated against our known-positive dataset (A01-A06, all [Vendor]-confirmed or confirmed via ASAN PoC). Setting the threshold lower increases recall at the cost of precision; setting it higher increases precision at the cost of recall.

Empirical validation ([Vendor] scan, 56,260 points):

Subsystem Total Points After Collapse Collapse Rate
Parser 32,847 ~5,200 ~84%
Wasm 8,417 ~1,350 ~84%
Compiler 14,996 ~2,400 ~84%

The consistent 84% collapse rate across all subsystems suggests it is a property of the projection engine, not of any particular codebase — meaning approximately 84% of VMF’s raw findings are false positives that can be identified structurally without manual review.


1.7 The Debt-to-Chain Theorem

Theorem: Every function with D_e > 0.8 in a security-critical subsystem participates in at least one exploit chain of CVSS >= 7.0.

Proof sketch:

  1. Let f be a function with D_e > 0.8. Then at least 80% of f’s error paths are unhandled.
  2. Let U be the set of unhandled error paths. Each u ∈ U represents a potential state corruption (write of uninitialized data, use of null pointer, continuation with corrupted buffer).
  3. For any u₁, u₂ ∈ U, the probability of both being reachable in the same execution is D_e² > 0.64.
  4. If u₁ produces a write primitive and u₂ reads corrupted state, the pair forms an exploit chain.
  5. In a security-critical subsystem (kernel, browser engine, system service), corrupted state from u₁ can cross a trust boundary, elevating u₂’s impact.
  6. CVSS >= 7.0 requires (AV:N/AV:L + AC:H or lower + no authentication). This is satisfied when the chain crosses a trust boundary (SCOPE: CHANGED) and produces code execution (C/I:H).

Corollary: The density of exploit chains in a codebase grows as the SQUARE of the error debt density.

This is why large, old codebases ([Vendor], [Vendor], [Vendor]) contain thousands of findings — the debt has accumulated over decades, and the chain density grows quadratically with it.


1.8 Feynman Gate

Every finding must pass a 10-question honesty gate before it is submitted:

# Question Pass/Fail
1 Does a working PoC exist? Binary
2 Is the exploit chain complete? (write + read/control) Binary
3 Have you tested the failure case? (what would disprove this?) Binary
4 Is the CVSS honest? (not inflated for bounty) Binary
5 Would you bet money on this being exploitable? Binary
6 Have you considered the reviewer’s likely first objection? Binary
7 Is there an easier way to achieve the same impact? Binary
8 Have you verified this on the real target (not a mirror)? Binary
9 Does the finding composition principle hold (2+ errors)? Binary
10 Is the severity proportional to the actual attack surface? Binary

A FAIL on questions 1-3 is a hard block — the finding is not ready for submission.
A FAIL on questions 4-10 is a soft block — the finding needs reframing or additional work.

Empirical example: The [Vendor] DCHECK-bypass chain originally had CVSS 8.8 (AV:N). Feynman Gate revealed:
– Q1 (PoC): FAIL — PoC was against mirror code, not real [Vendor]
– Q4 (CVSS honesty): FAIL — requires renderer compromise first (AV:L, not AV:N)
– Q10 (proportionality): FAIL — “~3B vulnerable devices” overstated
Corrected CVSS: 7.5
Outcome: Submitted responsibly to security@[Vendor]js.org, not as [Vendor] zero-day


1.9 The Strategic Implication

The Error Principle implies a fundamental shift in vulnerability research:

Traditional approach: Find individual bugs. Fix them. Wait for new ones.

Debt approach: Find the information gaps that make bugs inevitable. Fix the gap. The bugs stop coming.

A single try/catch block can eliminate an entire class of exploits. A single bounds check can collapse thousands of attack paths. The Debt Collector identifies WHICH try/catch and WHICH bounds check provides the maximum chain collapse.

This is why [Vendor] assigned P2/S2 to A06 (pure static analysis, no exploit demo). They understood that finding the 53 unguarded exception handlers in AMS/NMS/UGMS was more valuable than any single exploit proof — it told them where the structural debt was, allowing them to fix the root cause rather than the symptoms.


1.10 Limitations

  1. D_e is a heuristic. It measures the NUMBER of error paths handled, not the QUALITY of handling. A catch(...) { } (empty catch block) counts as handled but provides no meaningful safety. This inflates H_e and deflates D_e. The Error Debt Scanner (error_debt/) addresses this by classifying handlers into 6 categories (empty, log-only, rethrow, partial-cleanup, swallow, default-deny), but this classification is itself heuristic.

  2. D_e does not measure PATH reachability. Two unhandled errors may exist in the same function but on mutually exclusive control flow paths. The quadratic D_e² assumes independence, which is the worst case. Real exploit probability is bounded by D_e² from above.

  3. Curvature weights (0.35, 0.30, etc.) are empirically tuned. The formal derivation from first principles is ongoing work. However, the COLLAPSE condition (product of dimensions) is not arbitrary — it follows from the Projection Collapse Theorem, which is provably true given the definitions.

  4. Feynman Gate is subjective. Questions 4-10 depend on the researcher’s judgment. Standardization through a decision tree is planned.

Leave a Comment