@lenardangeloolajay/len-toolkit 1.1.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/LICENSE +21 -0
- package/README.md +209 -0
- package/bin/cli.js +244 -0
- package/package.json +35 -0
- package/src/installer.js +236 -0
- package/templates/configs/.editorconfig +12 -0
- package/templates/configs/sample.gitignore +8 -0
- package/templates/docs/FEATURE.md +40 -0
- package/templates/docs/HANDOFF.md +39 -0
- package/templates/docs/IMPLEMENTATION_PLAN.md +47 -0
- package/templates/docs/SPEC_INDEX.md +12 -0
- package/templates/docs/VERIFICATION.md +14 -0
- package/templates/docs/product/ARCHITECTURE.md +22 -0
- package/templates/docs/product/CONSTRAINTS.md +22 -0
- package/templates/docs/product/DATA_MODEL.md +22 -0
- package/templates/docs/product/OVERVIEW.md +22 -0
- package/templates/examples/flutter-handoff/EXERCISES.md +16 -0
- package/templates/examples/flutter-handoff/HANDOFF.md +32 -0
- package/templates/examples/flutter-handoff/docs/SPEC_INDEX.md +19 -0
- package/templates/examples/flutter-handoff/docs/evidence/FEAT-001-verification.md +14 -0
- package/templates/examples/flutter-handoff/docs/features/FEAT-001-local-note.md +40 -0
- package/templates/examples/flutter-handoff/docs/plans/FEAT-001-implementation.md +43 -0
- package/templates/examples/flutter-handoff/docs/product/ARCHITECTURE.md +24 -0
- package/templates/examples/flutter-handoff/docs/product/CONSTRAINTS.md +13 -0
- package/templates/examples/flutter-handoff/docs/product/DATA_MODEL.md +20 -0
- package/templates/examples/flutter-handoff/docs/product/OVERVIEW.md +26 -0
- package/templates/rules/.cursorrules +7 -0
- package/templates/rules/AGENTS.md +61 -0
- package/templates/rules/GEMINI.md +7 -0
- package/templates/skills/a-philosophy-of-software-design/SKILL.md +11 -0
- package/templates/skills/a-philosophy-of-software-design/a-philosophy-of-software-design.md +370 -0
- package/templates/skills/a-philosophy-of-software-design/a-philosophy-of-software-design.mini.md +46 -0
- package/templates/skills/a-philosophy-of-software-design/a-philosophy-of-software-design.nano.md +35 -0
- package/templates/skills/clean-architecture/SKILL.md +11 -0
- package/templates/skills/clean-architecture/clean-architecture.md +515 -0
- package/templates/skills/clean-architecture/clean-architecture.mini.md +49 -0
- package/templates/skills/clean-architecture/clean-architecture.nano.md +36 -0
- package/templates/skills/clean-code/SKILL.md +11 -0
- package/templates/skills/clean-code/clean-code.md +297 -0
- package/templates/skills/clean-code/clean-code.mini.md +47 -0
- package/templates/skills/clean-code/clean-code.nano.md +32 -0
- package/templates/skills/code-complete/SKILL.md +11 -0
- package/templates/skills/code-complete/code-complete.md +354 -0
- package/templates/skills/code-complete/code-complete.mini.md +56 -0
- package/templates/skills/code-complete/code-complete.nano.md +41 -0
- package/templates/skills/council/SKILL.md +37 -0
- package/templates/skills/designing-data-intensive-applications/SKILL.md +11 -0
- package/templates/skills/designing-data-intensive-applications/designing-data-intensive-applications.md +393 -0
- package/templates/skills/designing-data-intensive-applications/designing-data-intensive-applications.mini.md +55 -0
- package/templates/skills/designing-data-intensive-applications/designing-data-intensive-applications.nano.md +34 -0
- package/templates/skills/domain-driven-design/SKILL.md +11 -0
- package/templates/skills/domain-driven-design/domain-driven-design.md +979 -0
- package/templates/skills/domain-driven-design/domain-driven-design.mini.md +48 -0
- package/templates/skills/domain-driven-design/domain-driven-design.nano.md +39 -0
- package/templates/skills/domain-driven-design-distilled/SKILL.md +11 -0
- package/templates/skills/domain-driven-design-distilled/domain-driven-design-distilled.md +317 -0
- package/templates/skills/domain-driven-design-distilled/domain-driven-design-distilled.mini.md +56 -0
- package/templates/skills/domain-driven-design-distilled/domain-driven-design-distilled.nano.md +41 -0
- package/templates/skills/implementation-plan/SKILL.md +42 -0
- package/templates/skills/implementing-domain-driven-design/SKILL.md +11 -0
- package/templates/skills/implementing-domain-driven-design/implementing-domain-driven-design.md +337 -0
- package/templates/skills/implementing-domain-driven-design/implementing-domain-driven-design.mini.md +57 -0
- package/templates/skills/implementing-domain-driven-design/implementing-domain-driven-design.nano.md +37 -0
- package/templates/skills/patterns-of-enterprise-application-architecture/SKILL.md +11 -0
- package/templates/skills/patterns-of-enterprise-application-architecture/patterns-of-enterprise-application-architecture.md +404 -0
- package/templates/skills/patterns-of-enterprise-application-architecture/patterns-of-enterprise-application-architecture.mini.md +54 -0
- package/templates/skills/patterns-of-enterprise-application-architecture/patterns-of-enterprise-application-architecture.nano.md +35 -0
- package/templates/skills/ponytail/SKILL.md +124 -0
- package/templates/skills/ponytail-audit/SKILL.md +45 -0
- package/templates/skills/ponytail-debt/SKILL.md +48 -0
- package/templates/skills/ponytail-gain/SKILL.md +17 -0
- package/templates/skills/ponytail-help/SKILL.md +42 -0
- package/templates/skills/ponytail-review/SKILL.md +61 -0
- package/templates/skills/refactoring/SKILL.md +11 -0
- package/templates/skills/refactoring/refactoring.md +433 -0
- package/templates/skills/refactoring/refactoring.mini.md +49 -0
- package/templates/skills/refactoring/refactoring.nano.md +37 -0
- package/templates/skills/refactoring-guru/SKILL.md +11 -0
- package/templates/skills/refactoring-guru/refactoring-guru.md +765 -0
- package/templates/skills/refactoring-guru/refactoring-guru.mini.md +64 -0
- package/templates/skills/refactoring-guru/refactoring-guru.nano.md +41 -0
- package/templates/skills/release-it/SKILL.md +11 -0
- package/templates/skills/release-it/release-it.md +382 -0
- package/templates/skills/release-it/release-it.mini.md +48 -0
- package/templates/skills/release-it/release-it.nano.md +38 -0
- package/templates/skills/security-audit/AI-AND-LLM.md +83 -0
- package/templates/skills/security-audit/ATTACK-CLASSES.md +130 -0
- package/templates/skills/security-audit/CLIENT-SIDE.md +83 -0
- package/templates/skills/security-audit/CLOUD-AND-DEPLOYMENT.md +86 -0
- package/templates/skills/security-audit/DATA-ISOLATION-AND-LIFECYCLE.md +84 -0
- package/templates/skills/security-audit/DESKTOP-MOBILE-AND-LOCAL-IPC.md +89 -0
- package/templates/skills/security-audit/HUNTING.md +251 -0
- package/templates/skills/security-audit/MEMORY-SAFETY-AND-BINARY.md +101 -0
- package/templates/skills/security-audit/PROTOCOLS-RPC-AND-MESSAGING.md +81 -0
- package/templates/skills/security-audit/RECONNAISSANCE.md +156 -0
- package/templates/skills/security-audit/RESOURCE-EXHAUSTION-AND-AVAILABILITY.md +78 -0
- package/templates/skills/security-audit/SKILL.md +192 -0
- package/templates/skills/security-audit/SUPPLY-CHAIN-AND-RELEASE.md +73 -0
- package/templates/skills/security-audit/VALIDATION-AND-REPORTING.md +186 -0
- package/templates/skills/security-audit/WEB-PROTOCOL-AND-AUTH.md +105 -0
- package/templates/skills/security-audit/report-schema.json +461 -0
- package/templates/skills/security-audit/validate-coverage-ledger.cjs +872 -0
- package/templates/skills/security-audit/validate-coverage-ledger.test.cjs +740 -0
- package/templates/skills/security-audit/validate-findings.cjs +773 -0
- package/templates/skills/security-audit/validate-findings.test.cjs +652 -0
- package/templates/skills/spec/SKILL.md +55 -0
- package/templates/skills/the-pragmatic-programmer/SKILL.md +11 -0
- package/templates/skills/the-pragmatic-programmer/the-pragmatic-programmer.md +359 -0
- package/templates/skills/the-pragmatic-programmer/the-pragmatic-programmer.mini.md +65 -0
- package/templates/skills/the-pragmatic-programmer/the-pragmatic-programmer.nano.md +44 -0
- package/templates/skills/working-effectively-with-legacy-code/SKILL.md +11 -0
- package/templates/skills/working-effectively-with-legacy-code/working-effectively-with-legacy-code.md +371 -0
- package/templates/skills/working-effectively-with-legacy-code/working-effectively-with-legacy-code.mini.md +50 -0
- package/templates/skills/working-effectively-with-legacy-code/working-effectively-with-legacy-code.nano.md +35 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
# Vulnerability Hunting
|
|
2
|
+
|
|
3
|
+
### Phase 2: Run coverage-led hunting waves
|
|
4
|
+
|
|
5
|
+
The parent assigns `planned` ledger units to `general` agents. Use enough focused hunters to cover the units without combining unrelated boundaries. One hunter may own closely related units in one subsystem; no unit may be silently unassigned because of an agent-count limit - a unit the budget cannot reach is explicitly `deferred` with reason `budget_cannot_reserve_critics_and_validation`.
|
|
6
|
+
|
|
7
|
+
When a budget or profile caps hunter count, assign 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 launch, the parent changes assigned units to `in_progress`, sets a canonical lowercase `agent_id`, and creates that agent's `scratch/` and parent-owned `artifacts/`. Hunters read source and parent-provided context, write only to their unique `scratch/`, and return one structured result through the Task tool. They never write retained artifacts or edit target source, `architecture.md`, `coverage-ledger.json`, `findings.json`, or another agent's files.
|
|
10
|
+
|
|
11
|
+
## Required hunter prompt
|
|
12
|
+
|
|
13
|
+
Every hunter prompt contains these parts in this order:
|
|
14
|
+
|
|
15
|
+
1. A two-sentence role preamble: the hunter's goal is to find source-grounded security invariant failures in its assigned units, and it must return exactly one JSON object matching the structured-result contract at the end of this prompt.
|
|
16
|
+
2. `architecture.md` verbatim.
|
|
17
|
+
3. Assigned coverage IDs, subsystem, boundary, repository-relative starting paths, and each unit's assignment block map from `coverage-ledger.json`.
|
|
18
|
+
4. The exact selected blocks, copied verbatim: each selected 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`. Ordinary blocks are self-contained and carry no companion-style `Core discipline`, `Universal moves`, or `Validation rules` sections. Do not send block or companion names alone.
|
|
19
|
+
5. Explicit excluded ordinary and companion blocks with a reason for each exclusion.
|
|
20
|
+
6. The core hunting method below, followed by the promotion procedure block.
|
|
21
|
+
7. The core validation rules below.
|
|
22
|
+
8. Carried same-source prior confirmed exclusions, each limited to fingerprint, title, and root cause, plus peer-owned current coverage IDs that this hunter must not duplicate.
|
|
23
|
+
9. The unique scratch/artifact paths, safe agent ID, predeclared promotion allowlist and byte limits, and the structured-result contract, including the Structured hunter result block below and the `confirmed` and `needs_validation` branches of `report-schema.json` copied verbatim.
|
|
24
|
+
|
|
25
|
+
A prompt may select several companion blocks when the same path crosses several domains. Keep their constraints together. Scope is the hunter's coverage obligation, not permission to duplicate excluded work. If an unexpected different boundary appears, return it under `uncovered` so the parent creates a stable ledger unit and assigns it in the next wave.
|
|
26
|
+
|
|
27
|
+
#### Core hunting method - include in every hunter prompt
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
## Defensive vulnerability-finding method
|
|
31
|
+
|
|
32
|
+
Your goal is to find source-grounded security invariant failures and the smallest fix,
|
|
33
|
+
not to expand harm beyond the boundary result. Stay within source review and bounded local execution.
|
|
34
|
+
Do not contact deployed endpoints, provider APIs, registries, identity systems,
|
|
35
|
+
message brokers, shared services, or other users. Use local dummy data only.
|
|
36
|
+
|
|
37
|
+
READ THE CODE AT DEPTH. Follow each assigned input through parsing, identity,
|
|
38
|
+
authorization, normalization, state, derived copies, and the final sink. Read sibling,
|
|
39
|
+
legacy, batch, retry, cancellation, migration, and error paths that produce the same
|
|
40
|
+
effect. Compare sibling controls for equivalence, not only presence, and compare what
|
|
41
|
+
one component guarantees with what the next component assumes.
|
|
42
|
+
|
|
43
|
+
WORK FROM A CONCRETE INVARIANT:
|
|
44
|
+
1. Name the lower-trust principal and starting capability.
|
|
45
|
+
2. Name the accepted value, action, state transition, or resource selector.
|
|
46
|
+
3. Locate the control that should reject, bind, isolate, limit, or revoke it.
|
|
47
|
+
4. Trace the exact source path after that decision.
|
|
48
|
+
5. Stop at the smallest affected dummy record, wrong return value, process-integrity
|
|
49
|
+
effect, or locally observable shared-resource effect.
|
|
50
|
+
6. State a source-level change and regression case that enforce the invariant.
|
|
51
|
+
|
|
52
|
+
DEPTH BOUND: trace only paths that can reach your assigned boundary or whose
|
|
53
|
+
guarantees that boundary relies on. Stop a line of investigation as soon as the
|
|
54
|
+
invariant is settled either way, and record the result in your structured output -
|
|
55
|
+
a covered, candidate, or blocked disposition, or an `uncovered` entry - instead of
|
|
56
|
+
continuing to search.
|
|
57
|
+
|
|
58
|
+
TEST SAD PATHS AND DISAGREEMENTS. Check absent, empty, zero, negative, maximum,
|
|
59
|
+
over-limit, duplicate, mixed encoding, stale, revoked, reordered, concurrent,
|
|
60
|
+
partially migrated, failed dependency, and rollback state only where the interface
|
|
61
|
+
accepts them. Compare canonicalization and units at every parser or policy handoff.
|
|
62
|
+
For multi-step issues, treat each output as a prerequisite and do not assume a later
|
|
63
|
+
boundary. If any prerequisite is not established, record a blocker.
|
|
64
|
+
|
|
65
|
+
When a proposed high or critical candidate reveals a reusable root cause, search paths
|
|
66
|
+
owned by the assigned coverage IDs for lexical, structural, and logical variants.
|
|
67
|
+
Consolidate the same root cause, but establish each variant's conditions and impact
|
|
68
|
+
independently. Do not investigate peer-owned units. Return a variant with no current
|
|
69
|
+
coverage unit as `uncovered`.
|
|
70
|
+
|
|
71
|
+
USE THE NARROWEST LOCAL CHECK THAT SETTLES THE CLAIM. Target-controlled builds,
|
|
72
|
+
tests, processes, browsers, emulators, fuzzers, and fixture processing may run only
|
|
73
|
+
inside the parent-approved OS-enforced sandbox. It must disable external networking,
|
|
74
|
+
start from an empty allowlisted environment, expose target and tools read-only, permit
|
|
75
|
+
writes only to your scratch directory, and apply low CPU, memory, process, file-size,
|
|
76
|
+
disk, and wall-clock limits. Isolated loopback is allowed only for a local fixture.
|
|
77
|
+
If any control is unavailable, do not execute: return needs_validation with that exact
|
|
78
|
+
blocker. Prefer an existing unit test, minimal function harness, dummy-tenant service
|
|
79
|
+
call, small malformed fixture, deterministic race schedule, or locally rendered policy.
|
|
80
|
+
Do not install or fetch tools.
|
|
81
|
+
|
|
82
|
+
Record the exact input, command, limits, and minimum result. For the environment,
|
|
83
|
+
record only allowlisted variable names and safe non-secret values needed to reproduce
|
|
84
|
+
the check. Never capture the ambient environment, inherited variables, credentials,
|
|
85
|
+
authentication state, or unrelated host paths. The target-controlled process writes
|
|
86
|
+
only in scratch. After the sandbox and all its processes terminate, only trusted
|
|
87
|
+
parent-side code may promote predeclared scratch-relative files, following the
|
|
88
|
+
promotion procedure block included verbatim in this prompt. You and target code never
|
|
89
|
+
write retained artifacts. If promotion is unavailable or fails for decisive evidence,
|
|
90
|
+
return needs_validation with the exact promotion blocker.
|
|
91
|
+
Never stress availability, invoke a live target, use a real credential, publish an
|
|
92
|
+
artifact, or continue past the minimum observed effect.
|
|
93
|
+
|
|
94
|
+
A deployment, browser, provider, broker, OS, proxy, package, secret, or identity fact
|
|
95
|
+
outside source is not proof either way. If one such fact is decisive, return a
|
|
96
|
+
needs_validation record with the exact missing observation and safe owner-observed check.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
#### Promotion procedure - copy this promotion procedure verbatim into every hunter prompt
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
Artifact promotion procedure (trusted parent-side code only):
|
|
103
|
+
Reference only for you: the parent performs these steps; you never perform them.
|
|
104
|
+
|
|
105
|
+
Before execution, the parent opens and retains trusted, non-inheritable directory
|
|
106
|
+
descriptors for the agent's scratch/ and artifacts/ roots, and records an allowlist
|
|
107
|
+
of expected scratch-relative artifact files plus explicit per-file and cumulative
|
|
108
|
+
byte limits. Never pass those descriptors to the agent or sandbox. After the sandbox
|
|
109
|
+
and all its processes terminate, trusted parent-side code promotes each allowlisted
|
|
110
|
+
file separately:
|
|
111
|
+
|
|
112
|
+
1. Validate the declared relative path: reject absolute, empty, `.`, `..`, or
|
|
113
|
+
symlinked components.
|
|
114
|
+
2. Walk each parent component from the retained scratch-root descriptor with
|
|
115
|
+
no-follow directory-relative operations; never reopen by path.
|
|
116
|
+
3. Open the leaf no-follow and nonblocking.
|
|
117
|
+
4. Verify with `fstat` that it is a regular file with link count exactly one and
|
|
118
|
+
within the recorded per-file and cumulative byte limits.
|
|
119
|
+
5. Enforce those limits again while reading from that descriptor.
|
|
120
|
+
6. Copy exactly the verified size, repeat `fstat`, and reject a changed identity,
|
|
121
|
+
type, link count, or size.
|
|
122
|
+
7. For the destination, walk every parent component from the retained
|
|
123
|
+
artifacts-root descriptor with no-follow directory-relative operations; require
|
|
124
|
+
each existing component to be a real directory, and create any missing directory
|
|
125
|
+
exclusively before reopening and verifying it no-follow.
|
|
126
|
+
8. Create the leaf exclusively without following links, verify that the opened
|
|
127
|
+
destination is a regular file with link count exactly one, and copy from the
|
|
128
|
+
verified source descriptor without reopening either path.
|
|
129
|
+
9. Use equivalent race-safe APIs on non-POSIX systems.
|
|
130
|
+
10. Never recursively copy or glob scratch, extract an archive into artifacts, or
|
|
131
|
+
open or promote a symlink, FIFO, socket, device, directory, hard-linked file,
|
|
132
|
+
changing file, or file that exceeds its bound.
|
|
133
|
+
11. If any check is unavailable, cannot be enforced, or fails, discard the scratch
|
|
134
|
+
entry; if it is decisive evidence, retain `needs_validation` with the exact
|
|
135
|
+
promotion blocker.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### Core validation rules - include in every hunter prompt
|
|
139
|
+
|
|
140
|
+
```text
|
|
141
|
+
## Candidate gate
|
|
142
|
+
|
|
143
|
+
1. A candidate needs a complete repository-relative source trace and evidence for the
|
|
144
|
+
claimed root cause, including the strongest source-visible control.
|
|
145
|
+
2. A proposed confirmed record needs a bounded local observed result, meaningful impact
|
|
146
|
+
across a stated boundary, complete conditions, and no visible preventing layer.
|
|
147
|
+
3. Do not strengthen a crash into code execution, ordinary work into shared availability,
|
|
148
|
+
or a same-principal action into privilege gain.
|
|
149
|
+
4. If a required fact is not source-visible or locally observable, use
|
|
150
|
+
needs_validation. Name exact blockers; do not give it severity or speculative completion.
|
|
151
|
+
5. A missing best practice with no affected principal/resource is excluded or hardening,
|
|
152
|
+
not a finding. A candidate disproved by source is not needs_validation.
|
|
153
|
+
6. Use the same source-derived fingerprint for the same root cause in every state.
|
|
154
|
+
It must match `^[A-Za-z0-9][A-Za-z0-9._:/@+-]*$` and must not include a line,
|
|
155
|
+
wave, agent, severity, or verdict.
|
|
156
|
+
7. Return an empty candidate array when nothing survives these gates.
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Local validation boundaries
|
|
160
|
+
|
|
161
|
+
Local execution is for confirmation, not impact expansion:
|
|
162
|
+
|
|
163
|
+
- **Allowed only in the required OS sandbox:** offline builds with present dependencies; isolated-loopback processes using dummy state; unit and integration tests; small fixture processing; sanitizers; bounded fuzz/regression tests; deterministic concurrency checks; local browser/emulator tests with dummy accounts; rendered manifests and policy evaluation with dummy identities; mocked external or paid calls.
|
|
164
|
+
- **Disallowed:** live or deployed traffic; requests to services not started for this isolated check; 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.
|
|
165
|
+
|
|
166
|
+
The sandbox starts with an empty environment, gives target code no external network or host writable path, and enforces explicit low resource and time limits for every check, not only checks expected to be expensive. Scratch output remains target-controlled after exit. Promote it only with the no-follow, path-confined, regular-file, bounded-size host procedure in `SKILL.md`. Missing any sandbox or promotion capability does not erase a source-grounded candidate; represent the exact blocker in `needs_validation`.
|
|
167
|
+
|
|
168
|
+
## Structured hunter result
|
|
169
|
+
|
|
170
|
+
Return exactly one JSON object, with no surrounding prose:
|
|
171
|
+
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"units": [
|
|
175
|
+
{
|
|
176
|
+
"coverage_id": "one assigned ID",
|
|
177
|
+
"disposition": "covered|candidate|blocked",
|
|
178
|
+
"reviewed_paths": ["repo/relative/path"],
|
|
179
|
+
"checks": [
|
|
180
|
+
{
|
|
181
|
+
"agent_id": "canonical owner of this check",
|
|
182
|
+
"reviewed_paths": ["repo/relative/path owned by this check"],
|
|
183
|
+
"invariant": "specific control checked for this unit",
|
|
184
|
+
"method": "source|local",
|
|
185
|
+
"result": "what source or the bounded check established",
|
|
186
|
+
"artifact": "agents/<agent-id>/artifacts/file for local, null for source"
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
"candidate_fingerprints": [],
|
|
190
|
+
"unresolved": []
|
|
191
|
+
}
|
|
192
|
+
],
|
|
193
|
+
"candidates": [],
|
|
194
|
+
"hardening": ["concrete non-finding note"],
|
|
195
|
+
"uncovered": [
|
|
196
|
+
{
|
|
197
|
+
"surface": "...",
|
|
198
|
+
"boundary": "...",
|
|
199
|
+
"subsystem": "...",
|
|
200
|
+
"attack_class": "...",
|
|
201
|
+
"starting_paths": ["repo/relative/path"],
|
|
202
|
+
"reason": "why this needs its own deterministic coverage unit"
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Each `candidates` entry is schema-shaped except that it uses `proposed_verdict` in place of `verdict`:
|
|
209
|
+
|
|
210
|
+
- `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 local check already performed. `payloads` holds the minimum test input, fixture, or native invocation. `observed_result` records actual local output. Overall severity must not exceed observed impact.
|
|
211
|
+
- `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.
|
|
212
|
+
|
|
213
|
+
Every assigned coverage ID appears exactly once in `units`. A `covered` unit needs an owner, nonempty `reviewed_paths` and `checks`, no unresolved fact, and no candidate. A `candidate` unit has the same owned evidence and is the only state that carries linked fingerprints. A `blocked` unit is an owned partial review with nonempty paths, checks, and unresolved facts but no fingerprint. All source paths are repository-relative, never absolute or traversal paths. A trace with several entries begins at `entrypoint`, ends at `sink`, and labels intermediate steps `propagation`. Every check has its own canonical lowercase `agent_id` and nonempty `reviewed_paths`; the unit-level list is exactly the union of those owned paths. A `source` check uses `artifact: null`. A `local` check uses one successfully parent-promoted regular file beneath `agents/<check.agent_id>/artifacts/`; this permits a verifier to add independently owned evidence without taking ownership from the hunter. Never link scratch, an output-root file, or another check owner's artifact.
|
|
214
|
+
|
|
215
|
+
## Parent consolidation and ledger update
|
|
216
|
+
|
|
217
|
+
The parent validates each unit result, maps it to exactly one assigned `coverage_id`, and updates only that ledger unit. Reject duplicate or absent IDs, unsafe unit or check agent IDs, source checks with artifacts, and local artifacts that trusted parent-side code did not promote into the check owner's artifacts subtree. Copy the unit's `reviewed_paths`, its `checks` into the unit's `local_checks`, linked artifact paths, candidate fingerprints, and unresolved facts into the ledger. Retain each hunter's `hardening` list in a parent bookkeeping field on the relevant units (outside the semantic fields) so Phase 6 can report it. A failed, malformed, or unsupported conclusion leaves that unit `planned` for reassignment. Untouched budget/profile units become unassigned `deferred` units with empty evidence and a reason; do not hide partial evidence in `deferred`. Run `validate-coverage-ledger.cjs` after the update; an invalid ledger cannot drive another assignment. This per-unit contract allows one hunter to close one unit while returning a candidate or blocker for another.
|
|
218
|
+
|
|
219
|
+
Consolidate candidate entries 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 duplicate candidates to validation.
|
|
220
|
+
|
|
221
|
+
## Coverage-critic waves
|
|
222
|
+
|
|
223
|
+
Immediately after each hunter wave, spend the reserved invocation on one fresh `research` post-wave coverage critic. It receives `architecture.md`, the full coverage ledger including each assignment block map, current candidate fingerprints and states, and the prior-ledger gap summary. It reads source but does not write or run targets. Require exactly this JSON:
|
|
224
|
+
|
|
225
|
+
```json
|
|
226
|
+
{
|
|
227
|
+
"missing_units": [
|
|
228
|
+
{
|
|
229
|
+
"surface": "...",
|
|
230
|
+
"boundary": "...",
|
|
231
|
+
"subsystem": "...",
|
|
232
|
+
"attack_class": "...",
|
|
233
|
+
"starting_paths": ["repo/relative/path"],
|
|
234
|
+
"selected_companion_blocks": ["FILE.md#section"],
|
|
235
|
+
"excluded_blocks": [{"block": "FILE.md#section", "reason": "..."}],
|
|
236
|
+
"reason": "source-backed coverage gap"
|
|
237
|
+
}
|
|
238
|
+
],
|
|
239
|
+
"reassign_ids": ["existing-id-that-did-not-close"],
|
|
240
|
+
"resolved_prior_leads": ["fingerprint"],
|
|
241
|
+
"stop": false
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The critic checks 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. It proposes coverage, not findings. `stop` is the critic's own assessment: `true` only when it accepts no `missing_units` and no `reassign_ids`; the parent's loop condition below, not `stop` alone, decides whether another wave runs. For each fingerprint in `resolved_prior_leads`, the parent marks the linked unit or prior-lead entry resolved and records the critic's source-backed reason.
|
|
246
|
+
|
|
247
|
+
The parent rejects proposed units outside the review scope or source/local boundary, derives canonical IDs for accepted units, and deduplicates 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 critic's source-backed `reassignment_reason`. Preserve its owner, checks, artifacts, fingerprints, and unresolved facts in that archive. Increment the live `wave`; the next hunter must be a fresh owner and receives an `in_progress` unit with empty live evidence. The hunter's terminal result writes only its new evidence into the live fields. Never copy an archived owner's checks or artifacts into the new live attempt. Sort IDs and validate the ledger before another assignment. In `standard` and `deep`, when the post-wave critic reports no accepted `missing_units` or legitimate `reassign_ids` and no `planned` units remain, spend the separately reserved invocation on a distinct final-clean critic. Complete coverage only when that critic also returns no accepted work. If it finds work, queue it and repeat the wave, post-wave critic, and final-clean process. If time or resources force an early stop, mark every untouched unit `deferred`, preserve the critic's reason, and disclose the gap in the report. Never use a silent wave or agent cap as evidence of complete coverage.
|
|
248
|
+
|
|
249
|
+
The run profile bounds this loop. A `quick` run has exactly one hunter wave followed by exactly one final critic pass. Add each accepted `missing_unit` to the current ledger and mark it `deferred` with reason `quick_profile_final_critic`. 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_critic`. Do not launch a second hunter wave or another critic. In a scoped run, the critic still reports out-of-scope gaps it notices, but the parent records them as `out_of_scope` with the critic's reason instead of assigning them. The early-stop rule above is the same mechanism: `quick` is a pre-declared early stop, not evidence of complete coverage.
|
|
250
|
+
|
|
251
|
+
A budget bounds it the same way. Before assigning each wave, compare remaining budget against its hunter count, the validation reserve, the immediate post-wave critic, and the retained final-clean critic (`quick` reserves only its single final post-wave critic). Shrink the hunter wave to fit, taking units in priority order. If those mandatory reserves do not fit, launch no hunter from that wave and mark its planned units `deferred` with reason `budget_cannot_reserve_critics_and_validation`. Critic-proposed units enter the same ranked queue rather than extending the budget. If surviving candidates exceed the validation reserve, follow the incomplete-run rule in `SKILL.md`: stop hunting, validate in fingerprint order, retain unvalidated units as unresolved candidates, and never present them as findings.
|
|
@@ -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 (include in every agent prompt for 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 (subagent_type: `general`)
|
|
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 (subagent_type: `general`)
|
|
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 (subagent_type: `general`)
|
|
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 (subagent_type: `general`)
|
|
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 (subagent_type: `general`)
|
|
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 (include in every agent prompt for 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 (subagent_type: `general`)
|
|
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 (subagent_type: `general`)
|
|
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 (subagent_type: `general`)
|
|
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 (subagent_type: `general`)
|
|
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,156 @@
|
|
|
1
|
+
# Reconnaissance
|
|
2
|
+
|
|
3
|
+
### Phase 1: Map the source and plan coverage
|
|
4
|
+
|
|
5
|
+
The parent initializes `run-metadata.json`, applies the strict pre-reconnaissance budget gate in `SKILL.md`, then creates agent scratch roots and the shared ledger before hunting. If the gate fails, record the incomplete status in metadata and launch no reconnaissance agent. 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.
|
|
6
|
+
|
|
7
|
+
Launch several `research` agents in parallel. They return structured facts to the parent and do not write files.
|
|
8
|
+
|
|
9
|
+
**Agent 1a: Product, stack, and local operation**
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
Read the target at <target>. Do not use network access. Return:
|
|
13
|
+
1. Product type, users, operators, and ordinary trust-sensitive actions.
|
|
14
|
+
2. Languages, frameworks, build system, runtimes, and locally visible deployment models.
|
|
15
|
+
3. Repository-relative entry points and subsystem boundaries.
|
|
16
|
+
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.
|
|
17
|
+
5. Comparable software or protocol visible from local documentation and dependencies. If no useful comparison is source-grounded, say so.
|
|
18
|
+
6. Missing local toolchains or runtime facts that limit bounded execution.
|
|
19
|
+
Return only source facts with repository-relative file:line references.
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Agent 1b: Principals, authority, and controls**
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
Read all source that establishes identity, authorization, isolation, and privilege. Map:
|
|
26
|
+
1. Each lower-trust principal and the actions it has by design.
|
|
27
|
+
2. Authentication or peer identity at each entry surface.
|
|
28
|
+
3. Per-resource authorization and tenant/owner scope.
|
|
29
|
+
4. Process, browser, workload, CI, plugin, model/tool, device, or local-IPC authority.
|
|
30
|
+
5. Privilege changes, confirmation, revocation, recovery, and fallback paths.
|
|
31
|
+
6. Which controls are source-visible and which depend on an unobserved deployment fact.
|
|
32
|
+
Return trust boundaries and control locations with repository-relative file:line references. Do not infer live reachability.
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Agent 1c: Entry surfaces, copies, and sinks**
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
Inventory every source-visible place external or lower-trust input enters:
|
|
39
|
+
- 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.
|
|
40
|
+
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.
|
|
41
|
+
Return repository-relative paths and line numbers. Be complete, but do not execute or send inputs.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Agent 1d: Local execution and deployment visibility**
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
Read tests, build definitions, manifests, packaging, and maintained environment overlays. Return:
|
|
48
|
+
1. Small offline tests or existing fixtures that could validate trust boundaries with dummy data inside the required OS-enforced sandbox.
|
|
49
|
+
2. Processes that could use an isolated loopback network namespace without external or shared dependencies.
|
|
50
|
+
3. Commands that would fetch dependencies, publish artifacts, contact paid/provider APIs, or affect shared state; mark them prohibited for this run.
|
|
51
|
+
4. Deployed controls and attachments that source cannot establish and therefore require needs_validation if decisive.
|
|
52
|
+
5. The final active source path for each deployment mode only where the repository selects it deterministically.
|
|
53
|
+
6. Whether the local platform can enforce an empty allowlisted environment, no external network, read-only target/toolchain mounts, scratch-only writes, and explicit CPU, memory, process, file-size, disk, and wall-clock limits. Missing controls block target-controlled execution.
|
|
54
|
+
7. Whether trusted parent-side code can promote predeclared scratch files with path-confined no-follow descriptor traversal, nonblocking regular-file checks, no-follow traversal of every destination parent, exclusive regular-file destination creation, and explicit per-file and cumulative size bounds. Missing promotion controls block use of scratch files as evidence.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Add focused reconnaissance agents for materially distinct deployment modes or subsystems that these four do not map. Do not silently omit them: if the budget gate in `SKILL.md` blocks a focused agent, launch nothing for it, seed the unmapped area as a `deferred` ledger unit with reason `budget_cannot_reserve_critics_and_validation`, and disclose the gap in the report.
|
|
58
|
+
|
|
59
|
+
## Prior-run input
|
|
60
|
+
|
|
61
|
+
Before selecting work, the parent reads every available prior `coverage-ledger.json` and `findings.json` for the same repo:
|
|
62
|
+
|
|
63
|
+
- Compare the source locations, controls, conditions, and source-derived identity for every prior record and unit against the current source.
|
|
64
|
+
- 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 hunter exclusion list. The Phase 3 verifier that re-verifies 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.
|
|
65
|
+
- 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.
|
|
66
|
+
- 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.
|
|
67
|
+
- 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 verifier 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.
|
|
68
|
+
- 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.
|
|
69
|
+
- Record missing or incompatible ledgers instead of treating them as empty coverage.
|
|
70
|
+
|
|
71
|
+
State paths and source refs used in `run-metadata.json`. Summarize only the coverage consequences in `architecture.md`.
|
|
72
|
+
|
|
73
|
+
## Architecture summary and companion selection
|
|
74
|
+
|
|
75
|
+
The parent synthesizes `<output-dir>/architecture.md`, with a hard cap of about 1,000 words. Include:
|
|
76
|
+
|
|
77
|
+
1. Product, principals, normal authority, and protected resources.
|
|
78
|
+
2. The comparable-software baseline from Agent 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.
|
|
79
|
+
3. Tech stack, source-visible deployment paths, and offline build/test limits.
|
|
80
|
+
4. Entry surfaces and the important source-to-sink or lifecycle paths.
|
|
81
|
+
5. Trust boundaries and the strongest source-visible control on each.
|
|
82
|
+
6. Repository-relative starting paths.
|
|
83
|
+
7. Prior coverage gaps, changed-source and blocked revalidation targets, and same-source confirmed exclusions.
|
|
84
|
+
8. A short companion-selection summary derived from [ATTACK-CLASSES.md](ATTACK-CLASSES.md): selected files and the source-visible boundaries that require them.
|
|
85
|
+
|
|
86
|
+
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 exact hunter prompt map machine-checkable.
|
|
87
|
+
|
|
88
|
+
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 another agent will review a related class.
|
|
89
|
+
|
|
90
|
+
## Deterministic coverage ledger
|
|
91
|
+
|
|
92
|
+
The parent writes `<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.
|
|
93
|
+
|
|
94
|
+
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.
|
|
95
|
+
|
|
96
|
+
Derive `coverage_id` without lossy slugs:
|
|
97
|
+
|
|
98
|
+
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.
|
|
99
|
+
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.
|
|
100
|
+
3. Join encoded `surface`, `boundary`, `subsystem`, and `attack_class` references with `::`; append encoded `lifecycle` when present.
|
|
101
|
+
|
|
102
|
+
Use the fixed canonical value `profile/quick/all-in-scope-subsystems` for the quick profile's coarsened subsystem dimension. Do not include wave number, agent, 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.
|
|
103
|
+
|
|
104
|
+
Each unit records:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"coverage_id": "...",
|
|
109
|
+
"canonical_refs": {
|
|
110
|
+
"surface": "src/router.ts#POST /users/:id",
|
|
111
|
+
"boundary": "src/authz.ts#requireOwner",
|
|
112
|
+
"subsystem": "packages/api",
|
|
113
|
+
"attack_class": "ATTACK-CLASSES.md#Access control"
|
|
114
|
+
},
|
|
115
|
+
"surface": "...",
|
|
116
|
+
"boundary": "...",
|
|
117
|
+
"subsystem": "...",
|
|
118
|
+
"attack_class": "...",
|
|
119
|
+
"starting_paths": ["repo/relative/path"],
|
|
120
|
+
"ordinary_attack_class_block": "ATTACK-CLASSES.md#Access control",
|
|
121
|
+
"selected_companion_blocks": ["FILE.md#section"],
|
|
122
|
+
"excluded_blocks": [{"block": "FILE.md#section", "reason": "..."}],
|
|
123
|
+
"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",
|
|
124
|
+
"attempts": [],
|
|
125
|
+
"wave": 1,
|
|
126
|
+
"status": "planned",
|
|
127
|
+
"agent_id": null,
|
|
128
|
+
"reviewed_paths": [],
|
|
129
|
+
"local_checks": [],
|
|
130
|
+
"result_fingerprints": [],
|
|
131
|
+
"unresolved": []
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
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.
|
|
136
|
+
|
|
137
|
+
The parent may add bookkeeping fields but keeps 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 critic to decide whether it needs another pass.
|
|
138
|
+
|
|
139
|
+
`attempts` is an append-only archive for evidence-bearing assignments that a coverage critic reopens. Before reassignment, append the prior unit's exact `wave`, `status`, `agent_id`, `reviewed_paths`, `local_checks`, `result_fingerprints`, and `unresolved`, plus the critic'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 owner, and starts with empty live evidence. If the profile or budget prevents another assignment, increment `wave` and use live `deferred` state with null owner, empty evidence, and the stop reason. Never copy an archived owner's checks or artifacts into the live state. A later live terminal state contains only the new attempt's evidence; the archive remains unchanged.
|
|
140
|
+
|
|
141
|
+
Enforce this state table exactly:
|
|
142
|
+
|
|
143
|
+
| Status | Unit `agent_id` | `reviewed_paths` / `local_checks` | `result_fingerprints` | `unresolved` |
|
|
144
|
+
|---|---|---|---|---|
|
|
145
|
+
| `planned` | null | empty | empty | empty |
|
|
146
|
+
| `not_applicable`, `out_of_scope`, `deferred` | null | empty | empty | nonempty reason |
|
|
147
|
+
| `in_progress` | canonical owner | empty | empty | empty |
|
|
148
|
+
| `blocked` | canonical owner | both nonempty owned partial evidence | empty | nonempty blocker |
|
|
149
|
+
| `covered` | canonical owner | both nonempty | empty | empty |
|
|
150
|
+
| `candidate` | canonical owner | both nonempty | nonempty | optional |
|
|
151
|
+
|
|
152
|
+
Canonical agent IDs 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 assignment owner. 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 regular file promoted only by trusted parent-side code under exactly `agents/<check.agent_id>/artifacts/`. This lets hunter and verifier checks coexist in one unit. Scratch paths, output-root files, symlinks, special files, and another check owner's artifacts are not evidence.
|
|
153
|
+
|
|
154
|
+
The ledger is the coverage claim. An architecture summary, agent count, or generic "auth reviewed" sentence is not coverage evidence. Phase 2 closes units only from the paths and checks in a hunter's structured result.
|
|
155
|
+
|
|
156
|
+
Run `node <skill-dir>/validate-coverage-ledger.cjs <output-dir>/coverage-ledger.json` after seeding, after every parent 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.
|