@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.
Files changed (79) hide show
  1. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  2. package/dist/core/upstream-evidence-manifest.js +6 -5
  3. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  4. package/package.json +1 -1
  5. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  6. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  7. package/plugins/lisa/.codex-plugin/skills/lisa-security-review/SKILL.md +69 -2
  8. package/plugins/lisa/.codex-plugin/skills/lisa-security-zap-scan/SKILL.md +22 -2
  9. package/plugins/lisa/agents/security-specialist.md +19 -2
  10. package/plugins/lisa/rules/eager/claim-evidence-mapping.md +9 -2
  11. package/plugins/lisa/rules/reference/claim-evidence-mapping.md +25 -4
  12. package/plugins/lisa/skills/lisa-security-review/SKILL.md +69 -2
  13. package/plugins/lisa/skills/lisa-security-zap-scan/SKILL.md +22 -2
  14. package/plugins/lisa-agy/agents/security-specialist.md +19 -2
  15. package/plugins/lisa-agy/plugin.json +1 -1
  16. package/plugins/lisa-agy/skills/lisa-security-review/SKILL.md +69 -2
  17. package/plugins/lisa-agy/skills/lisa-security-zap-scan/SKILL.md +22 -2
  18. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  20. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  21. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-copilot/agents/security-specialist.agent.md +19 -2
  25. package/plugins/lisa-copilot/rules/eager/claim-evidence-mapping.md +9 -2
  26. package/plugins/lisa-copilot/rules/reference/claim-evidence-mapping.md +25 -4
  27. package/plugins/lisa-copilot/skills/lisa-security-review/SKILL.md +69 -2
  28. package/plugins/lisa-copilot/skills/lisa-security-zap-scan/SKILL.md +22 -2
  29. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-cursor/agents/security-specialist.md +19 -2
  31. package/plugins/lisa-cursor/rules/claim-evidence-mapping-reference.mdc +25 -4
  32. package/plugins/lisa-cursor/rules/claim-evidence-mapping.mdc +9 -2
  33. package/plugins/lisa-cursor/skills/lisa-security-review/SKILL.md +69 -2
  34. package/plugins/lisa-cursor/skills/lisa-security-zap-scan/SKILL.md +22 -2
  35. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  37. package/plugins/lisa-expo-agy/plugin.json +1 -1
  38. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  42. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  43. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  48. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  52. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  53. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  55. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  57. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  58. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  60. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  61. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  62. package/plugins/lisa-rails-agy/plugin.json +1 -1
  63. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  65. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  67. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  68. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  72. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  73. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  75. package/plugins/src/base/agents/security-specialist.md +19 -2
  76. package/plugins/src/base/rules/eager/claim-evidence-mapping.md +9 -2
  77. package/plugins/src/base/rules/reference/claim-evidence-mapping.md +25 -4
  78. package/plugins/src/base/skills/lisa-security-review/SKILL.md +69 -2
  79. package/plugins/src/base/skills/lisa-security-zap-scan/SKILL.md +22 -2
@@ -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. The conservative security-bucket default is set in **BCE-5 (#1839)** — named
41
- here, defined there.
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 conservative default bucket for a security-sensitive claim is set in
86
- **BCE-5 (#1839)** named here as a field BCE-2's schema carries, not defined by this contract, and
87
- it ships with that ticket. Where such a sibling surface is not installed in a given branch, name what
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
- ### Vulnerabilities Found
45
- - [vulnerability] -- where in the code, how to prevent
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
- - List each Medium+ finding with its rule ID, name, and recommended fix
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. **Handle failures**:
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -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
- ### Vulnerabilities Found
39
- - [vulnerability] -- where in the code, how to prevent
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
@@ -87,10 +87,9 @@ defines the names; it stores nothing:
87
87
  A claim whose `required_evidence_kinds` has no captured, reaching artifact is **Not established** —
88
88
  defined in full, with its evidence templates, in the section below. Artifact identity — what makes
89
89
  two captured artifacts the same or different — is defined in the *Artifact identity* section below
90
- (shipped by BCE-4, #1838). The conservative default bucket for a security-sensitive claim is set in
91
- **BCE-5 (#1839)** named here as a field BCE-2's schema carries, not defined by this contract, and
92
- it ships with that ticket. Where such a sibling surface is not installed in a given branch, name what
93
- you can and continue.
90
+ (shipped by BCE-4, #1838). The bucket a security-sensitive claim lands in is defined in the *Security
91
+ buckets* section below (shipped by BCE-5, #1839). Where such a sibling surface is not installed in a
92
+ given branch, name what you can and continue.
94
93
 
95
94
  ### Worked example
96
95
 
@@ -184,6 +183,28 @@ second one. Identity reconciliation is the same definition read from the evidenc
184
183
 
185
184
  Two guards, one definition — so they cannot disagree about what shipped.
186
185
 
186
+ ## Security buckets — the impact-or-exploitability bar
187
+
188
+ A security-shaped claim is a claim like any other: it reaches only as far as its evidence. Applied to
189
+ security findings (shipped by BCE-5, #1839), that yields two buckets and one bar:
190
+
191
+ - **Security (proven)** — the finding carries **both** a `reproducer` (an evidence ref of a kind that
192
+ reaches the claim's boundary, per the taxonomy above — e.g. an `http-transcript` for an injection
193
+ claim at `http-api`) **and** a bounded `impact`/exploitability statement.
194
+ - **Security (unproven)** — **missing either**. It keeps a one-line `reason` and **stays in the
195
+ security section**: a reproducer-less finding is **never auto-demoted** to a `maintenance` bucket,
196
+ because under-reporting a real vulnerability is the worse failure.
197
+
198
+ The unproven bucket's label is the single configurable policy point —
199
+ `security.review.unprovenBucket` in `.lisa.config.json`, default `security-unproven`. An owner who
200
+ prefers true demotion flips that one value; no other classification logic changes. Like the boundary
201
+ checks, bucketing is **advisory** — it shapes the report, not the merge — until
202
+ `verification.gate.enforceBoundaries` is `true`.
203
+
204
+ The full procedure — per-finding fields, report shape, ZAP alignment — lives in the
205
+ `lisa-security-review` skill (with `lisa-security-zap-scan` citing it); dependency-CVE remediation
206
+ keeps its separate ladder in `security-audit-handling`. Cite those slugs; do not restate them here.
207
+
187
208
  ## The "Not established" section — required, never omitted
188
209
 
189
210
  Every report that asserts something was verified also states, in the same breath, **what it did not
@@ -42,8 +42,15 @@ rule 5).
42
42
  A claim carries three fields — `claim_id`, `boundary`, and `required_evidence_kinds` — named here so
43
43
  every downstream surface uses one spelling. This ticket only writes the contract down; the schema and
44
44
  gate that make these fields executable ship with **BCE-2 (#1836)** — do not assume that surface is
45
- present in this branch. The conservative security-bucket default is set in **BCE-5 (#1839)** — named
46
- here, defined there.
45
+ present in this branch.
46
+
47
+ ## Security buckets (conservative by default)
48
+
49
+ A security finding is **proven** only with both a reproducer of a reaching kind and a bounded
50
+ impact/exploitability statement; missing either, it renders **unproven** with its reason and **stays
51
+ in the security section** — never auto-demoted to maintenance. The label is one policy point,
52
+ `security.review.unprovenBucket` (default `security-unproven`); the procedure lives in the
53
+ `lisa-security-review` skill.
47
54
 
48
55
  ## Artifact identity (pinned, never assumed)
49
56
 
@@ -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
- ### Vulnerabilities Found
45
- - [vulnerability] -- where in the code, how to prevent
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
- - List each Medium+ finding with its rule ID, name, and recommended fix
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. **Handle failures**:
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-phaser",
3
- "version": "2.264.0",
3
+ "version": "2.265.0",
4
4
  "description": "Phaser 4 game-development rules for TypeScript projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"