--- 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 /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 /scanners/scan-orchestrator.mjs "" --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: **Baseline:** → **Current:** ### 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 /scripts/render-report.mjs diff --in "" ``` The CLI writes `reports/diff-.html` relative to CWD and prints `file:///abs/path.html` on stdout. 4. Append to your response (markdown link, no bare URL): > **HTML-rapport:** [Åpne i nettleser](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.