@codyswann/lisa 2.264.0 → 2.265.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/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +6 -5
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-security-review/SKILL.md +69 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-security-zap-scan/SKILL.md +22 -2
- package/plugins/lisa/agents/security-specialist.md +19 -2
- package/plugins/lisa/rules/eager/claim-evidence-mapping.md +9 -2
- package/plugins/lisa/rules/reference/claim-evidence-mapping.md +25 -4
- package/plugins/lisa/skills/lisa-security-review/SKILL.md +69 -2
- package/plugins/lisa/skills/lisa-security-zap-scan/SKILL.md +22 -2
- package/plugins/lisa-agy/agents/security-specialist.md +19 -2
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-security-review/SKILL.md +69 -2
- package/plugins/lisa-agy/skills/lisa-security-zap-scan/SKILL.md +22 -2
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/agents/security-specialist.agent.md +19 -2
- package/plugins/lisa-copilot/rules/eager/claim-evidence-mapping.md +9 -2
- package/plugins/lisa-copilot/rules/reference/claim-evidence-mapping.md +25 -4
- package/plugins/lisa-copilot/skills/lisa-security-review/SKILL.md +69 -2
- package/plugins/lisa-copilot/skills/lisa-security-zap-scan/SKILL.md +22 -2
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/agents/security-specialist.md +19 -2
- package/plugins/lisa-cursor/rules/claim-evidence-mapping-reference.mdc +25 -4
- package/plugins/lisa-cursor/rules/claim-evidence-mapping.mdc +9 -2
- package/plugins/lisa-cursor/skills/lisa-security-review/SKILL.md +69 -2
- package/plugins/lisa-cursor/skills/lisa-security-zap-scan/SKILL.md +22 -2
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/agents/security-specialist.md +19 -2
- package/plugins/src/base/rules/eager/claim-evidence-mapping.md +9 -2
- package/plugins/src/base/rules/reference/claim-evidence-mapping.md +25 -4
- package/plugins/src/base/skills/lisa-security-review/SKILL.md +69 -2
- package/plugins/src/base/skills/lisa-security-zap-scan/SKILL.md +22 -2
package/package.json
CHANGED
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
"form-data": ">=4.0.6"
|
|
107
107
|
},
|
|
108
108
|
"name": "@codyswann/lisa",
|
|
109
|
-
"version": "2.
|
|
109
|
+
"version": "2.265.0",
|
|
110
110
|
"description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
|
|
111
111
|
"main": "dist/index.js",
|
|
112
112
|
"exports": {
|
|
@@ -16,6 +16,57 @@ Identify vulnerabilities, evaluate threats, and recommend mitigations for code c
|
|
|
16
16
|
5. **Check auth/authz** -- are access controls properly enforced for new endpoints or features?
|
|
17
17
|
6. **Review dependencies** -- do new dependencies introduce known vulnerabilities?
|
|
18
18
|
|
|
19
|
+
## The impact-or-exploitability bar
|
|
20
|
+
|
|
21
|
+
Severity is **earned, not pattern-matched**. Every security-shaped finding is classified
|
|
22
|
+
mechanically, before it is written up:
|
|
23
|
+
|
|
24
|
+
| Field | What it holds |
|
|
25
|
+
|-------|---------------|
|
|
26
|
+
| `reproducer` | an evidence ref of a kind that reaches the claim's boundary, or `none` |
|
|
27
|
+
| `impact` | a bounded impact/exploitability statement (who can do what, to what data, under what preconditions), or `unproven` |
|
|
28
|
+
| `reason` | one line saying why the finding landed in its bucket |
|
|
29
|
+
|
|
30
|
+
**The bar:** a finding is **proven** only when it carries **both** a reproducer **and** a bounded
|
|
31
|
+
impact statement. **Missing either ⇒ unproven.** No other input changes the bucket.
|
|
32
|
+
|
|
33
|
+
What counts as a reaching reproducer is defined by the `claim-evidence-mapping` contract (**BCE-1**,
|
|
34
|
+
#1835), not here: an injection claim at the `http-api` boundary needs an `http-transcript`; a UI
|
|
35
|
+
claim needs a `screenshot` or `recording`. A passing unit `test-run-log` reaches `code-unit` only and
|
|
36
|
+
never discharges either.
|
|
37
|
+
|
|
38
|
+
**Each field stands on its own.** The two halves are recorded independently: a finding with a bounded
|
|
39
|
+
impact but no reproducer keeps its impact statement verbatim and only `reproducer` reads `none`; a
|
|
40
|
+
finding with a reproducer but no bounded impact keeps the evidence ref and only `impact` reads
|
|
41
|
+
`unproven`. **Never overwrite** a field you actually have with a missing-value placeholder — the
|
|
42
|
+
`reason` line names which half is missing, and the surviving half is the head start the next reviewer
|
|
43
|
+
needs.
|
|
44
|
+
|
|
45
|
+
## The two buckets — conservative by default
|
|
46
|
+
|
|
47
|
+
Findings render in two clearly-labeled buckets: **Security (proven)** and **Security (unproven)**.
|
|
48
|
+
|
|
49
|
+
A reproducer-less finding **stays in the security section**, labeled `unproven` with its reason. It
|
|
50
|
+
is **never auto-demoted** to a `maintenance` bucket and it is **not removed** from the report —
|
|
51
|
+
under-reporting a real vulnerability is the worse failure, so the conservative default keeps it
|
|
52
|
+
visible where a security reader looks.
|
|
53
|
+
|
|
54
|
+
**Single policy point.** The unproven bucket's label is the only thing an owner may change:
|
|
55
|
+
`security.review.unprovenBucket` in `.lisa.config.json`, default `security-unproven`. An owner who
|
|
56
|
+
prefers true demotion sets it to a maintenance label; the finding then renders under that bucket and
|
|
57
|
+
**no other classification logic changes** — the bar, the fields, and the reasons are identical.
|
|
58
|
+
|
|
59
|
+
Write both buckets in operator voice (`factory-model` rule 5): a person who does not code reads this
|
|
60
|
+
at the gate. "Anyone who can reach the search box can read other customers' orders — reproduced with
|
|
61
|
+
the request transcript below" is usable; "possible SQLi in handler" is not.
|
|
62
|
+
|
|
63
|
+
This bar governs *code-review* security findings. Dependency CVE remediation keeps its own decision
|
|
64
|
+
ladder in the `security-audit-handling` rule — cite it, do not restate or fork it.
|
|
65
|
+
|
|
66
|
+
Bucketing is **advisory** — it shapes the report, it does not block a merge — on the same terms as
|
|
67
|
+
the boundary checks, which stay reporting-only until `verification.gate.enforceBoundaries` is `true`
|
|
68
|
+
in `.lisa.config.json`.
|
|
69
|
+
|
|
19
70
|
## Output Format
|
|
20
71
|
|
|
21
72
|
Structure findings as:
|
|
@@ -41,17 +92,33 @@ Structure findings as:
|
|
|
41
92
|
- [ ] No XSS vectors in user-facing output
|
|
42
93
|
- [ ] Dependencies free of known CVEs
|
|
43
94
|
|
|
44
|
-
###
|
|
45
|
-
- [
|
|
95
|
+
### Security (proven)
|
|
96
|
+
- [finding] -- where in the code, how to prevent
|
|
97
|
+
- reproducer: [evidence ref, e.g. evidence/<ticket>/http-transcript-01.txt]
|
|
98
|
+
- impact: [who can do what, to what data, under what preconditions]
|
|
99
|
+
- reason: reproducer + bounded impact
|
|
100
|
+
|
|
101
|
+
### Security (unproven)
|
|
102
|
+
- [finding] -- where in the code, how to prevent
|
|
103
|
+
- reproducer: [evidence ref if one exists, else `none`]
|
|
104
|
+
- impact: [bounded statement if one exists, else `unproven`]
|
|
105
|
+
- reason: [which half is missing -- e.g. "impact bounded, but never reproduced"]
|
|
106
|
+
-- kept in the security section, not demoted
|
|
46
107
|
|
|
47
108
|
### Recommendations
|
|
48
109
|
- [recommendation] -- priority (critical/warning/suggestion)
|
|
49
110
|
```
|
|
50
111
|
|
|
112
|
+
Rename the unproven heading only when `security.review.unprovenBucket` is set to something other
|
|
113
|
+
than `security-unproven`; everything else stays as written.
|
|
114
|
+
|
|
51
115
|
## Rules
|
|
52
116
|
|
|
53
117
|
- Focus on the specific changes proposed, not a full security audit of the entire codebase
|
|
54
118
|
- Flag only real risks -- do not invent hypothetical threats for internal tooling with no user input
|
|
119
|
+
- Classify every finding against the bar before writing it up; never leave a finding unbucketed
|
|
120
|
+
- Never silently drop or downgrade a finding out of the security section -- `unproven` is the
|
|
121
|
+
conservative landing spot, and the reason line says why
|
|
55
122
|
- Prioritize OWASP Top 10 vulnerabilities
|
|
56
123
|
- If the changes are purely internal (config, refactoring, docs), report "No security concerns" and explain why
|
|
57
124
|
- Always check `.gitleaksignore` patterns to understand what secrets scanning is already in place
|
|
@@ -22,10 +22,30 @@ Run a ZAP baseline security scan against the local application.
|
|
|
22
22
|
- After the scan completes, read `zap-report.html` (or `zap-report.md` for text)
|
|
23
23
|
- Summarize findings:
|
|
24
24
|
- Total number of alerts by risk level (High, Medium, Low, Informational)
|
|
25
|
-
-
|
|
25
|
+
- **Every alert reaches classification** -- High, Medium, Low, and Informational alike. Risk
|
|
26
|
+
level orders the summary; it never filters it. **Nothing is dropped before classification**,
|
|
27
|
+
so no alert can leave the report unclassified. Medium+ alerts are listed first, in full (rule
|
|
28
|
+
ID, name, recommended fix); Low/Informational alerts are still listed, bucketed, and given a
|
|
29
|
+
`reason`, even when compressed to one line each.
|
|
26
30
|
- Categorize findings as "infrastructure-level" (fix at CDN/proxy) vs "application-level" (fix in code)
|
|
27
31
|
|
|
28
|
-
4. **
|
|
32
|
+
4. **Apply the impact-or-exploitability bar** -- the same bar the `lisa-security-review` skill
|
|
33
|
+
defines; follow that skill, do not restate it. A ZAP alert is not a reproducer by itself: the
|
|
34
|
+
alert names a pattern, not an exercised impact path.
|
|
35
|
+
- **Security (proven)** -- the alert carries a reproducer **and** a bounded impact statement. The
|
|
36
|
+
reproducer counts only if its evidence kind **reaches the claim's boundary** under the
|
|
37
|
+
`claim-evidence-mapping` contract (BCE-1, #1835): a ZAP request/response transcript is an
|
|
38
|
+
`http-transcript` and reaches the `http-api` boundary only. An alert whose claim is about
|
|
39
|
+
rendered UI (`browser`) or persisted state (`data`) needs evidence at *that* boundary -- a
|
|
40
|
+
transcript never proves it.
|
|
41
|
+
- **Security (unproven)** -- everything else, each with a one-line `reason` (typically
|
|
42
|
+
"alert only, no reproducer / no bounded impact", or "transcript does not reach the claim's
|
|
43
|
+
boundary"). Unproven alerts are **not dropped** and not demoted out of the security summary --
|
|
44
|
+
they render in the unproven bucket so a reader still sees them.
|
|
45
|
+
- Rename the unproven heading only if `security.review.unprovenBucket` is set to something other
|
|
46
|
+
than `security-unproven`; no other classification changes.
|
|
47
|
+
|
|
48
|
+
5. **Handle failures**:
|
|
29
49
|
- If the scan failed, explain what failed and suggest concrete remediation steps
|
|
30
50
|
|
|
31
51
|
## Execution
|
|
@@ -35,13 +35,30 @@ Structure your findings as:
|
|
|
35
35
|
- [ ] No XSS vectors in user-facing output
|
|
36
36
|
- [ ] Dependencies free of known CVEs
|
|
37
37
|
|
|
38
|
-
###
|
|
39
|
-
- [
|
|
38
|
+
### Security (proven)
|
|
39
|
+
- [finding] -- where in the code, how to prevent
|
|
40
|
+
- reproducer: [evidence ref]
|
|
41
|
+
- impact: [who can do what, to what data, under what preconditions]
|
|
42
|
+
- reason: reproducer + bounded impact
|
|
43
|
+
|
|
44
|
+
### Security (unproven)
|
|
45
|
+
- [finding] -- where in the code, how to prevent
|
|
46
|
+
- reproducer: [evidence ref if one exists, else `none`]
|
|
47
|
+
- impact: [bounded statement if one exists, else `unproven`]
|
|
48
|
+
- reason: [which half is missing -- e.g. "impact bounded, but never reproduced"]
|
|
49
|
+
-- kept in the security section, not demoted
|
|
40
50
|
|
|
41
51
|
### Recommendations
|
|
42
52
|
- [recommendation] -- priority (critical/warning/suggestion)
|
|
43
53
|
```
|
|
44
54
|
|
|
55
|
+
A finding is **proven** only with both a reproducer evidence ref and a bounded impact statement;
|
|
56
|
+
missing either, it stays **unproven** inside the security section. Record the two halves
|
|
57
|
+
independently -- keep whichever one you have and let the `reason` name the missing half; never
|
|
58
|
+
overwrite a real value with a placeholder. The full bar, the per-finding fields, and the
|
|
59
|
+
`security.review.unprovenBucket` policy point live in the `security-review` skill -- follow it, do
|
|
60
|
+
not restate it.
|
|
61
|
+
|
|
45
62
|
## Rules
|
|
46
63
|
|
|
47
64
|
- Focus on the specific changes proposed, not a full security audit of the entire codebase
|
|
@@ -37,8 +37,15 @@ rule 5).
|
|
|
37
37
|
A claim carries three fields — `claim_id`, `boundary`, and `required_evidence_kinds` — named here so
|
|
38
38
|
every downstream surface uses one spelling. This ticket only writes the contract down; the schema and
|
|
39
39
|
gate that make these fields executable ship with **BCE-2 (#1836)** — do not assume that surface is
|
|
40
|
-
present in this branch.
|
|
41
|
-
|
|
40
|
+
present in this branch.
|
|
41
|
+
|
|
42
|
+
## Security buckets (conservative by default)
|
|
43
|
+
|
|
44
|
+
A security finding is **proven** only with both a reproducer of a reaching kind and a bounded
|
|
45
|
+
impact/exploitability statement; missing either, it renders **unproven** with its reason and **stays
|
|
46
|
+
in the security section** — never auto-demoted to maintenance. The label is one policy point,
|
|
47
|
+
`security.review.unprovenBucket` (default `security-unproven`); the procedure lives in the
|
|
48
|
+
`lisa-security-review` skill.
|
|
42
49
|
|
|
43
50
|
## Artifact identity (pinned, never assumed)
|
|
44
51
|
|
|
@@ -82,10 +82,9 @@ defines the names; it stores nothing:
|
|
|
82
82
|
A claim whose `required_evidence_kinds` has no captured, reaching artifact is **Not established** —
|
|
83
83
|
defined in full, with its evidence templates, in the section below. Artifact identity — what makes
|
|
84
84
|
two captured artifacts the same or different — is defined in the *Artifact identity* section below
|
|
85
|
-
(shipped by BCE-4, #1838). The
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
you can and continue.
|
|
85
|
+
(shipped by BCE-4, #1838). The bucket a security-sensitive claim lands in is defined in the *Security
|
|
86
|
+
buckets* section below (shipped by BCE-5, #1839). Where such a sibling surface is not installed in a
|
|
87
|
+
given branch, name what you can and continue.
|
|
89
88
|
|
|
90
89
|
### Worked example
|
|
91
90
|
|
|
@@ -179,6 +178,28 @@ second one. Identity reconciliation is the same definition read from the evidenc
|
|
|
179
178
|
|
|
180
179
|
Two guards, one definition — so they cannot disagree about what shipped.
|
|
181
180
|
|
|
181
|
+
## Security buckets — the impact-or-exploitability bar
|
|
182
|
+
|
|
183
|
+
A security-shaped claim is a claim like any other: it reaches only as far as its evidence. Applied to
|
|
184
|
+
security findings (shipped by BCE-5, #1839), that yields two buckets and one bar:
|
|
185
|
+
|
|
186
|
+
- **Security (proven)** — the finding carries **both** a `reproducer` (an evidence ref of a kind that
|
|
187
|
+
reaches the claim's boundary, per the taxonomy above — e.g. an `http-transcript` for an injection
|
|
188
|
+
claim at `http-api`) **and** a bounded `impact`/exploitability statement.
|
|
189
|
+
- **Security (unproven)** — **missing either**. It keeps a one-line `reason` and **stays in the
|
|
190
|
+
security section**: a reproducer-less finding is **never auto-demoted** to a `maintenance` bucket,
|
|
191
|
+
because under-reporting a real vulnerability is the worse failure.
|
|
192
|
+
|
|
193
|
+
The unproven bucket's label is the single configurable policy point —
|
|
194
|
+
`security.review.unprovenBucket` in `.lisa.config.json`, default `security-unproven`. An owner who
|
|
195
|
+
prefers true demotion flips that one value; no other classification logic changes. Like the boundary
|
|
196
|
+
checks, bucketing is **advisory** — it shapes the report, not the merge — until
|
|
197
|
+
`verification.gate.enforceBoundaries` is `true`.
|
|
198
|
+
|
|
199
|
+
The full procedure — per-finding fields, report shape, ZAP alignment — lives in the
|
|
200
|
+
`lisa-security-review` skill (with `lisa-security-zap-scan` citing it); dependency-CVE remediation
|
|
201
|
+
keeps its separate ladder in `security-audit-handling`. Cite those slugs; do not restate them here.
|
|
202
|
+
|
|
182
203
|
## The "Not established" section — required, never omitted
|
|
183
204
|
|
|
184
205
|
Every report that asserts something was verified also states, in the same breath, **what it did not
|
|
@@ -16,6 +16,57 @@ Identify vulnerabilities, evaluate threats, and recommend mitigations for code c
|
|
|
16
16
|
5. **Check auth/authz** -- are access controls properly enforced for new endpoints or features?
|
|
17
17
|
6. **Review dependencies** -- do new dependencies introduce known vulnerabilities?
|
|
18
18
|
|
|
19
|
+
## The impact-or-exploitability bar
|
|
20
|
+
|
|
21
|
+
Severity is **earned, not pattern-matched**. Every security-shaped finding is classified
|
|
22
|
+
mechanically, before it is written up:
|
|
23
|
+
|
|
24
|
+
| Field | What it holds |
|
|
25
|
+
|-------|---------------|
|
|
26
|
+
| `reproducer` | an evidence ref of a kind that reaches the claim's boundary, or `none` |
|
|
27
|
+
| `impact` | a bounded impact/exploitability statement (who can do what, to what data, under what preconditions), or `unproven` |
|
|
28
|
+
| `reason` | one line saying why the finding landed in its bucket |
|
|
29
|
+
|
|
30
|
+
**The bar:** a finding is **proven** only when it carries **both** a reproducer **and** a bounded
|
|
31
|
+
impact statement. **Missing either ⇒ unproven.** No other input changes the bucket.
|
|
32
|
+
|
|
33
|
+
What counts as a reaching reproducer is defined by the `claim-evidence-mapping` contract (**BCE-1**,
|
|
34
|
+
#1835), not here: an injection claim at the `http-api` boundary needs an `http-transcript`; a UI
|
|
35
|
+
claim needs a `screenshot` or `recording`. A passing unit `test-run-log` reaches `code-unit` only and
|
|
36
|
+
never discharges either.
|
|
37
|
+
|
|
38
|
+
**Each field stands on its own.** The two halves are recorded independently: a finding with a bounded
|
|
39
|
+
impact but no reproducer keeps its impact statement verbatim and only `reproducer` reads `none`; a
|
|
40
|
+
finding with a reproducer but no bounded impact keeps the evidence ref and only `impact` reads
|
|
41
|
+
`unproven`. **Never overwrite** a field you actually have with a missing-value placeholder — the
|
|
42
|
+
`reason` line names which half is missing, and the surviving half is the head start the next reviewer
|
|
43
|
+
needs.
|
|
44
|
+
|
|
45
|
+
## The two buckets — conservative by default
|
|
46
|
+
|
|
47
|
+
Findings render in two clearly-labeled buckets: **Security (proven)** and **Security (unproven)**.
|
|
48
|
+
|
|
49
|
+
A reproducer-less finding **stays in the security section**, labeled `unproven` with its reason. It
|
|
50
|
+
is **never auto-demoted** to a `maintenance` bucket and it is **not removed** from the report —
|
|
51
|
+
under-reporting a real vulnerability is the worse failure, so the conservative default keeps it
|
|
52
|
+
visible where a security reader looks.
|
|
53
|
+
|
|
54
|
+
**Single policy point.** The unproven bucket's label is the only thing an owner may change:
|
|
55
|
+
`security.review.unprovenBucket` in `.lisa.config.json`, default `security-unproven`. An owner who
|
|
56
|
+
prefers true demotion sets it to a maintenance label; the finding then renders under that bucket and
|
|
57
|
+
**no other classification logic changes** — the bar, the fields, and the reasons are identical.
|
|
58
|
+
|
|
59
|
+
Write both buckets in operator voice (`factory-model` rule 5): a person who does not code reads this
|
|
60
|
+
at the gate. "Anyone who can reach the search box can read other customers' orders — reproduced with
|
|
61
|
+
the request transcript below" is usable; "possible SQLi in handler" is not.
|
|
62
|
+
|
|
63
|
+
This bar governs *code-review* security findings. Dependency CVE remediation keeps its own decision
|
|
64
|
+
ladder in the `security-audit-handling` rule — cite it, do not restate or fork it.
|
|
65
|
+
|
|
66
|
+
Bucketing is **advisory** — it shapes the report, it does not block a merge — on the same terms as
|
|
67
|
+
the boundary checks, which stay reporting-only until `verification.gate.enforceBoundaries` is `true`
|
|
68
|
+
in `.lisa.config.json`.
|
|
69
|
+
|
|
19
70
|
## Output Format
|
|
20
71
|
|
|
21
72
|
Structure findings as:
|
|
@@ -41,17 +92,33 @@ Structure findings as:
|
|
|
41
92
|
- [ ] No XSS vectors in user-facing output
|
|
42
93
|
- [ ] Dependencies free of known CVEs
|
|
43
94
|
|
|
44
|
-
###
|
|
45
|
-
- [
|
|
95
|
+
### Security (proven)
|
|
96
|
+
- [finding] -- where in the code, how to prevent
|
|
97
|
+
- reproducer: [evidence ref, e.g. evidence/<ticket>/http-transcript-01.txt]
|
|
98
|
+
- impact: [who can do what, to what data, under what preconditions]
|
|
99
|
+
- reason: reproducer + bounded impact
|
|
100
|
+
|
|
101
|
+
### Security (unproven)
|
|
102
|
+
- [finding] -- where in the code, how to prevent
|
|
103
|
+
- reproducer: [evidence ref if one exists, else `none`]
|
|
104
|
+
- impact: [bounded statement if one exists, else `unproven`]
|
|
105
|
+
- reason: [which half is missing -- e.g. "impact bounded, but never reproduced"]
|
|
106
|
+
-- kept in the security section, not demoted
|
|
46
107
|
|
|
47
108
|
### Recommendations
|
|
48
109
|
- [recommendation] -- priority (critical/warning/suggestion)
|
|
49
110
|
```
|
|
50
111
|
|
|
112
|
+
Rename the unproven heading only when `security.review.unprovenBucket` is set to something other
|
|
113
|
+
than `security-unproven`; everything else stays as written.
|
|
114
|
+
|
|
51
115
|
## Rules
|
|
52
116
|
|
|
53
117
|
- Focus on the specific changes proposed, not a full security audit of the entire codebase
|
|
54
118
|
- Flag only real risks -- do not invent hypothetical threats for internal tooling with no user input
|
|
119
|
+
- Classify every finding against the bar before writing it up; never leave a finding unbucketed
|
|
120
|
+
- Never silently drop or downgrade a finding out of the security section -- `unproven` is the
|
|
121
|
+
conservative landing spot, and the reason line says why
|
|
55
122
|
- Prioritize OWASP Top 10 vulnerabilities
|
|
56
123
|
- If the changes are purely internal (config, refactoring, docs), report "No security concerns" and explain why
|
|
57
124
|
- Always check `.gitleaksignore` patterns to understand what secrets scanning is already in place
|
|
@@ -22,10 +22,30 @@ Run a ZAP baseline security scan against the local application.
|
|
|
22
22
|
- After the scan completes, read `zap-report.html` (or `zap-report.md` for text)
|
|
23
23
|
- Summarize findings:
|
|
24
24
|
- Total number of alerts by risk level (High, Medium, Low, Informational)
|
|
25
|
-
-
|
|
25
|
+
- **Every alert reaches classification** -- High, Medium, Low, and Informational alike. Risk
|
|
26
|
+
level orders the summary; it never filters it. **Nothing is dropped before classification**,
|
|
27
|
+
so no alert can leave the report unclassified. Medium+ alerts are listed first, in full (rule
|
|
28
|
+
ID, name, recommended fix); Low/Informational alerts are still listed, bucketed, and given a
|
|
29
|
+
`reason`, even when compressed to one line each.
|
|
26
30
|
- Categorize findings as "infrastructure-level" (fix at CDN/proxy) vs "application-level" (fix in code)
|
|
27
31
|
|
|
28
|
-
4. **
|
|
32
|
+
4. **Apply the impact-or-exploitability bar** -- the same bar the `lisa-security-review` skill
|
|
33
|
+
defines; follow that skill, do not restate it. A ZAP alert is not a reproducer by itself: the
|
|
34
|
+
alert names a pattern, not an exercised impact path.
|
|
35
|
+
- **Security (proven)** -- the alert carries a reproducer **and** a bounded impact statement. The
|
|
36
|
+
reproducer counts only if its evidence kind **reaches the claim's boundary** under the
|
|
37
|
+
`claim-evidence-mapping` contract (BCE-1, #1835): a ZAP request/response transcript is an
|
|
38
|
+
`http-transcript` and reaches the `http-api` boundary only. An alert whose claim is about
|
|
39
|
+
rendered UI (`browser`) or persisted state (`data`) needs evidence at *that* boundary -- a
|
|
40
|
+
transcript never proves it.
|
|
41
|
+
- **Security (unproven)** -- everything else, each with a one-line `reason` (typically
|
|
42
|
+
"alert only, no reproducer / no bounded impact", or "transcript does not reach the claim's
|
|
43
|
+
boundary"). Unproven alerts are **not dropped** and not demoted out of the security summary --
|
|
44
|
+
they render in the unproven bucket so a reader still sees them.
|
|
45
|
+
- Rename the unproven heading only if `security.review.unprovenBucket` is set to something other
|
|
46
|
+
than `security-unproven`; no other classification changes.
|
|
47
|
+
|
|
48
|
+
5. **Handle failures**:
|
|
29
49
|
- If the scan failed, explain what failed and suggest concrete remediation steps
|
|
30
50
|
|
|
31
51
|
## Execution
|
|
@@ -35,13 +35,30 @@ Structure your findings as:
|
|
|
35
35
|
- [ ] No XSS vectors in user-facing output
|
|
36
36
|
- [ ] Dependencies free of known CVEs
|
|
37
37
|
|
|
38
|
-
###
|
|
39
|
-
- [
|
|
38
|
+
### Security (proven)
|
|
39
|
+
- [finding] -- where in the code, how to prevent
|
|
40
|
+
- reproducer: [evidence ref]
|
|
41
|
+
- impact: [who can do what, to what data, under what preconditions]
|
|
42
|
+
- reason: reproducer + bounded impact
|
|
43
|
+
|
|
44
|
+
### Security (unproven)
|
|
45
|
+
- [finding] -- where in the code, how to prevent
|
|
46
|
+
- reproducer: [evidence ref if one exists, else `none`]
|
|
47
|
+
- impact: [bounded statement if one exists, else `unproven`]
|
|
48
|
+
- reason: [which half is missing -- e.g. "impact bounded, but never reproduced"]
|
|
49
|
+
-- kept in the security section, not demoted
|
|
40
50
|
|
|
41
51
|
### Recommendations
|
|
42
52
|
- [recommendation] -- priority (critical/warning/suggestion)
|
|
43
53
|
```
|
|
44
54
|
|
|
55
|
+
A finding is **proven** only with both a reproducer evidence ref and a bounded impact statement;
|
|
56
|
+
missing either, it stays **unproven** inside the security section. Record the two halves
|
|
57
|
+
independently -- keep whichever one you have and let the `reason` name the missing half; never
|
|
58
|
+
overwrite a real value with a placeholder. The full bar, the per-finding fields, and the
|
|
59
|
+
`security.review.unprovenBucket` policy point live in the `security-review` skill -- follow it, do
|
|
60
|
+
not restate it.
|
|
61
|
+
|
|
45
62
|
## Rules
|
|
46
63
|
|
|
47
64
|
- Focus on the specific changes proposed, not a full security audit of the entire codebase
|
|
@@ -16,6 +16,57 @@ Identify vulnerabilities, evaluate threats, and recommend mitigations for code c
|
|
|
16
16
|
5. **Check auth/authz** -- are access controls properly enforced for new endpoints or features?
|
|
17
17
|
6. **Review dependencies** -- do new dependencies introduce known vulnerabilities?
|
|
18
18
|
|
|
19
|
+
## The impact-or-exploitability bar
|
|
20
|
+
|
|
21
|
+
Severity is **earned, not pattern-matched**. Every security-shaped finding is classified
|
|
22
|
+
mechanically, before it is written up:
|
|
23
|
+
|
|
24
|
+
| Field | What it holds |
|
|
25
|
+
|-------|---------------|
|
|
26
|
+
| `reproducer` | an evidence ref of a kind that reaches the claim's boundary, or `none` |
|
|
27
|
+
| `impact` | a bounded impact/exploitability statement (who can do what, to what data, under what preconditions), or `unproven` |
|
|
28
|
+
| `reason` | one line saying why the finding landed in its bucket |
|
|
29
|
+
|
|
30
|
+
**The bar:** a finding is **proven** only when it carries **both** a reproducer **and** a bounded
|
|
31
|
+
impact statement. **Missing either ⇒ unproven.** No other input changes the bucket.
|
|
32
|
+
|
|
33
|
+
What counts as a reaching reproducer is defined by the `claim-evidence-mapping` contract (**BCE-1**,
|
|
34
|
+
#1835), not here: an injection claim at the `http-api` boundary needs an `http-transcript`; a UI
|
|
35
|
+
claim needs a `screenshot` or `recording`. A passing unit `test-run-log` reaches `code-unit` only and
|
|
36
|
+
never discharges either.
|
|
37
|
+
|
|
38
|
+
**Each field stands on its own.** The two halves are recorded independently: a finding with a bounded
|
|
39
|
+
impact but no reproducer keeps its impact statement verbatim and only `reproducer` reads `none`; a
|
|
40
|
+
finding with a reproducer but no bounded impact keeps the evidence ref and only `impact` reads
|
|
41
|
+
`unproven`. **Never overwrite** a field you actually have with a missing-value placeholder — the
|
|
42
|
+
`reason` line names which half is missing, and the surviving half is the head start the next reviewer
|
|
43
|
+
needs.
|
|
44
|
+
|
|
45
|
+
## The two buckets — conservative by default
|
|
46
|
+
|
|
47
|
+
Findings render in two clearly-labeled buckets: **Security (proven)** and **Security (unproven)**.
|
|
48
|
+
|
|
49
|
+
A reproducer-less finding **stays in the security section**, labeled `unproven` with its reason. It
|
|
50
|
+
is **never auto-demoted** to a `maintenance` bucket and it is **not removed** from the report —
|
|
51
|
+
under-reporting a real vulnerability is the worse failure, so the conservative default keeps it
|
|
52
|
+
visible where a security reader looks.
|
|
53
|
+
|
|
54
|
+
**Single policy point.** The unproven bucket's label is the only thing an owner may change:
|
|
55
|
+
`security.review.unprovenBucket` in `.lisa.config.json`, default `security-unproven`. An owner who
|
|
56
|
+
prefers true demotion sets it to a maintenance label; the finding then renders under that bucket and
|
|
57
|
+
**no other classification logic changes** — the bar, the fields, and the reasons are identical.
|
|
58
|
+
|
|
59
|
+
Write both buckets in operator voice (`factory-model` rule 5): a person who does not code reads this
|
|
60
|
+
at the gate. "Anyone who can reach the search box can read other customers' orders — reproduced with
|
|
61
|
+
the request transcript below" is usable; "possible SQLi in handler" is not.
|
|
62
|
+
|
|
63
|
+
This bar governs *code-review* security findings. Dependency CVE remediation keeps its own decision
|
|
64
|
+
ladder in the `security-audit-handling` rule — cite it, do not restate or fork it.
|
|
65
|
+
|
|
66
|
+
Bucketing is **advisory** — it shapes the report, it does not block a merge — on the same terms as
|
|
67
|
+
the boundary checks, which stay reporting-only until `verification.gate.enforceBoundaries` is `true`
|
|
68
|
+
in `.lisa.config.json`.
|
|
69
|
+
|
|
19
70
|
## Output Format
|
|
20
71
|
|
|
21
72
|
Structure findings as:
|
|
@@ -41,17 +92,33 @@ Structure findings as:
|
|
|
41
92
|
- [ ] No XSS vectors in user-facing output
|
|
42
93
|
- [ ] Dependencies free of known CVEs
|
|
43
94
|
|
|
44
|
-
###
|
|
45
|
-
- [
|
|
95
|
+
### Security (proven)
|
|
96
|
+
- [finding] -- where in the code, how to prevent
|
|
97
|
+
- reproducer: [evidence ref, e.g. evidence/<ticket>/http-transcript-01.txt]
|
|
98
|
+
- impact: [who can do what, to what data, under what preconditions]
|
|
99
|
+
- reason: reproducer + bounded impact
|
|
100
|
+
|
|
101
|
+
### Security (unproven)
|
|
102
|
+
- [finding] -- where in the code, how to prevent
|
|
103
|
+
- reproducer: [evidence ref if one exists, else `none`]
|
|
104
|
+
- impact: [bounded statement if one exists, else `unproven`]
|
|
105
|
+
- reason: [which half is missing -- e.g. "impact bounded, but never reproduced"]
|
|
106
|
+
-- kept in the security section, not demoted
|
|
46
107
|
|
|
47
108
|
### Recommendations
|
|
48
109
|
- [recommendation] -- priority (critical/warning/suggestion)
|
|
49
110
|
```
|
|
50
111
|
|
|
112
|
+
Rename the unproven heading only when `security.review.unprovenBucket` is set to something other
|
|
113
|
+
than `security-unproven`; everything else stays as written.
|
|
114
|
+
|
|
51
115
|
## Rules
|
|
52
116
|
|
|
53
117
|
- Focus on the specific changes proposed, not a full security audit of the entire codebase
|
|
54
118
|
- Flag only real risks -- do not invent hypothetical threats for internal tooling with no user input
|
|
119
|
+
- Classify every finding against the bar before writing it up; never leave a finding unbucketed
|
|
120
|
+
- Never silently drop or downgrade a finding out of the security section -- `unproven` is the
|
|
121
|
+
conservative landing spot, and the reason line says why
|
|
55
122
|
- Prioritize OWASP Top 10 vulnerabilities
|
|
56
123
|
- If the changes are purely internal (config, refactoring, docs), report "No security concerns" and explain why
|
|
57
124
|
- Always check `.gitleaksignore` patterns to understand what secrets scanning is already in place
|
|
@@ -22,10 +22,30 @@ Run a ZAP baseline security scan against the local application.
|
|
|
22
22
|
- After the scan completes, read `zap-report.html` (or `zap-report.md` for text)
|
|
23
23
|
- Summarize findings:
|
|
24
24
|
- Total number of alerts by risk level (High, Medium, Low, Informational)
|
|
25
|
-
-
|
|
25
|
+
- **Every alert reaches classification** -- High, Medium, Low, and Informational alike. Risk
|
|
26
|
+
level orders the summary; it never filters it. **Nothing is dropped before classification**,
|
|
27
|
+
so no alert can leave the report unclassified. Medium+ alerts are listed first, in full (rule
|
|
28
|
+
ID, name, recommended fix); Low/Informational alerts are still listed, bucketed, and given a
|
|
29
|
+
`reason`, even when compressed to one line each.
|
|
26
30
|
- Categorize findings as "infrastructure-level" (fix at CDN/proxy) vs "application-level" (fix in code)
|
|
27
31
|
|
|
28
|
-
4. **
|
|
32
|
+
4. **Apply the impact-or-exploitability bar** -- the same bar the `lisa-security-review` skill
|
|
33
|
+
defines; follow that skill, do not restate it. A ZAP alert is not a reproducer by itself: the
|
|
34
|
+
alert names a pattern, not an exercised impact path.
|
|
35
|
+
- **Security (proven)** -- the alert carries a reproducer **and** a bounded impact statement. The
|
|
36
|
+
reproducer counts only if its evidence kind **reaches the claim's boundary** under the
|
|
37
|
+
`claim-evidence-mapping` contract (BCE-1, #1835): a ZAP request/response transcript is an
|
|
38
|
+
`http-transcript` and reaches the `http-api` boundary only. An alert whose claim is about
|
|
39
|
+
rendered UI (`browser`) or persisted state (`data`) needs evidence at *that* boundary -- a
|
|
40
|
+
transcript never proves it.
|
|
41
|
+
- **Security (unproven)** -- everything else, each with a one-line `reason` (typically
|
|
42
|
+
"alert only, no reproducer / no bounded impact", or "transcript does not reach the claim's
|
|
43
|
+
boundary"). Unproven alerts are **not dropped** and not demoted out of the security summary --
|
|
44
|
+
they render in the unproven bucket so a reader still sees them.
|
|
45
|
+
- Rename the unproven heading only if `security.review.unprovenBucket` is set to something other
|
|
46
|
+
than `security-unproven`; no other classification changes.
|
|
47
|
+
|
|
48
|
+
5. **Handle failures**:
|
|
29
49
|
- If the scan failed, explain what failed and suggest concrete remediation steps
|
|
30
50
|
|
|
31
51
|
## Execution
|
|
@@ -35,13 +35,30 @@ Structure your findings as:
|
|
|
35
35
|
- [ ] No XSS vectors in user-facing output
|
|
36
36
|
- [ ] Dependencies free of known CVEs
|
|
37
37
|
|
|
38
|
-
###
|
|
39
|
-
- [
|
|
38
|
+
### Security (proven)
|
|
39
|
+
- [finding] -- where in the code, how to prevent
|
|
40
|
+
- reproducer: [evidence ref]
|
|
41
|
+
- impact: [who can do what, to what data, under what preconditions]
|
|
42
|
+
- reason: reproducer + bounded impact
|
|
43
|
+
|
|
44
|
+
### Security (unproven)
|
|
45
|
+
- [finding] -- where in the code, how to prevent
|
|
46
|
+
- reproducer: [evidence ref if one exists, else `none`]
|
|
47
|
+
- impact: [bounded statement if one exists, else `unproven`]
|
|
48
|
+
- reason: [which half is missing -- e.g. "impact bounded, but never reproduced"]
|
|
49
|
+
-- kept in the security section, not demoted
|
|
40
50
|
|
|
41
51
|
### Recommendations
|
|
42
52
|
- [recommendation] -- priority (critical/warning/suggestion)
|
|
43
53
|
```
|
|
44
54
|
|
|
55
|
+
A finding is **proven** only with both a reproducer evidence ref and a bounded impact statement;
|
|
56
|
+
missing either, it stays **unproven** inside the security section. Record the two halves
|
|
57
|
+
independently -- keep whichever one you have and let the `reason` name the missing half; never
|
|
58
|
+
overwrite a real value with a placeholder. The full bar, the per-finding fields, and the
|
|
59
|
+
`security.review.unprovenBucket` policy point live in the `security-review` skill -- follow it, do
|
|
60
|
+
not restate it.
|
|
61
|
+
|
|
45
62
|
## Rules
|
|
46
63
|
|
|
47
64
|
- Focus on the specific changes proposed, not a full security audit of the entire codebase
|