ktg-plugin-marketplace/plugins/llm-security/commands/diff.md
Kjell Tore Guttormsen 03b8885b6e chore(llm-security): v7.7.2 — language consistency pass
~/.claude/CLAUDE.md specifies English for code and documentation,
Norwegian for dialog only. Norwegian had crept into surface text
across v7.5-v7.7. Translated to English in eight surfaces.

No scanner, hook, or behavior changes — purely surface text.

- 18 skill commands: the HTML Report-step now reads "HTML report:
  [Open in browser]" instead of "HTML-rapport: [Åpne i nettleser]"
- scripts/lib/report-renderers.mjs: key-stat labels, lede defaults,
  table headers, maturity-ladder descriptions, action-tier labels,
  clean buckets, dry-run/apply copy, and JS comments. Regex
  alternations /^high|^høy/ and /resolution|løsning/i preserved.
- playground/llm-security-playground.html: same renderer changes
  mirrored bit-identical, plus playground-only UI strings (catalog,
  breadcrumb aria-label, theme toggle, builder-modal hint,
  guide-panel "no projects yet", delete confirmation, alert/copy).
  Demo-state fixture content for dft-komplett-demo preserved
  (intentional Norwegian persona).
- agents/skill-scanner-agent.md + agents/mcp-scanner-agent.md:
  Generaliseringsgrense + Parallell Read-strategi sections translated
  to Generalization boundary + Parallel Read strategy.
- README.md: playground architecture prose + Recent versions table
  (v7.5.0 — v7.7.1).
- CLAUDE.md: v7.7.1 highlights translated, new v7.7.2 highlights
  added.
- ../../README.md: llm-security v7.5.0 — v7.7.1 bullets.
- ../../CLAUDE.md: llm-security catalog entry.
- docs/scanner-reference.md: six runnable-examples table cells.
- docs/version-history.md: new v7.7.2 entry. v7.5-v7.7 narrative
  sections left in original language (deferred per operator).
- Version bumped 7.7.1 → 7.7.2 in package.json,
  .claude-plugin/plugin.json, README badge + Recent versions,
  CLAUDE.md header + state, docs/version-history.md, playground
  renderHome hardcoded string, root README + CLAUDE.md llm-security
  entries.

Tests: 1820/1820 green. CLI smoke-test: 18/18 commandIds produce
>138 KB self-contained HTML. Browser-dogfood verified.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 06:47:44 +02:00

118 lines
3.7 KiB
Markdown

---
name: security:diff
description: Compare scan results against a stored baseline — shows new, resolved, unchanged, and moved findings
allowed-tools: Bash, Read, AskUserQuestion
model: sonnet
---
# /security diff [path]
Run a deterministic deep scan and compare results against a stored baseline. Shows what changed since the last saved scan.
## Step 1: Check for Existing Baseline
Determine plugin root (parent of this `commands/` folder) and target path from `$ARGUMENTS` (default `.`).
Check if a baseline already exists:
```bash
ls -la <plugin-root>/reports/baselines/ 2>/dev/null
```
If baseline files exist for the target, inform the user:
> A baseline already exists. Running `/security diff` will overwrite it with new results.
Use AskUserQuestion to ask: "Overwrite existing baseline and run diff? (The previous baseline will be replaced.)"
If the user declines, exit without scanning. If the user confirms (or no baseline exists yet), proceed to Step 2.
## Step 2: Run Scan with Baseline Comparison
```bash
node <plugin-root>/scanners/scan-orchestrator.mjs "<target>" --baseline --save-baseline
```
Parse stdout JSON. The scan runs all 9 scanners, diffs against any existing baseline, then saves the new results as the current baseline.
If no baseline exists yet (`diff` is `null` in output), this is a first run — report that a baseline has been created and show the current scan summary instead of a diff.
## Step 3: Display Results
### First run (no prior baseline)
```
## Baseline Created
No prior baseline found. Current scan saved as baseline.
**Findings:** XC XH XM XL XI | **Risk Score:** X/100 | **Verdict:** ALLOW/WARNING/BLOCK
Run `/security diff` again after making changes to see the delta.
```
### Subsequent runs (diff available)
```
## Security Diff: <target>
**Baseline:** <baseline_timestamp> → **Current:** <now>
### Summary
| Category | Count |
|----------|-------|
| New | X |
| Resolved | X |
| Moved | X |
| Unchanged| X |
```
For **New** findings (sorted critical → info):
```
### New Findings (X)
| # | Severity | Scanner | Title | File | OWASP |
```
For **Resolved** findings:
```
### Resolved Findings (X)
| # | Severity | Scanner | Title | File | OWASP |
```
For **Moved** findings (only if count > 0):
```
### Moved Findings (X)
| # | Severity | Scanner | Title | File | Previous Location |
```
Omit Unchanged findings from the output — they add noise. Mention count in summary only.
## Step 4: Advisory
- If new CRITICAL/HIGH findings: "**Action required:** X new critical/high findings since baseline."
- If resolved > new: "**Improving:** more findings resolved than introduced."
- If new > 0 and resolved == 0: "**Regression:** X new findings, none resolved."
- If new == 0 and resolved == 0: "**Stable:** no changes since baseline."
## Step 5: HTML Report
After producing the markdown diff report above:
1. Compute a temp markdown path:
```bash
node -p "require('path').join(require('os').tmpdir(), 'sec-diff-' + Date.now() + '.md')"
```
2. Use the Write tool to save the **entire markdown report you just produced** (banner with baseline+current timestamps + Summary table + New + Resolved + Moved sections + Advisory) to that temp path. Verbatim.
3. Run the renderer:
```bash
node <plugin-root>/scripts/render-report.mjs diff --in "<temp-md-path>"
```
The CLI writes `reports/diff-<YYYYMMDD-HHmmss>.html` relative to CWD and prints `file:///abs/path.html` on stdout.
4. Append to your response (markdown link, no bare URL):
> **HTML report:** [Open in browser](file:///abs/path.html)
If the CLI exits non-zero, mention the error but do not block — the markdown report above is the primary deliverable.