§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:
- Let f be a function with D_e > 0.8. Then at least 80% of f’s error paths are unhandled.
- 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).
- For any u₁, u₂ ∈ U, the probability of both being reachable in the same execution is D_e² > 0.64.
- If u₁ produces a write primitive and u₂ reads corrupted state, the pair forms an exploit chain.
- In a security-critical subsystem (kernel, browser engine, system service), corrupted state from u₁ can cross a trust boundary, elevating u₂’s impact.
- 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
-
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. -
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.
-
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.
-
Feynman Gate is subjective. Questions 4-10 depend on the researcher’s judgment. Standardization through a decision tree is planned.