free-pi-cli 0.4.9 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{index-xkn61g24.js → index-2s8fh2p0.js} +338 -403
- package/dist/index-n5qs9pq1.js +49 -0
- package/dist/index.js +4 -1
- package/dist/main-a786gwpy.js +24256 -0
- package/package.json +3 -2
- package/skills/security-audit/AI-AND-LLM.md +83 -0
- package/skills/security-audit/ATTACK-CLASSES.md +130 -0
- package/skills/security-audit/CLIENT-SIDE.md +83 -0
- package/skills/security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
- package/skills/security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
- package/skills/security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
- package/skills/security-audit/HUNTING.md +172 -0
- package/skills/security-audit/LICENSE +21 -0
- package/skills/security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
- package/skills/security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
- package/skills/security-audit/RECONNAISSANCE.md +140 -0
- package/skills/security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
- package/skills/security-audit/SKILL.md +152 -0
- package/skills/security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
- package/skills/security-audit/UPSTREAM.md +1 -0
- package/skills/security-audit/VALIDATION-AND-REPORTING.md +141 -0
- package/skills/security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
- package/skills/security-audit/report-schema.json +461 -0
- package/skills/security-audit/validate-coverage-ledger.cjs +872 -0
- package/skills/security-audit/validate-findings.cjs +773 -0
- package/dist/main-jaz36mav.js +0 -10818
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Vulnerability Hunting
|
|
2
|
+
|
|
3
|
+
### Phase 2: Run coverage-led hunting waves
|
|
4
|
+
|
|
5
|
+
You hunt every `planned` ledger unit yourself, one unit (or a few closely related units in one subsystem) at a time, in the main thread. No unit may be silently skipped: a unit you cannot reach is explicitly `deferred` with reason `context_or_time_exhausted`.
|
|
6
|
+
|
|
7
|
+
Take units in priority order and record the ordering rationale in the ledger. Rank by: (1) unauthenticated or lowest-trust entry surfaces before authenticated ones; (2) boundaries protecting the most valuable resources (credentials, cross-tenant data, code execution, release authority); (3) prior-run gaps, revalidation targets, and changed source before same-source re-passes; (4) units whose class historically yields confirmed findings for this target type over speculative ones. Ties break lexicographically by `coverage_id` so runs stay deterministic.
|
|
8
|
+
|
|
9
|
+
Before hunting a unit, set it to `in_progress` with owner pass label `main-w<wave>` (for example `main-w1`). Hunt by reading source. Do not edit target source. Write only the run files described in `SKILL.md`.
|
|
10
|
+
|
|
11
|
+
For each unit, load into your working context: `architecture.md`; the unit's coverage ID, subsystem, boundary, starting paths, and assignment block map; the exact selected blocks (the ordinary attack-class block from `ATTACK-CLASSES.md`, and from each selected companion its `Core discipline`, each chosen attack-class subsection, `Universal moves`, and `Validation rules`); the excluded blocks and their reasons; the carried same-source prior confirmed exclusions (fingerprint, title, root cause only); and the method and candidate gate below. Re-read the selected blocks before each unit rather than relying on memory of an earlier unit.
|
|
12
|
+
|
|
13
|
+
Scope is your coverage obligation, not permission to duplicate excluded work. If an unexpected different boundary appears, note it under `uncovered` so a stable ledger unit is created for the next wave.
|
|
14
|
+
|
|
15
|
+
#### Core hunting method
|
|
16
|
+
|
|
17
|
+
```text
|
|
18
|
+
## Defensive vulnerability-finding method
|
|
19
|
+
|
|
20
|
+
Your goal is to find source-grounded security invariant failures and the smallest fix,
|
|
21
|
+
not to expand harm beyond the boundary result. Stay within source review and bounded
|
|
22
|
+
local checks the user has approved. Do not contact deployed endpoints, provider APIs,
|
|
23
|
+
registries, identity systems, message brokers, shared services, or other users. Use
|
|
24
|
+
local dummy data only.
|
|
25
|
+
|
|
26
|
+
READ THE CODE AT DEPTH. Follow each assigned input through parsing, identity,
|
|
27
|
+
authorization, normalization, state, derived copies, and the final sink. Read sibling,
|
|
28
|
+
legacy, batch, retry, cancellation, migration, and error paths that produce the same
|
|
29
|
+
effect. Compare sibling controls for equivalence, not only presence, and compare what
|
|
30
|
+
one component guarantees with what the next component assumes.
|
|
31
|
+
|
|
32
|
+
WORK FROM A CONCRETE INVARIANT:
|
|
33
|
+
1. Name the lower-trust principal and starting capability.
|
|
34
|
+
2. Name the accepted value, action, state transition, or resource selector.
|
|
35
|
+
3. Locate the control that should reject, bind, isolate, limit, or revoke it.
|
|
36
|
+
4. Trace the exact source path after that decision.
|
|
37
|
+
5. Stop at the smallest affected dummy record, wrong return value, process-integrity
|
|
38
|
+
effect, or locally observable shared-resource effect.
|
|
39
|
+
6. State a source-level change and regression case that enforce the invariant.
|
|
40
|
+
|
|
41
|
+
DEPTH BOUND: trace only paths that can reach the unit's boundary or whose guarantees
|
|
42
|
+
that boundary relies on. Stop a line of investigation as soon as the invariant is
|
|
43
|
+
settled either way, and record the result in the ledger as covered, candidate, or
|
|
44
|
+
blocked (or as `uncovered`) instead of continuing to search.
|
|
45
|
+
|
|
46
|
+
TEST SAD PATHS AND DISAGREEMENTS. Check absent, empty, zero, negative, maximum,
|
|
47
|
+
over-limit, duplicate, mixed encoding, stale, revoked, reordered, concurrent,
|
|
48
|
+
partially migrated, failed dependency, and rollback state only where the interface
|
|
49
|
+
accepts them. Compare canonicalization and units at every parser or policy handoff.
|
|
50
|
+
For multi-step issues, treat each output as a prerequisite and do not assume a later
|
|
51
|
+
boundary. If any prerequisite is not established, record a blocker.
|
|
52
|
+
|
|
53
|
+
When a proposed high or critical candidate reveals a reusable root cause, search the
|
|
54
|
+
units you own for lexical, structural, and logical variants. Consolidate the same root
|
|
55
|
+
cause, but establish each variant's conditions and impact independently. Record a
|
|
56
|
+
variant with no current coverage unit as `uncovered`.
|
|
57
|
+
|
|
58
|
+
USE THE NARROWEST CHECK THAT SETTLES THE CLAIM. Prefer reading code. When a local
|
|
59
|
+
check is worth running (an existing unit test, a minimal function harness, a small
|
|
60
|
+
malformed fixture, a locally rendered policy), follow the execution safety rules in
|
|
61
|
+
SKILL.md: ask the user before running anything that executes code from the audited
|
|
62
|
+
target, run it offline on dummy data, never with network access or against a live
|
|
63
|
+
system, and do not install or fetch tools.
|
|
64
|
+
|
|
65
|
+
Record the exact input, command, and minimum result. For the environment, record only
|
|
66
|
+
variable names and safe non-secret values needed to reproduce the check. Never capture
|
|
67
|
+
the ambient environment, credentials, authentication state, or unrelated host paths.
|
|
68
|
+
Never stress availability, invoke a live target, use a real credential, publish an
|
|
69
|
+
artifact, or continue past the minimum observed effect.
|
|
70
|
+
|
|
71
|
+
A deployment, browser, provider, broker, OS, proxy, package, secret, or identity fact
|
|
72
|
+
outside source is not proof either way. If one such fact is decisive, record a
|
|
73
|
+
needs_validation candidate with the exact missing observation and a safe owner-observed
|
|
74
|
+
check. If a check needs runtime proof you may not run, that is also needs_validation.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### Candidate gate
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
1. A candidate needs a complete repository-relative source trace and evidence for the
|
|
81
|
+
claimed root cause, including the strongest source-visible control.
|
|
82
|
+
2. A proposed confirmed record needs a bounded observed result (a source-proven wrong
|
|
83
|
+
result, or an approved local check), meaningful impact across a stated boundary,
|
|
84
|
+
complete conditions, and no visible preventing layer.
|
|
85
|
+
3. Do not strengthen a crash into code execution, ordinary work into shared availability,
|
|
86
|
+
or a same-principal action into privilege gain.
|
|
87
|
+
4. If a required fact is not source-visible or locally observable, use
|
|
88
|
+
needs_validation. Name exact blockers; do not give it severity or speculative completion.
|
|
89
|
+
5. A missing best practice with no affected principal/resource is excluded or hardening,
|
|
90
|
+
not a finding. A candidate disproved by source is not needs_validation.
|
|
91
|
+
6. Use the same source-derived fingerprint for the same root cause in every state.
|
|
92
|
+
It must match `^[A-Za-z0-9][A-Za-z0-9._:/@+-]*$` and must not include a line,
|
|
93
|
+
wave, pass label, severity, or verdict.
|
|
94
|
+
7. Record no candidate when nothing survives these gates.
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Local validation boundaries
|
|
98
|
+
|
|
99
|
+
Local execution is for confirmation, not impact expansion, and always needs the user's approval first:
|
|
100
|
+
|
|
101
|
+
- **Allowed (with approval):** the repository's own existing unit and integration tests; small offline fixture processing on dummy data; minimal function harnesses; rendered manifests and policy evaluation with dummy identities; mocked external or paid calls. Run them offline with no credentials.
|
|
102
|
+
- **Disallowed:** live or deployed traffic; network access of any kind from target code; starting servers that accept outside connections; network dependency installation; real accounts or credentials; production data; shared queues, cloud resources, runners, registries, signing or release services; publishing; stress, saturation, or cost generation; any work after the minimum dummy-data boundary result.
|
|
103
|
+
|
|
104
|
+
You have no OS sandbox, so the boundary is your judgment plus the user's approval. If you cannot be confident a check is safe and offline, do not run it; represent the exact blocker in `needs_validation`. A missing safe check does not erase a source-grounded candidate.
|
|
105
|
+
|
|
106
|
+
## Recording results
|
|
107
|
+
|
|
108
|
+
After hunting a unit, update that one ledger unit. The unit ends in one of three dispositions:
|
|
109
|
+
|
|
110
|
+
- `covered`: the unit has a nonempty `reviewed_paths` and nonempty checks, no unresolved fact, and no candidate.
|
|
111
|
+
- `candidate`: the same owned evidence plus linked candidate fingerprints. It is the only state that carries fingerprints.
|
|
112
|
+
- `blocked`: owned partial review with nonempty paths, checks, and unresolved facts but no fingerprint.
|
|
113
|
+
|
|
114
|
+
Each check you record in the unit's `local_checks` has this shape:
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"agent_id": "main-w1",
|
|
119
|
+
"reviewed_paths": ["repo/relative/path owned by this check"],
|
|
120
|
+
"invariant": "specific control checked for this unit",
|
|
121
|
+
"method": "source|local",
|
|
122
|
+
"result": "what source or the bounded check established",
|
|
123
|
+
"artifact": "agents/main-w1/artifacts/file for local, null for source"
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
All source paths are repository-relative, never absolute or traversal paths. The unit-level `reviewed_paths` is exactly the union of its checks' paths. A `source` check uses `artifact: null`. A `local` check uses one plain regular file you saved beneath `agents/<check.agent_id>/artifacts/` (SKILL.md, Files and retained evidence). Never link an output-root file or another check owner's artifact.
|
|
128
|
+
|
|
129
|
+
Keep each candidate as a working record, schema-shaped except that it uses `proposed_verdict` in place of `verdict`:
|
|
130
|
+
|
|
131
|
+
- `proposed_verdict: "confirmed"`: include every field required by the `confirmed` branch of `report-schema.json` other than `verdict`: `fingerprint`, title, description, `root_cause`, `intended_behavior`, ordered `trace`, `evidence`, `conditions`, target-neutral `execution`, `remediation`, `severity`, and `confidence`. The execution instructions describe only the bounded check already performed or the source-level proof. `payloads` holds the minimum test input, fixture, or native invocation. `observed_result` records actual output. Overall severity must not exceed observed impact.
|
|
132
|
+
- `proposed_verdict: "needs_validation"`: include every field required by that schema branch other than `verdict`: `fingerprint`, title, description, `claimed_root_cause`, ordered `trace`, `evidence`, nonempty `blockers`, and `validation_plan` with at least one applicable `local` or `deployment` step. Do not invent an inapplicable context. Do not include severity, execution, remediation, reason, or a confirmed `root_cause`. `deployment` is an owner-observed check, not a request to probe a live target.
|
|
133
|
+
|
|
134
|
+
A trace with several entries begins at `entrypoint`, ends at `sink`, and labels intermediate steps `propagation`.
|
|
135
|
+
|
|
136
|
+
Keep `hardening` notes (concrete non-findings) in a bookkeeping field on the relevant ledger units so Phase 6 can report them. Run `validate-coverage-ledger.cjs` after each batch of updates; an invalid ledger must be fixed before you continue. A unit whose conclusion you cannot support stays `planned` for another attempt. Untouched units become unassigned `deferred` units with empty evidence and a reason; do not hide partial evidence in `deferred`.
|
|
137
|
+
|
|
138
|
+
Consolidate candidates by fingerprint and then by root cause. One root cause that exposes several entry paths or effects is one candidate with the strongest complete trace. Related but independent missing controls use separate fingerprints. Record duplicate fingerprints in the relevant ledger unit and do not send duplicates to the disprove pass.
|
|
139
|
+
|
|
140
|
+
## Coverage review waves
|
|
141
|
+
|
|
142
|
+
After each hunting wave, do a coverage review before starting another. This is a separate step: re-read `architecture.md`, the full ledger, the current candidate fingerprints, and the prior-ledger gap summary, as if reviewing someone else's coverage. Write down the result as this object (in your notes, not a file):
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"missing_units": [
|
|
147
|
+
{
|
|
148
|
+
"surface": "...",
|
|
149
|
+
"boundary": "...",
|
|
150
|
+
"subsystem": "...",
|
|
151
|
+
"attack_class": "...",
|
|
152
|
+
"starting_paths": ["repo/relative/path"],
|
|
153
|
+
"selected_companion_blocks": ["FILE.md#section"],
|
|
154
|
+
"excluded_blocks": [{"block": "FILE.md#section", "reason": "..."}],
|
|
155
|
+
"reason": "source-backed coverage gap"
|
|
156
|
+
}
|
|
157
|
+
],
|
|
158
|
+
"reassign_ids": ["existing-id-that-did-not-close"],
|
|
159
|
+
"resolved_prior_leads": ["fingerprint"],
|
|
160
|
+
"stop": false
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Look for unmapped entry points, unchecked parallel paths, missing lifecycle modes, selected companion classes without a unit, unjustified exclusions, units closed without paths/checks, and prior `needs_validation` or changed-source gaps that no unit addresses. The review proposes coverage, not findings. `stop` is true only when you accept no `missing_units` and no `reassign_ids`. For each fingerprint in `resolved_prior_leads`, mark the linked unit or prior-lead entry resolved and record the source-backed reason.
|
|
165
|
+
|
|
166
|
+
Reject proposed units outside the review scope or the source/local boundary, derive canonical IDs for accepted units, and deduplicate them against current units. A prior same-source completed unit may supply evidence; prior `deferred`, `blocked`, `out_of_scope`, or changed-source units become current work and never suppress an accepted unit. Fail rather than merge a canonical ID collision. For each legitimate `reassign_id` with live `blocked`, `covered`, or `candidate` evidence, append that exact terminal record to the unit's `attempts` with the review's source-backed `reassignment_reason`. Increment the live `wave`; the next attempt uses the new pass label `main-w<wave>` and starts `in_progress` with empty live evidence. Write only the new attempt's evidence into the live fields, and never copy an archived pass label's checks or artifacts into it. Sort IDs and validate the ledger before the next wave.
|
|
167
|
+
|
|
168
|
+
In `standard` and `deep`, when a review reports no accepted `missing_units` or legitimate `reassign_ids` and no `planned` units remain, do one more clean review from scratch (re-read the ledger and source starting paths again, without your previous review notes). Complete coverage only when that second review also returns nothing. If it finds work, queue it and repeat the wave, review, and clean review. If time or context force an early stop, mark every untouched unit `deferred`, preserve the reason, and disclose the gap in the report. Never use a silent wave cap as evidence of complete coverage.
|
|
169
|
+
|
|
170
|
+
The run profile bounds this loop. A `quick` run has exactly one hunting wave followed by exactly one coverage review. Add each accepted `missing_unit` to the current ledger and mark it `deferred` with reason `quick_profile_final_review`. For each legitimate evidence-bearing `reassign_id`, archive the live terminal state in `attempts`, increment `wave`, and set the live state to unassigned `deferred` with empty evidence and reason `quick_profile_final_review`. Do not start a second hunting wave or another review. In a scoped run, record out-of-scope gaps you notice as `out_of_scope` with the review's reason instead of assigning them. `quick` is a pre-declared early stop, not evidence of complete coverage.
|
|
171
|
+
|
|
172
|
+
If surviving candidates exceed what you can disprove-check in the time and context you have left, follow the incomplete-run rule in `SKILL.md`: stop hunting, run the disprove pass in fingerprint order, retain unchecked units as unresolved candidates, and never present them as findings.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 Cloudflare, Inc.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Memory Safety, Binary, and Kernel Hunting
|
|
2
|
+
|
|
3
|
+
#### When to use this file
|
|
4
|
+
|
|
5
|
+
Reach for this file when the target processes untrusted bytes in a memory-unsafe or privileged context: C/C++/Objective-C, Rust `unsafe`, FFI, kernel modules and drivers, parsers and decoders, network daemons, firmware, binary loaders, language runtimes, and JITs. Use `PROTOCOLS-RPC-AND-MESSAGING.md` for protocol authorization and state-machine logic, and this file for process integrity, memory safety, ABI boundaries, and loader behavior.
|
|
6
|
+
|
|
7
|
+
Pick relevant classes from Phase 1 and split large targets by parser, allocator/lifetime, FFI, concurrency, loader, runtime, or privileged interface.
|
|
8
|
+
|
|
9
|
+
## Core discipline (apply throughout this domain)
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
- Re-derive every bound and lifetime from attacker-controlled inputs and all callers. Validate against the worst accepted case, not a typical test vector.
|
|
13
|
+
- A panic, sanitizer finding, or crash proves a defect only when a realistic untrusted input reaches it. Do not infer memory corruption, code execution, or shared availability impact from a label alone.
|
|
14
|
+
- Validate in a local harness with sanitizers, deterministic concurrency tests, existing fuzz targets, and debugger-assisted fault classification. Stop after proving the violated invariant and observable impact; do not develop post-corruption techniques.
|
|
15
|
+
- Assembly, JIT code, custom allocators, intra-object accesses, and foreign libraries can escape sanitizer coverage. Identify which relevant instructions are instrumented.
|
|
16
|
+
- Classify as `confirmed` only after source evidence and bounded local validation establish the defect and effect. Use `needs_validation` when ABI, allocator, architecture, feature, deployment, or reachability facts remain unknown.
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Bounds, integer, and representation attack classes
|
|
20
|
+
|
|
21
|
+
**Out-of-bounds read or write**
|
|
22
|
+
A length, offset, index, or terminator reaches a fixed or allocated buffer without a correct bound. Recalculate available headroom after prefixes, alignment, padding, and terminators. Check both source and destination capacity, and whether a short input is read before its declared length is trusted.
|
|
23
|
+
|
|
24
|
+
**Integer overflow, underflow, truncation, and signedness**
|
|
25
|
+
Review attacker-controlled arithmetic before allocation, copy, loop, indexing, and pointer operations. High-hit patterns include `a - b` with `b > a`, `count * element_size`, additions near the type maximum, negative values converted to unsigned, 64-bit lengths narrowed to 32-bit fields, and sentinel values such as `-1` becoming a large size. Confirm which checked representation is later used.
|
|
26
|
+
|
|
27
|
+
**Unit and pointer-depth confusion**
|
|
28
|
+
Code mixes bytes, elements, code units, pages, words, wire units, or nested pointer element sizes. Compare the unit at parse, validation, allocation, API boundary, and copy. A bounds check using the same wrong unit as the allocation is still wrong.
|
|
29
|
+
|
|
30
|
+
**Uninitialized or partially initialized data**
|
|
31
|
+
A buffer, padding, struct field, or vector capacity is returned, compared, hashed, serialized, or passed across a trust boundary before initialization. Require an observable consumer and realistic output length; stack allocation by itself is not disclosure.
|
|
32
|
+
|
|
33
|
+
## Lifetime, type, and concurrency attack classes
|
|
34
|
+
|
|
35
|
+
**Use-after-free, stale view, and double free**
|
|
36
|
+
Owners are released while callbacks, wait queues, timers, iterators, borrowed slices, or cached raw pointers can still use them. Review every error, cancellation, close, and realloc path. For embedded notification anchors, each free path must drain or detach all observers.
|
|
37
|
+
|
|
38
|
+
**Type confusion and invalid downcast**
|
|
39
|
+
A tag, vtable, union discriminator, object kind, or foreign handle is checked differently from the representation later read. Look for unchecked dynamic casts, stale tags after reuse, and serialized types whose validated element differs from the element consumed. Confirm a wrong-type read or write locally without extending the test beyond the violated invariant.
|
|
40
|
+
|
|
41
|
+
**Reference-count and ownership races**
|
|
42
|
+
Non-atomic retain/release, a check followed by an unlocked use, or inconsistent ownership across threads can free or mutate an object during access. Compare fast, error, shutdown, and compatibility paths for the same lock and ownership rules.
|
|
43
|
+
|
|
44
|
+
**Shared-state races and TOCTOU**
|
|
45
|
+
Concurrent parser streams, global caches, lazy initialization, signal handlers, and resource teardown can invalidate bounds, policy, or pointers established earlier. Verify the race with a repeatable local schedule, barrier, or thread sanitizer; a hypothetical interleaving without a security-relevant state transition remains `needs_validation`.
|
|
46
|
+
|
|
47
|
+
**Lock-order, deadlock, and starvation**
|
|
48
|
+
Externally reachable operations acquire locks in inconsistent order or hold them across callbacks and blocking I/O. Report under availability only when bounded input can stop shared progress; otherwise record it for fixing as a concurrency defect.
|
|
49
|
+
|
|
50
|
+
## FFI and ABI attack classes
|
|
51
|
+
|
|
52
|
+
**Pointer-length and ownership contract mismatch**
|
|
53
|
+
Caller and callee disagree on who allocates, frees, pins, or mutates a buffer, how long a pointer remains valid, or whether a length is bytes or elements. Trace both sides of every `extern`, CGo/JNI/Python/native binding, and generated wrapper. Check null, zero length, aliasing, and callback retention.
|
|
54
|
+
|
|
55
|
+
**Layout, alignment, and enum disagreement**
|
|
56
|
+
Foreign code receives a struct, bitfield, packed record, callback signature, integer width, enum, or calling convention that differs by architecture or build flag. Verify `repr`, packing, alignment, endianness, and ABI-specific types. An in-repo declaration mismatch can be confirmed locally; an opaque foreign implementation requires `needs_validation`.
|
|
57
|
+
|
|
58
|
+
**Unwind, exception, and thread-affinity violations**
|
|
59
|
+
Exceptions or panics cross an ABI that forbids unwinding, callbacks run after teardown, or APIs requiring one runtime thread are invoked elsewhere. Review error conversion and cancellation. Confirm whether the process aborts or state is corrupted before assigning impact.
|
|
60
|
+
|
|
61
|
+
## Binary loading and runtime attack classes
|
|
62
|
+
|
|
63
|
+
**Library, plugin, and executable search-order trust**
|
|
64
|
+
A privileged process loads a library, plugin, runtime image, or helper from a path writable by a less-trusted principal, or resolves a bare name through an attacker-influenceable working directory or environment. Compare intended installation ownership with each fallback and compatibility search path. A user loading their own plugin into their own process is not a boundary violation.
|
|
65
|
+
|
|
66
|
+
**Missing artifact identity or signature binding**
|
|
67
|
+
A loader verifies one file or metadata record but maps a different image because path resolution, file replacement, architecture slices, or embedded resources are not bound to the check. Supply-channel authenticity belongs in `SUPPLY-CHAIN-AND-RELEASE.md`; this class covers the local verification-to-map gap.
|
|
68
|
+
|
|
69
|
+
**Malformed binary metadata and relocation handling**
|
|
70
|
+
Offsets, counts, sections, relocations, symbols, bytecode, or debug metadata are trusted before range, overlap, and representation checks. Test parsers with bounded local fixtures and sanitizers. Separate memory corruption from a safely rejected malformed file.
|
|
71
|
+
|
|
72
|
+
**JIT and generated-code consistency**
|
|
73
|
+
Validator, interpreter, optimizer, and generated code disagree about types, bounds, side effects, or lifetime. Diff optimized and unoptimized paths using the same local input. Confirm a process-integrity effect; output variance that stays within language semantics is not a finding.
|
|
74
|
+
|
|
75
|
+
**Unload, reload, and teardown safety**
|
|
76
|
+
Live function pointers, callbacks, worker threads, or data views survive module unload or runtime reset. Review shutdown and failed-load cleanup as closely as startup.
|
|
77
|
+
|
|
78
|
+
## Kernel and privileged-interface attack classes
|
|
79
|
+
|
|
80
|
+
**User-copy bounds and repeated reads**
|
|
81
|
+
A syscall, ioctl, driver, or kernel parser derives a trusted fact from user memory then reads the same mutable address again. Copy the full request once or revalidate the later copy. Also audit size, direction, and access checks at each user-copy primitive.
|
|
82
|
+
|
|
83
|
+
**Privileged object lifecycle and dispatch consistency**
|
|
84
|
+
Externally reachable objects have unbalanced retain/release, teardown without observer drain, unchecked selector/table indices, or duplicated compatibility paths that omit a guard. Diff each dispatch and free path side by side.
|
|
85
|
+
|
|
86
|
+
**Under-authorized powerful interfaces**
|
|
87
|
+
A device node, admin socket, helper, or management API validates shape but not the caller's authority over the resource. Establish actual interface ownership and reachability; permissions or sandbox policy outside the repository make this `needs_validation`.
|
|
88
|
+
|
|
89
|
+
## Universal moves (apply across the above)
|
|
90
|
+
|
|
91
|
+
- Audit fixes and duplicated paths for the same source-to-sink shape. A check in one caller, architecture, protocol role, feature flag, or compatibility path does not protect its siblings.
|
|
92
|
+
- Build a table for every parser or FFI boundary: accepted length/type, checked representation, allocation owner, consumer, thread, and teardown. Most native findings are one disagreement in that table.
|
|
93
|
+
- Use existing corpora and small locally generated boundary fixtures. Save exact sanitizer/runtime output and the input property that triggers it; avoid large resource consumption and any live target.
|
|
94
|
+
|
|
95
|
+
## Validation rules (apply before reporting ANY finding here)
|
|
96
|
+
|
|
97
|
+
1. Establish a realistic untrusted entry and exact operation that violates a bounds, type, lifetime, ABI, concurrency, loader, or authority invariant.
|
|
98
|
+
2. Classify the observable effect: invalid read, invalid write, stale alias, wrong object, uninitialized output, unauthorized image load, deadlock, or safe process termination. Do not claim a stronger effect than observed.
|
|
99
|
+
3. Run the narrowest local harness, existing test, sanitizer, or fuzzer needed to reproduce the effect. Verify sanitizer coverage of the faulting operation and record architecture/build conditions.
|
|
100
|
+
4. For concurrency, use a deterministic schedule or sanitizer trace. For binary loading, prove the checked identity differs from the mapped identity and name the lower-trust writer.
|
|
101
|
+
5. Return `confirmed` findings only with exact input, source trace, and observed result. Return `needs_validation` for a specific unresolved reachability, ABI, build, deployment, or runtime fact and state the bounded check needed.
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Protocols, RPC, and Messaging Hunting
|
|
2
|
+
|
|
3
|
+
#### When to use this file
|
|
4
|
+
|
|
5
|
+
Reach for this file when the target uses gRPC, GraphQL transports, Cap'n Proto, Thrift, Protobuf, custom binary protocols, streaming RPC, webhooks, brokers, queues, pub/sub, or event buses. It covers peer identity, logical message interpretation, routing, replay, ordering, and delivery semantics. Use `MEMORY-SAFETY-AND-BINARY.md` for parser memory safety, `WEB-PROTOCOL-AND-AUTH.md` for HTTP framing, and `RESOURCE-EXHAUSTION-AND-AVAILABILITY.md` for availability impact.
|
|
6
|
+
|
|
7
|
+
Split large systems by producer/consumer pair, external/internal peer role, synchronous RPC, streaming, and asynchronous message path.
|
|
8
|
+
|
|
9
|
+
## Core discipline (apply throughout this domain)
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
- "Internal" is not authentication. Name the peer identity at every hop and show how it becomes the application principal used for authorization.
|
|
13
|
+
- Schema validation proves message shape, not provenance, resource authority, ordering, or safe values. Follow decoded fields to policy and side effects.
|
|
14
|
+
- Broker guarantees and application guarantees differ. Write down retry, ordering, acknowledgement, deduplication, and transaction behavior before evaluating state changes.
|
|
15
|
+
- Parser disagreement requires two concrete consumers, schema versions, or wire representations and one security-relevant divergent value.
|
|
16
|
+
- Use `confirmed` for source-complete paths plus bounded local producer/consumer tests. Use `needs_validation` for broker ACL, service-mesh identity, topic attachment, or compatibility behavior outside the repository.
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Framing, schema, and interpretation attack classes
|
|
20
|
+
|
|
21
|
+
**Message boundary and canonicalization disagreement**
|
|
22
|
+
Components disagree on length, compression, duplicate fields, unknown fields, encoding, numeric width, normalization, or envelope/body precedence. Compare generated and custom parsers, gateways, language bindings, and version converters. Confirm which principal, resource, or operation differs after decoding.
|
|
23
|
+
|
|
24
|
+
**Union, enum, and default confusion**
|
|
25
|
+
Unknown variants, missing discriminators, zero values, default privileges, or compatibility mappings reach code that assumes a validated case. Review exhaustive dispatch, default branches, and how old consumers interpret newly added fields.
|
|
26
|
+
|
|
27
|
+
**Envelope and payload identity mismatch**
|
|
28
|
+
Authorization uses trusted-looking routing or envelope metadata while the handler acts on a conflicting tenant, account, subject, object, or sender in the body. Identify which source is authoritative and ensure clients cannot override it.
|
|
29
|
+
|
|
30
|
+
## RPC identity and authorization attack classes
|
|
31
|
+
|
|
32
|
+
**Interceptor and method-path inconsistency**
|
|
33
|
+
An authn/authz interceptor applies to unary methods but not streams, reflection, health, gateway-transcoded paths, compatibility services, or individual stream messages. Compare every registration and route to the same operation.
|
|
34
|
+
|
|
35
|
+
**Peer identity to application-principal confusion**
|
|
36
|
+
mTLS, workload identity, bearer metadata, forwarded identity, or broker credentials authenticate a channel, but a caller-controlled field selects the user or tenant. The channel identity and claimed principal must be bound by deterministic policy.
|
|
37
|
+
|
|
38
|
+
**Per-item and streaming authorization gaps**
|
|
39
|
+
A stream, subscription, batch, or bulk message is authorized once, then later items name different resources or continue after role, membership, or token revocation. Re-check where scope can change and bind subscriptions to their original principal.
|
|
40
|
+
|
|
41
|
+
**Callback and reply-correlation confusion**
|
|
42
|
+
Predictable, reused, or cross-tenant correlation IDs let a response, webhook, cancellation, or acknowledgment satisfy another caller's pending operation. Bind each outstanding request to authenticated peer, tenant, operation, and lifecycle.
|
|
43
|
+
|
|
44
|
+
## Broker and queue isolation attack classes
|
|
45
|
+
|
|
46
|
+
**Topic, routing-key, and subscription scope gaps**
|
|
47
|
+
A publisher or subscriber can select another tenant's topic, wildcard, consumer group, partition, reply queue, or dead-letter route. Check broker-enforced ACLs where visible and application-side namespace construction. Tenant text inside a payload is not isolation.
|
|
48
|
+
|
|
49
|
+
**Dead-letter, retry, and diagnostic disclosure**
|
|
50
|
+
Messages routed to dead-letter queues, error topics, tracing, or operator views contain secrets or cross-tenant payloads accessible to a lower-trust consumer. Review policy and redaction at the failure path, not just normal delivery.
|
|
51
|
+
|
|
52
|
+
**Untrusted producer treated as control plane**
|
|
53
|
+
A message body can declare itself an admin event, provider callback, replication record, or migration instruction without an independently authenticated producer and event type. Verify signatures and source/account/audience binding before privileged handling.
|
|
54
|
+
|
|
55
|
+
## Replay, ordering, and transaction attack classes
|
|
56
|
+
|
|
57
|
+
**Duplicate delivery and idempotency gaps**
|
|
58
|
+
Retries or redelivery repeat a side effect because deduplication is absent, occurs after mutation, or uses a key that collides across tenants or operations. Confirm the broker's delivery model and the side effect that is not naturally idempotent.
|
|
59
|
+
|
|
60
|
+
**Out-of-order and stale message acceptance**
|
|
61
|
+
Older state, revoked membership, canceled work, or pre-step-up authorization arrives after newer state and overwrites it. Review sequence/version checks, tombstones, partition changes, and restore/replay workflows.
|
|
62
|
+
|
|
63
|
+
**Acknowledgment/commit ordering defects**
|
|
64
|
+
Acknowledgment occurs before durable commit and loses security-relevant work, or commit happens before an unreliable acknowledgment and duplicates a mutation. Evaluate transactional outbox/inbox behavior and failure recovery.
|
|
65
|
+
|
|
66
|
+
**Partial multi-consumer transitions**
|
|
67
|
+
Several consumers jointly implement one authorization or business transition, but retries and partial failure leave only a subset committed. Identify invariants that must become durable atomically or compensate with current authorization.
|
|
68
|
+
|
|
69
|
+
## Universal moves (apply across the above)
|
|
70
|
+
|
|
71
|
+
- Draw producer → broker/transport → gateway → consumer → storage for each message family. At each hop record authenticated peer, authoritative tenant/resource fields, validation, and side effect.
|
|
72
|
+
- Feed the same small fixture to every in-repo schema version or language binding. Test duplicate, missing, unknown, boundary, replayed, and reordered messages without producing load.
|
|
73
|
+
- Compare normal, retry, dead-letter, replay, migration, reflection, stream, and gateway-transcoded routes. Security policy must survive transport changes.
|
|
74
|
+
|
|
75
|
+
## Validation rules (apply before reporting ANY finding here)
|
|
76
|
+
|
|
77
|
+
1. Name the realistic producer or peer, accepted message, authenticated channel identity, affected principal/resource, and unauthorized mutation or disclosure.
|
|
78
|
+
2. For disagreement claims, cite both parsers/consumers and the divergent decoded value. Safe rejection by either side prevents confirmation.
|
|
79
|
+
3. For replay/order claims, establish actual delivery guarantees and reproduce the invariant failure with a bounded local/in-memory transport.
|
|
80
|
+
4. For authorization and isolation, verify all interceptor, broker ACL, gateway, and consumer layers visible in source. External attachments make the candidate `needs_validation`.
|
|
81
|
+
5. Return `confirmed` only with the complete message lifecycle and observed meaningful result. Return `needs_validation` with the exact broker, service identity, route, or delivery fact required.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# Reconnaissance
|
|
2
|
+
|
|
3
|
+
### Phase 1: Map the source and plan coverage
|
|
4
|
+
|
|
5
|
+
You initialize `run-metadata.json`, then create the coverage ledger before hunting. Reconnaissance reads the target and locally available build/configuration state only. It does not contact deployed endpoints, external identity providers, registries, brokers, cloud APIs, or other shared services, and it does not run target code.
|
|
6
|
+
|
|
7
|
+
Work through these four reconnaissance passes in order yourself, in the main thread. Keep short notes of the source facts each pass finds (with repository-relative file:line references); you will use them for `architecture.md` and the ledger. Do not write files until the architecture step below.
|
|
8
|
+
|
|
9
|
+
**Pass 1a: Product, stack, and local operation**
|
|
10
|
+
|
|
11
|
+
1. Product type, users, operators, and ordinary trust-sensitive actions.
|
|
12
|
+
2. Languages, frameworks, build system, runtimes, and locally visible deployment models.
|
|
13
|
+
3. Repository-relative entry points and subsystem boundaries.
|
|
14
|
+
4. Exact build and test commands that could run offline with local dependencies, their expected write locations, and the target-controlled inputs they process. Do not run them during reconnaissance.
|
|
15
|
+
5. Comparable software or protocol visible from local documentation and dependencies. If no useful comparison is source-grounded, say so.
|
|
16
|
+
6. Missing local toolchains or runtime facts that limit bounded execution.
|
|
17
|
+
|
|
18
|
+
**Pass 1b: Principals, authority, and controls**
|
|
19
|
+
|
|
20
|
+
Read all source that establishes identity, authorization, isolation, and privilege. Map:
|
|
21
|
+
1. Each lower-trust principal and the actions it has by design.
|
|
22
|
+
2. Authentication or peer identity at each entry surface.
|
|
23
|
+
3. Per-resource authorization and tenant/owner scope.
|
|
24
|
+
4. Process, browser, workload, CI, plugin, model/tool, device, or local-IPC authority.
|
|
25
|
+
5. Privilege changes, confirmation, revocation, recovery, and fallback paths.
|
|
26
|
+
6. Which controls are source-visible and which depend on an unobserved deployment fact.
|
|
27
|
+
Record trust boundaries and control locations. Do not infer live reachability.
|
|
28
|
+
|
|
29
|
+
**Pass 1c: Entry surfaces, copies, and sinks**
|
|
30
|
+
|
|
31
|
+
Inventory every source-visible place external or lower-trust input enters: HTTP/browser, RPC/message/protocol, files/archive/document, CLI/env/config, plugins/dependencies/CI, cloud events/IAM selectors, model context/tool arguments, mobile/deep-link/webview, and local IPC. For each surface, follow major transformations, stored or derived copies, and security-relevant sinks. Record source-visible limits and parallel paths to the same effect. Be complete, but do not execute or send inputs.
|
|
32
|
+
|
|
33
|
+
**Pass 1d: Local execution and deployment visibility**
|
|
34
|
+
|
|
35
|
+
Read tests, build definitions, manifests, packaging, and maintained environment overlays. Record:
|
|
36
|
+
1. Small offline tests or existing fixtures that could validate trust boundaries with dummy data, each of which would still need the user's approval before running (SKILL.md, Universal execution safety).
|
|
37
|
+
2. Commands that would fetch dependencies, publish artifacts, contact paid/provider APIs, start network listeners, or affect shared state; mark them prohibited for this run.
|
|
38
|
+
3. Deployed controls and attachments that source cannot establish and therefore require needs_validation if decisive.
|
|
39
|
+
4. The final active source path for each deployment mode only where the repository selects it deterministically.
|
|
40
|
+
|
|
41
|
+
After the four passes, add focused passes for materially distinct deployment modes or subsystems they did not map. If you cannot reach one, seed the unmapped area as a `deferred` ledger unit with reason `context_or_time_exhausted` and disclose the gap in the report.
|
|
42
|
+
|
|
43
|
+
## Prior-run input
|
|
44
|
+
|
|
45
|
+
Before selecting work, read every available prior `coverage-ledger.json` and `findings.json` for the same repo:
|
|
46
|
+
|
|
47
|
+
- Compare the source locations, controls, conditions, and source-derived identity for every prior record and unit against the current source.
|
|
48
|
+
- Carry an unchanged prior `confirmed` record into the current candidate set, with the same fingerprint, only when its relevant source, conditions, and qualifying evidence still apply. Link it to a current `planned` unit with `prior_status: "prior_confirmed_same_source"` and put only that root cause on the hunting exclusion list. The Phase 3 disprove pass that re-checks the carried record becomes that unit's assignment owner; its source re-check is the unit's first check and moves the unit to `candidate` with the carried fingerprint.
|
|
49
|
+
- Build a current planned `prior_confirmed_changed_source` revalidation unit when any relevant source or condition changed. Do not exclude that root cause from hunting or assume the prior verdict still applies.
|
|
50
|
+
- Build current work units for every prior `needs_validation`, `deferred`, `blocked`, `out_of_scope`, and changed-source unit. These states are priority input, never deduplication or suppression keys.
|
|
51
|
+
- Carry a still-blocked prior `needs_validation` record with the same fingerprint only after current source supports its trace. Link it to a current `planned` unit with `prior_status: "prior_needs_validation"`; the record keeps the unresolved blocker. The Phase 3 disprove pass that re-checks the carried record becomes that unit's assignment owner; its re-check is the unit's first check and moves the unit to `candidate` with the carried fingerprint. Include the record in final verification.
|
|
52
|
+
- Treat prior rejected records as stale claims unless current evidence changes the failed trace or missing condition. An unchanged rejection suppresses only that exact claim, not review of the coverage unit.
|
|
53
|
+
- Record missing or incompatible ledgers instead of treating them as empty coverage.
|
|
54
|
+
|
|
55
|
+
State paths and source refs used in `run-metadata.json`. Summarize only the coverage consequences in `architecture.md`.
|
|
56
|
+
|
|
57
|
+
## Architecture summary and companion selection
|
|
58
|
+
|
|
59
|
+
Write `<output-dir>/architecture.md`, with a hard cap of about 1,000 words. Include:
|
|
60
|
+
|
|
61
|
+
1. Product, principals, normal authority, and protected resources.
|
|
62
|
+
2. The comparable-software baseline from Pass 1a, when one is source-grounded: what security trade-offs the comparable accepts. Use it to calibrate effort and severity, never to dismiss a demonstrated finding; if the comparable shares a defect pattern that has mattered in practice, that strengthens the finding. Omit this line when no meaningful comparable exists.
|
|
63
|
+
3. Tech stack, source-visible deployment paths, and offline build/test limits.
|
|
64
|
+
4. Entry surfaces and the important source-to-sink or lifecycle paths.
|
|
65
|
+
5. Trust boundaries and the strongest source-visible control on each.
|
|
66
|
+
6. Repository-relative starting paths.
|
|
67
|
+
7. Prior coverage gaps, changed-source and blocked revalidation targets, and same-source confirmed exclusions.
|
|
68
|
+
8. A short companion-selection summary derived from [ATTACK-CLASSES.md](ATTACK-CLASSES.md): selected files and the source-visible boundaries that require them.
|
|
69
|
+
|
|
70
|
+
Keep the assignment-level ordinary block, selected companion blocks, and excluded blocks with reasons in each ledger unit, not in `architecture.md`. This keeps the architecture cap valid for large runs and makes the assignment map for each unit machine-checkable.
|
|
71
|
+
|
|
72
|
+
Do not select a companion file merely because the language or dependency name appears. Select it because reconnaissance found the trust-sensitive boundary described by its `When to use this file` section. Do not exclude a visible boundary just because a later pass will review a related class.
|
|
73
|
+
|
|
74
|
+
## Deterministic coverage ledger
|
|
75
|
+
|
|
76
|
+
Write `<output-dir>/coverage-ledger.json` as a top-level JSON array. Derive one unit for every material combination of entry surface, trust boundary, subsystem, and applicable ordinary or companion attack class at the granularity the run profile sets (`quick` uses one all-in-scope subsystem identity; `deep` adds lifecycle modes). For a scoped run, seed in-scope surfaces for assignment and retain discovered excluded surfaces as `out_of_scope` units so later full runs can turn them into current work.
|
|
77
|
+
|
|
78
|
+
Each dimension has a human label and a stable source-derived value in `canonical_refs`. Use the same canonical reference for the same source object across runs even if its display label changes. Suitable references include a repository-relative entry path plus exported scope, a route or message identity defined in source, the source control that defines a boundary, a repository package path, and the exact attack-class block reference. A block reference is `FILE.md#` plus the exact class name as written in bold or as a heading in that file — a stable identifier matched against the file text, not a rendered HTML anchor. For companion section blocks, use the heading text before any parenthetical qualifier (for example `Core discipline`). Do not derive references by lowercasing or slugging display labels.
|
|
79
|
+
|
|
80
|
+
Derive `coverage_id` without lossy slugs:
|
|
81
|
+
|
|
82
|
+
1. Require every reference to be Unicode NFC with valid scalar values, visible content, no control, format, line/paragraph separator, or default-ignorable code point, and no surrounding whitespace.
|
|
83
|
+
2. Encode its UTF-8 bytes with RFC 3986 percent encoding: leave only `A-Z a-z 0-9 - . _ ~` unescaped and use uppercase `%HH` for every other byte.
|
|
84
|
+
3. Join encoded `surface`, `boundary`, `subsystem`, and `attack_class` references with `::`; append encoded `lifecycle` when present.
|
|
85
|
+
|
|
86
|
+
Use the fixed canonical value `profile/quick/all-in-scope-subsystems` for the quick profile's coarsened subsystem dimension. Do not include wave number, pass label, verdict, severity, or line number in a reference or ID. Sort units lexicographically by `coverage_id` before each assignment. Fail on every duplicate ID. If duplicate IDs have different semantic fields, treat that as a canonical identity collision; never merge or silently overwrite them. The validator also rejects one semantic tuple represented by different canonical references.
|
|
87
|
+
|
|
88
|
+
Each unit records:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"coverage_id": "...",
|
|
93
|
+
"canonical_refs": {
|
|
94
|
+
"surface": "src/router.ts#POST /users/:id",
|
|
95
|
+
"boundary": "src/authz.ts#requireOwner",
|
|
96
|
+
"subsystem": "packages/api",
|
|
97
|
+
"attack_class": "ATTACK-CLASSES.md#Access control"
|
|
98
|
+
},
|
|
99
|
+
"surface": "...",
|
|
100
|
+
"boundary": "...",
|
|
101
|
+
"subsystem": "...",
|
|
102
|
+
"attack_class": "...",
|
|
103
|
+
"starting_paths": ["repo/relative/path"],
|
|
104
|
+
"ordinary_attack_class_block": "ATTACK-CLASSES.md#Access control",
|
|
105
|
+
"selected_companion_blocks": ["FILE.md#section"],
|
|
106
|
+
"excluded_blocks": [{"block": "FILE.md#section", "reason": "..."}],
|
|
107
|
+
"prior_status": "new|prior_confirmed_same_source|prior_confirmed_changed_source|prior_needs_validation|prior_deferred|prior_blocked|prior_out_of_scope|prior_covered_same_source|prior_covered_changed_source|prior_rejected_claim_changed|none",
|
|
108
|
+
"attempts": [],
|
|
109
|
+
"wave": 1,
|
|
110
|
+
"status": "planned",
|
|
111
|
+
"agent_id": null,
|
|
112
|
+
"reviewed_paths": [],
|
|
113
|
+
"local_checks": [],
|
|
114
|
+
"result_fingerprints": [],
|
|
115
|
+
"unresolved": []
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
When `lifecycle` is material, add both `canonical_refs.lifecycle` and a human `lifecycle` field. `ordinary_attack_class_block` is null only when no ordinary block applies. The selected companion list includes each applicable class plus its companion `Core discipline`, `Universal moves`, and `Validation rules`; `excluded_blocks` records every considered but unselected block and the source fact that excludes it.
|
|
120
|
+
|
|
121
|
+
You may add bookkeeping fields but keep the semantic fields above stable. In `prior_status`, `new` marks a surface first seen in this run when compatible prior ledgers exist; `none` marks a unit seeded when no compatible prior ledger is available. Prior `deferred`, `blocked`, `out_of_scope`, and changed-source units initialize as current `planned` work when now in scope. A prior same-source covered unit remains visible in the current ledger; assign changed source, important lifecycle paths, and exact conflicts first, then use the coverage review to decide whether it needs another pass.
|
|
122
|
+
|
|
123
|
+
`attempts` is an append-only archive for evidence-bearing assignments that a coverage review reopens. Before reassignment, append the prior unit's exact `wave`, `status`, `agent_id`, `reviewed_paths`, `local_checks`, `result_fingerprints`, and `unresolved`, plus the review's source-backed `reassignment_reason`. Only `blocked`, `covered`, and `candidate` states can be archived. Archived attempts retain the same state and evidence invariants as live units, use strictly increasing waves below the current wave, and retain their producing owners and artifacts. The next assignment increments `wave`, uses a fresh pass label (`main-w<wave>`), and starts with empty live evidence. If the profile or your limits prevent another assignment, increment `wave` and use live `deferred` state with null owner, empty evidence, and the stop reason. Never copy an archived pass label's checks or artifacts into the live state. A later live terminal state contains only the new attempt's evidence; the archive remains unchanged.
|
|
124
|
+
|
|
125
|
+
Enforce this state table exactly:
|
|
126
|
+
|
|
127
|
+
| Status | Unit `agent_id` | `reviewed_paths` / `local_checks` | `result_fingerprints` | `unresolved` |
|
|
128
|
+
|---|---|---|---|---|
|
|
129
|
+
| `planned` | null | empty | empty | empty |
|
|
130
|
+
| `not_applicable`, `out_of_scope`, `deferred` | null | empty | empty | nonempty reason |
|
|
131
|
+
| `in_progress` | canonical owner | empty | empty | empty |
|
|
132
|
+
| `blocked` | canonical owner | both nonempty owned partial evidence | empty | nonempty blocker |
|
|
133
|
+
| `covered` | canonical owner | both nonempty | empty | empty |
|
|
134
|
+
| `candidate` | canonical owner | both nonempty | nonempty | optional |
|
|
135
|
+
|
|
136
|
+
Pass labels (the `agent_id` field) match `^[a-z0-9][a-z0-9_-]{0,63}$` and are not Windows device names. Lowercase is mandatory, so one ledger cannot contain case-fold aliases. The unit `agent_id` records the pass label that owns the unit; use `main-w<wave>` for hunting, `main-disprove` and `main-final` for later checks. Every check records its own `agent_id` and nonempty `reviewed_paths`; the unit-level `reviewed_paths` is exactly their union. A source-only check uses `artifact: null`. A local check requires a plain regular file you saved under exactly `agents/<check.agent_id>/artifacts/` (SKILL.md, Files and retained evidence). This lets hunting-pass and disprove-pass checks coexist in one unit. Output-root files, symlinks, special files, and another check owner's artifacts are not evidence.
|
|
137
|
+
|
|
138
|
+
The ledger is the coverage claim. An architecture summary, pass count, or generic "auth reviewed" sentence is not coverage evidence. Phase 2 closes units only from the paths and checks you recorded while hunting them.
|
|
139
|
+
|
|
140
|
+
Run `node <skill-dir>/validate-coverage-ledger.cjs <output-dir>/coverage-ledger.json` after seeding, after every ledger update, and before Phase 6. The validator rejects input beyond 5 MiB, 64 nesting levels, 10,000 units, 1,000 entries in a nested collection, or 500,000 traversed values, and caps reported validation errors at 100. In practice the 5 MiB byte limit holds roughly 2,000-5,000 realistic units, so it binds before the 10,000-unit cap. Fix every error before assigning work or making a coverage claim.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Resource Exhaustion and Availability Hunting
|
|
2
|
+
|
|
3
|
+
#### When to use this file
|
|
4
|
+
|
|
5
|
+
Reach for this file when untrusted requests, messages, files, tenant state, or agent work can consume CPU, memory, disk, connections, worker slots, paid APIs, or queue capacity, or can deadlock/crash a shared service. This domain distinguishes a source-reviewable availability vulnerability from a general performance issue. Never validate by stressing a shared or live service.
|
|
6
|
+
|
|
7
|
+
Use `MEMORY-SAFETY-AND-BINARY.md` for memory-integrity defects and `PROTOCOLS-RPC-AND-MESSAGING.md` for broker delivery logic. A reachable fatal error belongs here for shared impact even when the underlying parser is covered elsewhere.
|
|
8
|
+
|
|
9
|
+
## Core discipline (apply throughout this domain)
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
- Require an input-to-cost path, a missing effective bound, and impact on another user, shared service, safety function, or operator-owned spend. Self-limiting work in the requester's own process is not a service vulnerability.
|
|
13
|
+
- A missing rate limit is not enough. Check body/message/file caps, concurrency, queues, deadlines, database constraints, upstream gateways, and per-tenant quotas before calling a path unbounded.
|
|
14
|
+
- Do not run stress, saturation, or production tests. Use asymptotic analysis, small boundary fixtures, mocked paid calls, strict local resource limits, and deterministic cancellation tests.
|
|
15
|
+
- State attacker cost, service work, persistence, scope, and recovery. One bounded input with superlinear or persistent shared effect is materially different from sustained volume.
|
|
16
|
+
- Use `confirmed` for source-visible bounds failures demonstrated safely. Use `needs_validation` when upstream caps, deployed topology, autoscaling, paid quota, or recovery behavior is outside the repository.
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Computational amplification attack classes
|
|
20
|
+
|
|
21
|
+
**Superlinear parsing, matching, or evaluation**
|
|
22
|
+
Small accepted input drives catastrophic regex backtracking, nested parsing, recursive validation, symbolic evaluation, graph traversal, template expansion, or adversarial sort/hash behavior. Derive accepted depth/cardinality and complexity, then demonstrate a bounded growth curve locally.
|
|
23
|
+
|
|
24
|
+
**Decompression and representation amplification**
|
|
25
|
+
Compressed, sparse, nested, aliased, or encoded input expands far beyond the checked transfer or file size. Verify limits after every expansion and across parser stages, including archives, images, fonts, structured documents, and protocol compression tables.
|
|
26
|
+
|
|
27
|
+
**Database and downstream query amplification**
|
|
28
|
+
A small request creates broad scans, pathological joins, fan-out, unbounded sort/aggregation, or many downstream calls because query depth, filter cardinality, pagination, or expansion fields are not bounded. Confirm authorization does not intentionally permit the same resource scope.
|
|
29
|
+
|
|
30
|
+
## Resource accumulation attack classes
|
|
31
|
+
|
|
32
|
+
**Unbounded buffering and cardinality**
|
|
33
|
+
Bodies, out-of-order streams, uploads, sessions, unique cache keys, metrics labels, log fields, subscriptions, or pending jobs accumulate without per-item and aggregate limits. Find cleanup and expiration on disconnect, timeout, cancellation, and partial parse.
|
|
34
|
+
|
|
35
|
+
**File descriptor, handle, and temporary-resource leaks**
|
|
36
|
+
Malformed or canceled work misses cleanup and retains sockets, files, database cursors, timers, subprocesses, temporary files, or object references. Confirm the leak repeats through bounded local iterations and affects a shared pool.
|
|
37
|
+
|
|
38
|
+
**Detached work after cancellation**
|
|
39
|
+
Client timeout, disconnect, canceled job, or failed authorization returns control but leaves database, model, network, or worker work running. Trace cancellation and deadline propagation through every layer.
|
|
40
|
+
|
|
41
|
+
## Quota and scheduling attack classes
|
|
42
|
+
|
|
43
|
+
**Pre-authentication work imbalance**
|
|
44
|
+
Expensive parsing, key lookup, cryptography, decompression, or external requests happen before authentication and the earliest size/rate gate. Compare minimal requester effort to shared service cost and check upstream limits.
|
|
45
|
+
|
|
46
|
+
**Quota-accounting scope and reset gaps**
|
|
47
|
+
Accounting uses attacker-influenceable IP, route, tenant, key prefix, task ID, or other dimension, allowing one principal's work to escape its intended budget or consume another principal's allocation. Review integer overflow, distributed races, retries, reconnects, and account switching.
|
|
48
|
+
|
|
49
|
+
**Worker, pool, and priority starvation**
|
|
50
|
+
Low-priority or attacker-controlled jobs hold shared locks, workers, database pools, event-loop turns, or scheduler priority needed by unrelated users. Require a path that bypasses queue/concurrency fairness or retains a slot beyond its deadline.
|
|
51
|
+
|
|
52
|
+
## Failure and recovery attack classes
|
|
53
|
+
|
|
54
|
+
**Reachable fatal error or deadlock**
|
|
55
|
+
An untrusted input reaches `panic`, abort, fatal assertion, unhandled exception, process exit, lock cycle, or infinite loop in a shared process. Confirm supervisor scope and whether one worker or the whole service becomes unavailable. A restarted isolated worker may reduce impact but does not erase the defect.
|
|
56
|
+
|
|
57
|
+
**Retry storm and fail-open amplification**
|
|
58
|
+
Timeouts, dependency errors, partially processed messages, or health-check failures trigger synchronized or unbounded retries without jitter, ceilings, circuit breaking, or deduplication. Verify one bounded failure source can create persistent aggregate work.
|
|
59
|
+
|
|
60
|
+
**Poison-record and head-of-line blocking**
|
|
61
|
+
One malformed record or message repeatedly fails at the front of a shared queue, partition, startup scan, migration, or recovery loop. Review skip/quarantine policy, offsets, and whether other tenants share the blocked unit.
|
|
62
|
+
|
|
63
|
+
**Unsafe recovery and capacity rollback**
|
|
64
|
+
A restart, restore, fallback, or cleanup path rebuilds unbounded state, ignores current quotas, or restores the input that immediately repeats failure. Recovery correctness is part of availability.
|
|
65
|
+
|
|
66
|
+
## Universal moves (apply across the above)
|
|
67
|
+
|
|
68
|
+
- Build an input-to-resource table: earliest accepted size/cardinality, work before auth, downstream fan-out, persistence, shared pool, limit and cleanup owner, recovery.
|
|
69
|
+
- Compare aggregate limits with per-object limits. Ten thousand valid one-byte items may evade a per-message cap while exhausting tenant-wide or process-wide state.
|
|
70
|
+
- Validate only in an isolated fixture with strict CPU/memory/time limits and small growth points. Mock external and paid calls and stop once the missing bound or cancellation is observable.
|
|
71
|
+
|
|
72
|
+
## Validation rules (apply before reporting ANY finding here)
|
|
73
|
+
|
|
74
|
+
1. Name untrusted input, requester work, service amplification or retained resource, shared blast radius, and recovery. Missing limits without concrete shared impact are hardening.
|
|
75
|
+
2. Confirm no source-visible upstream, parser, queue, tenant, or framework bound prevents the path. Unknown deployed controls require `needs_validation`.
|
|
76
|
+
3. For superlinear behavior, establish the accepted complexity and bounded local growth. For leaks, show repeatable retention after cleanup should occur. For fatal paths, identify process/supervisor isolation.
|
|
77
|
+
4. Prioritize by low requester work, unauthenticated reachability, cross-tenant scope, persistence, and poor recovery; do not validate with availability impact.
|
|
78
|
+
5. Return `confirmed` only with safe local proof and meaningful shared effect. Return `needs_validation` with the exact upstream limit, topology, quota, or recovery observation an owner must check.
|