AutoPiff
February 18, 2026 · View on GitHub
Purpose
Semantic rules define which code changes are considered security-relevant and therefore eligible to appear in AutoPiff reports.
These rules are intentionally conservative:
- Fewer findings
- Higher confidence
- Strong bias toward obvious vulnerability fixes
AutoPiff v1 prioritizes trustworthiness over coverage.
Rule Philosophy
A semantic rule should answer:
“Does this change plausibly fix a memory-safety or trust-boundary issue that could be exploited if reachable?”
Rules must:
- Rely on explicit code changes, not inference
- Be explainable in plain English
- Trigger on specific, localized logic changes
- Avoid refactor-sensitive patterns
Rules must NOT:
- Speculate about exploitability
- Rely on naming alone
- Trigger on stylistic or cosmetic changes
Canonical Rule Categories (v1)
Only the categories below are allowed in v1.
Each rule belongs to exactly one category.
1) Bounds & Size Validation
Category ID: bounds_check
Intent
Detect fixes where insufficient validation of sizes, indices, or lengths could previously result in out-of-bounds access.
High-Signal Indicators
-
New conditional checks on:
- buffer length
- index bounds
- structure size
-
Added comparisons before copy loops or memory access
-
Introduction of explicit size validation helpers
Typical Sinks
RtlCopyMemory,memcpy,memmove- Manual copy loops
- Array indexing using untrusted values
Example Rule Triggers
if (len < sizeof(...)) return STATUS_INVALID_PARAMETER;if (idx >= count) return STATUS_INVALID_PARAMETER;- Replacement of unchecked arithmetic with validated size calculation
2) Pointer Lifetime & Ownership Hardening
Category ID: lifetime_fix
Intent
Detect fixes addressing double free, use-after-free, or invalid pointer reuse.
High-Signal Indicators
- Pointer set to
NULLimmediately afterExFreePool* - Added checks preventing repeated free
- Introduction of reference counting or ownership checks
Typical Sinks
ExFreePool,ExFreePoolWithTag- Manual object destruction routines
Example Rule Triggers
ptr = NULLadded after freeif (ptr != NULL)guard added before free- Added
InterlockedIncrement/Decrementguarding object lifetime
3) User ↔ Kernel Boundary Validation
Category ID: user_boundary_check
Intent
Detect fixes where untrusted user-mode data was previously accessed without sufficient validation.
High-Signal Indicators
-
Added calls to:
ProbeForReadProbeForWriteExGetPreviousMode
-
New checks gating behavior based on caller mode
-
Added structured exception handling around user pointer access
Typical Sinks
- Direct dereference of user-supplied pointers
- Copying from user buffers into kernel memory
Example Rule Triggers
if (ExGetPreviousMode() != KernelMode) ProbeForRead(...);- Introduction of
__try/__exceptaround pointer access
4) Integer Overflow / Size Arithmetic Hardening
Category ID: int_overflow
Intent
Detect fixes where integer overflow could previously lead to incorrect allocation sizes or bounds bypass.
High-Signal Indicators
-
Replacement of raw arithmetic with:
RtlULongAddRtlULongLongMultRtlSizeTMult
-
Explicit overflow checks before allocation
Typical Sinks
ExAllocatePool*- Size-based memory operations
Example Rule Triggers
if (!NT_SUCCESS(RtlSizeTMult(a, b, &out))) return STATUS_INVALID_PARAMETER;- Change from 32-bit to 64-bit arithmetic in size calculations
5) State & Reference Count Hardening
Category ID: state_hardening
Intent
Detect fixes where inconsistent state or missing synchronization could lead to unsafe behavior.
High-Signal Indicators
- Added reference counting around shared objects
- Added locking around state transitions
- New validation of object state before use
Typical Sinks
- Shared global or device context structures
- State machines accessed from multiple IRP paths
Example Rule Triggers
Interlocked*operations added- State validation added before dereference or use
Explicit Non-Rules (v1)
The following MUST NOT trigger semantic findings:
- Logging or tracing changes (ETW, WPP,
DbgPrint) - Error code changes without logic changes
- Refactors with no added guards
- Performance-only changes
- Reordering of checks without new validation
- Compiler-inserted artifacts (stack cookies, CFG)
If in doubt, do not trigger.
Rule Metadata Contract
Every semantic rule must define:
rule_id(stable, snake_case)category(one of the canonical categories)confidence(0.0–1.0)required_signalsexcluded_patternsplain_english_summary
Rules must be representable in rules/semantic_rules.yaml.
Rule → Report Mapping
Each triggered rule contributes:
-
Category label (used in report grouping)
-
Plain-English explanation (no jargon)
-
One or more key indicators:
- sinks involved
- checks added
-
A diff hint pointing to what changed
Rules that cannot produce all of the above must not surface in reports.
Rule Confidence (Guidance)
Default confidence guidance:
- Direct guard added before sink: 0.85–0.95
- Lifetime hardening after free: 0.80–0.90
- User boundary checks added: 0.85–0.95
- Integer overflow helpers added: 0.80–0.90
- State hardening without explicit sink: ≤ 0.75
Failure Handling
If:
- rule signals conflict
- function matching confidence is low
- reachability is unknown
Then:
- reduce confidence
- allow surfacing only if score remains high
Success Criteria
Semantic rules are successful if:
- ≥80% of surfaced findings are “worth a look” to an expert
- False positives are explainable in one sentence
- Rules generalize across vendors and drivers
Versioning
This document defines AutoPiff Semantic Rules v1.
All changes:
- must be backward compatible where possible
- must be recorded in
docs/DECISIONS.md