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>
This commit is contained in:
parent
4f6fc4a2a5
commit
03b8885b6e
31 changed files with 467 additions and 359 deletions
|
|
@ -10,7 +10,7 @@ plugins/
|
|||
config-audit/ v3.1.0 — Configuration intelligence (health, opportunities, auto-fix, whats-active)
|
||||
graceful-handoff/ v2.1.0 — Auto-trigger handoff via Stop hook (skill + JSON pipeline + 4-step model-aware context resolution)
|
||||
linkedin-thought-leadership/ v1.2.0 — LinkedIn content pipeline + analytics
|
||||
llm-security/ v7.7.1 — Security scanning, auditing, threat modeling + HTML-rapport for alle 18 skill-kommandoer (render-report CLI + canonical ESM-modul som speiles bit-identisk i playground). v7.7.1 strippet playground til katalog-overflate som eneste rute.
|
||||
llm-security/ v7.7.2 — Security scanning, auditing, threat modeling. HTML report output for all 18 skill commands (render-report CLI + canonical ESM module mirrored bit-identical into the playground). v7.7.2 translated the remaining Norwegian surface text in the playground UI, the canonical renderer, the agent prompts, and the README/CLAUDE.md state sections to English. v7.7.1 stripped the playground to the catalog as the only routable surface.
|
||||
ms-ai-architect/ v1.15.0 — Microsoft AI architecture (Cosmo Skyberg persona) + manual KB-refresh slash command + v3 project-view (sidebar med 17 artifacts + main + import-modal overlay, v2-surface fjernet i v1.15.0)
|
||||
okr/ v1.0.0 — OKR guidance for Norwegian public sector
|
||||
voyage/ v5.0.3 — Brief, research, plan, execute, review, continue. Contract-driven Claude Code pipeline (six-command universal pipeline + multi-session resumption + --gates autonomy chain). /trekbrief, /trekplan, and /trekreview each end by running scripts/annotate.mjs against the just-written .md and printing the file:// link to a self-contained operator-annotation HTML modelled on claude-code-100x/build-site.js: pencil-toggle annotation mode, select text or click any element, choose intent (Fiks/Endre/Spørsmål), comment, sidebar groups by section with delete + Copy Prompt, localStorage persistence per artifact path. v5.0.0 removed the v4.2/v4.3 bespoke playground + /trekrevise + Handover 8; v5.0.1 pointed at /playground document-critique (wrong direction); v5.0.2 was operator-led but too thin; v5.0.3 matches the reference the operator pointed at from day one.
|
||||
|
|
|
|||
13
README.md
13
README.md
|
|
@ -26,7 +26,7 @@ Then open Claude Code and type `/plugin` to browse and install plugins from the
|
|||
|
||||
## Plugins
|
||||
|
||||
### [LLM Security](plugins/llm-security/) `v7.7.1`
|
||||
### [LLM Security](plugins/llm-security/) `v7.7.2`
|
||||
|
||||
Security scanning, auditing, and threat modeling for agentic AI projects.
|
||||
|
||||
|
|
@ -36,11 +36,12 @@ Built on OWASP LLM Top 10 (2025), OWASP Agentic AI Top 10, and the AI Agent Trap
|
|||
- **Deterministic scanning** — 23 Node.js scanners (10 orchestrated + 13 standalone) for byte-level analysis: Shannon entropy, Unicode codepoints, typosquatting detection, taint flow, DNS resolution, git forensics, AI-BOM, attack simulation, IDE extension prescan (VS Code + JetBrains — URL fetch from Marketplace / OpenVSX / direct VSIX / JetBrains Marketplace, hardened ZIP extractor for zip-slip / symlinks / bombs, plus OS sandbox via `sandbox-exec` / `bwrap` so the kernel enforces FS confinement), MCP cumulative-drift baseline reset (E14 — sticky baseline catches slow-burn rug-pulls). Bash-normalize T1-T6 for obfuscation-resistant denylists
|
||||
- **Advisory analysis** — 20 commands that scan, audit, and model threats with structured reports, letter grades, and actionable remediation
|
||||
- **Enterprise governance** — Compliance mapping (EU AI Act, NIST AI RMF, ISO 42001), SARIF 2.1.0 output, structured audit trail, policy-as-code, standalone CLI
|
||||
- **v7.7.1 playground UX-strip (2026-05-18)** — Operatør-feedback umiddelbart etter v7.7.0: katalog-overflaten ble eneste levende rute i playgrounden (onboarding/home/project-render-funksjonene bevart men ikke rutbare). Topbar forenklet til `Katalog`-knapp + state/tema-handlinger. Breadcrumb-orgname erstattet med nøytralt `llm-security`. Onboarding-konseptet (kontekst-injeksjon per kommando) dokumentert som v7.8.0-kandidat i ROADMAP. Ingen scanner- eller hook-atferdsendringer
|
||||
- **v7.7.0 HTML-rapport for alle 18 skill-kommandoer (2026-05-18)** — Hver `/security <cmd>` som produserer rapport printer nå en klikkbar `file://`-lenke til en self-contained HTML-versjon. Levert over fem sesjoner: (1) playground katalog list-view + builder-pane med copy-knapp; (2) playground prosjekt-surface opprydding (stub-screen + topbar-splitt); (3) 18 inline parserne + rendererne flyttet til canonical ESM-modul `scripts/lib/report-renderers.mjs` (playground beholder bit-identisk inline-kopi siden ESM `import` ikke fungerer fra `file://`); (4) ny zero-dep CLI `scripts/render-report.mjs` — stdin/file/stdout-modus, kebab→camel commandId-routing, inliner 6 DS-stylesheets, ~140 KB self-contained HTML med system-font-fallback, absolutte `file://`-paths for Ghostty cmd-click; (5) alle 18 skills wired (4 i sesjon 4 + 14 i sesjon 5). Ingen scanner- eller hook-atferdsendringer — purely additive
|
||||
- **v7.6.1 playground visuell-patch (2026-05-06)** — Seks bugs fanget av maintainer ved manuell verifisering i nettleser etter v7.6.0-release. Alle skyldtes mismatch mellom DS-klasser og hvordan playground-rendrere brukte dem (eller manglende DS-implementasjoner av klasser playground-rendrere antok eksisterte): `renderFindingsBlock` brukte `.findings` outer-class (DS' 2-kolonners list+detail-grid) → erstattet med `<section class="report-meta">` + korrekt `findings__list`-mønster; `.report-table` manglet helt i DS men brukes i 7+ rendrere → lokal CSS-implementasjon; `renderPreDeploy` traffic-lights brukte fast 28×28 px `.sm-card__grade` for "PASS"/"PASS-WITH-NOTES"/"FAIL" → bredde-tilpasset status-pill; threat-model matrix-bobler ikke klikkbare → `<button>` med `data-threat-id` + click-handler som scroller til Trusler-tabellen; radar-labels overlappet → SVG 280→380, R 105→125, dynamisk `text-anchor`; `recommendation-card__body` tekstoverflyt → `overflow-wrap: anywhere`. 4/4 fix-spesifikke + 18/18 regresjons-tester passerer. Ingen scanner- eller hook-atferdsendringer
|
||||
- **v7.6.0 playground Tier 3-referanse-case (2026-05-06)** — Playgroundet er hevet til en visuelt og strukturelt fullført referanse for `shared/playground-design-system/` Tier 3-supplementet. 8 nye DS-komponenter integrert i de 18 rapport-rendererne: `tfa-flow` + `tfa-leg` + `tfa-arrow` (lethal trifecta-kjede med `<button>`-elementer + ARIA), `mat-ladder` + `mat-step` (5-trinns modenhets-stige), `suppressed-group` (narrative-audit), `codepoint-reveal` + `cp-tag/cp-zw/cp-bidi` (Unicode-steganografi), `top-risks` + `top-risk[data-severity]` (rangert top-funn-listing), utvidet `recommendation-card[data-severity]` på `clean`/`harden`/`audit`/`posture`/`pre-deploy`/`plugin-audit`, `risk-meter` (band-visualisering 0-100 på 5 archetypes), `card--severity-{level}` modifier på findings-cards. Wave 1 (Sesjon 2): `badge--scope-security` (identitets-chip), `verdict-pill-lg` (DS Tier 3-pill på alle 18 rapport-typer), `form-progress` + `fp-step` (onboarding-wizard). Slettet ~30 duplikat-CSS-deklarasjoner (DS vinner cascade). 5 nye DS-helpers + `mapSeverityToCardLevel` + `parseNarrativeAudit`. A11Y-rapport oppdatert. Filendring totalt 10209 → 10677 linjer over 5 sesjoner. Ingen scanner- eller hook-behavior-changes — purely additive surface
|
||||
- **v7.5.0 playground (2026-05-05)** — Single-file SPA at `plugins/llm-security/playground/llm-security-playground.html` (~10 200 lines) for onboarding, demoer og workshop-bruk uten Claude Code-installasjon. Parsere + renderere for alle 18 produces_report-kommandoer, 18 markdown test-fixtures som kontrakt-anker, komplett demo-prosjekt med alle 18 rapporter ferdig parsed, vendor-synket design-system, 9 Playwright-genererte screenshots. 11 nye `window`-globaler eksponert for testing/automasjon (`__store`, `__navigate`, `__loadDemoState`, `__PARSERS`, `__RENDERERS` …). Bug-fix: `normalizeVerdictText` håndterer GO-WITH-CONDITIONS uten å kollapse til ALLOW. Ingen scanner- eller hook-behavior-changes — purely additive surface
|
||||
- **v7.7.2 language consistency pass (2026-05-19)** — Norwegian had crept into surface text across v7.5-v7.7. Per the `~/.claude/CLAUDE.md` convention (English for code and documentation, Norwegian for dialog only), this release translates the HTML Report-step in all 18 skill commands, the canonical CLI renderer `scripts/lib/report-renderers.mjs`, the playground UI strings, the skill-scanner and mcp-scanner agent prompts, the marketplace + plugin README/CLAUDE.md state sections, and six table cells in `docs/scanner-reference.md`. Demo-state fixture content for the `dft-komplett-demo` project (intentional Norwegian persona) and regex alternations that match Norwegian-language report markdown (`/^high\|^høy/`, `/resolution\|løsning/`) were preserved. No scanner, hook, or behavior changes — purely surface text
|
||||
- **v7.7.1 playground UX strip (2026-05-18)** — Operator feedback immediately after v7.7.0: the catalog became the only routable surface in the playground (the onboarding/home/project render functions remain in source but are not routable). Topbar simplified to a `Catalog` button + state/theme actions. Breadcrumb org-name replaced with a neutral `llm-security`. The onboarding concept (per-command context injection) is documented as a v7.8.0 candidate in ROADMAP. No scanner or hook behavior changes
|
||||
- **v7.7.0 HTML report for all 18 skill commands (2026-05-18)** — Every `/security <cmd>` that produces a report now prints a clickable `file://` link to a self-contained HTML version. Delivered across five sessions: (1) playground catalog list-view + builder-pane with a copy button; (2) playground project-surface cleanup (stub-screen + topbar split); (3) the 18 inline parsers + renderers moved to a canonical ESM module `scripts/lib/report-renderers.mjs` (the playground keeps a bit-identical inline copy since ESM `import` does not work from `file://`); (4) new zero-dep CLI `scripts/render-report.mjs` — stdin/file/stdout mode, kebab→camel commandId routing, inlines 6 DS stylesheets, ~140 KB self-contained HTML with system-font fallback, absolute `file://` paths for Ghostty cmd-click; (5) all 18 skills wired (4 in session 4 + 14 in session 5). No scanner or hook behavior changes — purely additive
|
||||
- **v7.6.1 playground visual patch (2026-05-06)** — Six bugs caught by the maintainer during manual browser verification after the v7.6.0 release. All were mismatches between DS classes and how playground renderers used them (or missing DS implementations the renderers assumed existed): `renderFindingsBlock` used the `.findings` outer class (the DS 2-column list+detail grid) → replaced with `<section class="report-meta">` + the correct `findings__list` pattern; `.report-table` was missing entirely from the DS but used in 7+ renderers → local CSS implementation; `renderPreDeploy` traffic-lights used the fixed 28×28 px `.sm-card__grade` for "PASS"/"PASS-WITH-NOTES"/"FAIL" → width-adapting status pill; threat-model matrix bubbles were not clickable → `<button>` with `data-threat-id` + click handler that scrolls to the Threats table; radar labels overlapped → SVG 280→380, R 105→125, dynamic `text-anchor`; `recommendation-card__body` text overflow → `overflow-wrap: anywhere`. 4/4 fix-specific + 18/18 regression tests passing. No scanner or hook behavior changes
|
||||
- **v7.6.0 playground Tier 3 reference case (2026-05-06)** — The playground was raised to a visually and structurally complete reference for the `shared/playground-design-system/` Tier 3 supplement. 8 new DS components integrated into the 18 report renderers: `tfa-flow` + `tfa-leg` + `tfa-arrow` (lethal trifecta chain with `<button>` elements + ARIA), `mat-ladder` + `mat-step` (5-step maturity ladder), `suppressed-group` (narrative audit), `codepoint-reveal` + `cp-tag/cp-zw/cp-bidi` (Unicode steganography), `top-risks` + `top-risk[data-severity]` (ranked top-findings listing), extended `recommendation-card[data-severity]` on `clean`/`harden`/`audit`/`posture`/`pre-deploy`/`plugin-audit`, `risk-meter` (0-100 band visualization across 5 archetypes), `card--severity-{level}` modifier on findings cards. Wave 1 (Session 2): `badge--scope-security` (identity chip), `verdict-pill-lg` (DS Tier 3 pill across all 18 report types), `form-progress` + `fp-step` (onboarding wizard). Removed ~30 duplicate CSS declarations (DS wins the cascade). 5 new DS helpers + `mapSeverityToCardLevel` + `parseNarrativeAudit`. A11Y report updated. File size 10209 → 10677 lines across 5 sessions. No scanner or hook behavior changes — purely additive surface
|
||||
- **v7.5.0 playground (2026-05-05)** — Single-file SPA at `plugins/llm-security/playground/llm-security-playground.html` (~10 200 lines) for onboarding, demos and workshop use without a Claude Code installation. Parsers + renderers for all 18 produces_report commands, 18 markdown test fixtures as contract anchors, a complete demo project with all 18 reports parsed in advance, vendor-synced design-system, 9 Playwright-generated screenshots. 11 new `window` globals exposed for testing/automation (`__store`, `__navigate`, `__loadDemoState`, `__PARSERS`, `__RENDERERS` …). Bug-fix: `normalizeVerdictText` handles GO-WITH-CONDITIONS without collapsing to ALLOW. No scanner or hook behavior changes — purely additive surface
|
||||
- **v7.4.0 examples + e2e suite (2026-05-05)** — 9 runnable demonstration walkthroughs under `examples/` (lethal-trifecta, mcp-rug-pull, supply-chain-attack, poisoned-claude-md, bash-evasion-gallery, prompt-injection-showcase, malicious-skill-demo, toxic-agent-demo, pre-compact-poisoning) plus three new test suites under `tests/e2e/` (attack-chain, multi-session, scan-pipeline) that prove the framework works as a coordinated system. +45 tests (1777 → 1822), no scanner or hook behavior changes — purely additive surface
|
||||
- **v8.0.0 env-var deprecation runway (D3, v7.3.0)** — Hook configuration has historically been split between process env-vars and the team-distributable `.llm-security/policy.json` file. Until v7.3.0 the two surfaces could disagree silently. The new `getPolicyValueWithEnvWarn()` helper in `scanners/lib/policy-loader.mjs` now emits a one-time-per-process stderr line whenever both surfaces are explicitly set:
|
||||
- Affected pairs: `LLM_SECURITY_INJECTION_MODE`↔`injection.mode`, `LLM_SECURITY_TRIFECTA_MODE`↔`trifecta.mode`, `LLM_SECURITY_ESCALATION_WINDOW`↔`trifecta.escalation_window` (new key in `DEFAULT_POLICY`), `LLM_SECURITY_AUDIT_LOG`↔`audit.log_path`
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "llm-security",
|
||||
"description": "Security scanning, auditing, and threat modeling for Claude Code projects. Detects secrets, validates MCP servers, assesses security posture, and generates threat models aligned with OWASP LLM Top 10.",
|
||||
"version": "7.7.1"
|
||||
"version": "7.7.2"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,83 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [7.7.2] - 2026-05-19
|
||||
|
||||
Language consistency pass. Norwegian had crept into surface text across
|
||||
v7.5-v7.7. Per the `~/.claude/CLAUDE.md` convention (English for code and
|
||||
documentation, Norwegian for dialog only), surface text was translated to
|
||||
English. No scanner, hook, or behavior changes — purely surface text.
|
||||
|
||||
### Changed
|
||||
|
||||
- **18 skill commands `commands/*.md`** — the "HTML Report"-step appended
|
||||
by each `/security <cmd>` flow now reads
|
||||
`> **HTML report:** [Open in browser](file:///abs/path.html)` (previously
|
||||
Norwegian).
|
||||
- **CLI canonical module `scripts/lib/report-renderers.mjs`** — translated
|
||||
KEY_STATS_CONFIG labels (`TOTALT` → `TOTAL`, `KRITISK` → `CRITICAL`,
|
||||
`HØY` → `HIGH`, `FUNN` → `FINDINGS`, `PROSJEKTER` → `PROJECTS`,
|
||||
`MASKINKLASSE` → `MACHINE GRADE`, `SVAKEST` → `WEAKEST`,
|
||||
`NÅ-GRADE` → `CURRENT GRADE`, `AKSJONER` → `ACTIONS`, `MODUS` → `MODE`),
|
||||
the 5-step maturity ladder descriptions, the suppressed-group desc,
|
||||
4 table-header sets, the 6 renderer `lede` defaults (plugin-audit,
|
||||
mcp-audit, harden, diff, watch, clean), the action tier labels
|
||||
(Umiddelbar/Høy prioritet/Medium prioritet → Immediate/High priority/
|
||||
Medium priority), the clean buckets, and the dry-run/apply text. JS
|
||||
comments translated for consistency. Preserved the regex alternations
|
||||
`/^high|^høy/` and `/resolution|løsning/i` — they intentionally match
|
||||
Norwegian-language report markdown.
|
||||
- **Playground `playground/llm-security-playground.html`** — the same
|
||||
display strings as the canonical module (kept bit-identical), plus
|
||||
playground-specific UI text: catalog row labels, search placeholder,
|
||||
breadcrumb aria-label, theme-toggle labels, primary nav aria-label,
|
||||
builder-modal hints, "no projects yet" guide-panel, delete-project
|
||||
confirmation, alert/copy-confirm strings, and the field-from-tag
|
||||
"felles" pill (now "shared"). The hardcoded `Plugin v7.7.1` in
|
||||
`renderHome` bumped to `Plugin v7.7.2`, and `prosjekter`/`kommandoer`
|
||||
there became `projects`/`commands`. Demo-state fixture content for the
|
||||
`dft-komplett-demo` project (intentional Norwegian persona) and regex
|
||||
tokens were preserved.
|
||||
- **Agent prompts `agents/skill-scanner-agent.md` +
|
||||
`agents/mcp-scanner-agent.md`** — translated the `Generaliseringsgrense`
|
||||
and `Parallell Read-strategi` sections (identical content in both files)
|
||||
to `Generalization boundary` and `Parallel Read strategy`.
|
||||
- **`README.md`** — translated the Recent versions table rows for v7.5.0
|
||||
→ v7.7.1 and the playground architecture prose (L495-553). Version
|
||||
badge bumped to 7.7.2.
|
||||
- **`CLAUDE.md`** — translated the v7.7.1 highlights paragraph and added a
|
||||
new v7.7.2 highlights paragraph. Header and "release notes" sentinel
|
||||
bumped to v7.7.2.
|
||||
- **Marketplace root `../../README.md`** — translated the v7.5.0 → v7.7.1
|
||||
llm-security bullet entries (lines 39-43). Version label in the
|
||||
header bumped to v7.7.2. The voyage and ms-ai-architect entries on
|
||||
lines 90-91 / 192-197 were not touched (strict plugin scope).
|
||||
- **Marketplace root `../../CLAUDE.md`** — translated the llm-security
|
||||
catalog entry on line 13 and bumped its version to v7.7.2.
|
||||
- **`docs/scanner-reference.md`** — translated the six runnable-examples
|
||||
table cells (L114-122) and the surrounding paragraph.
|
||||
- **`docs/version-history.md`** — added a v7.7.2 entry describing this
|
||||
pass. The v7.5.0 → v7.7.1 narrative sections retain the Norwegian they
|
||||
were written in (deferred per operator decision).
|
||||
- **`package.json` + `.claude-plugin/plugin.json`** — version 7.7.1 →
|
||||
7.7.2.
|
||||
|
||||
### Preserved (intentional Norwegian)
|
||||
|
||||
- Demo-state `dft-komplett-demo` JSON `description`, `system_description`,
|
||||
and parsed-data `"label": "HØY"` / `"label": "NÅ-GRADE"` entries —
|
||||
intentional Norwegian persona for the public-sector reference scenario.
|
||||
- Regex alternations `/^high|^høy/` and `/resolution|løsning/i` in both
|
||||
the canonical renderer and the playground inline copy — they let
|
||||
reports written in Norwegian still parse and route correctly.
|
||||
- `knowledge/norwegian-context.md` and other knowledge files — out of
|
||||
scope.
|
||||
- The v7.5.0 → v7.7.1 entries in CHANGELOG.md and `docs/version-history.md`
|
||||
remain in the language they were written in; rewriting historical
|
||||
release notes was deferred.
|
||||
- `REMEMBER.md`, `TODO.md`, `ROADMAP.md`, `*.local.md`, commit messages,
|
||||
test fixtures, and the `playground/A11Y-RAPPORT.md` artifact.
|
||||
|
||||
## [7.7.1] - 2026-05-18
|
||||
|
||||
Playground UX-strip etter v7.7.0-operatør-feedback. Hjem-overflaten ledet
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
# LLM Security Plugin (v7.7.1)
|
||||
# LLM Security Plugin (v7.7.2)
|
||||
|
||||
Security scanning, auditing, and threat modeling for Claude Code projects. 5 frameworks: OWASP LLM Top 10, Agentic AI Top 10 (ASI), Skills Top 10 (AST), MCP Top 10, AI Agent Traps (DeepMind). 1820+ unit, integration, and end-to-end tests (`tests/e2e/` covers the multi-hook attack chain, multi-session state simulation, and the full scan-orchestrator pipeline); mutation-testing coverage not published.
|
||||
|
||||
Release notes for v7.0.0 → v7.7.1: see `docs/version-history.md` — read on demand.
|
||||
Release notes for v7.0.0 → v7.7.2: see `docs/version-history.md` — read on demand.
|
||||
|
||||
**v7.7.1 highlights** — Playground UX-strip etter operatør-feedback: katalog er nå eneste levende overflate (onboarding/home/project-render-funksjonene er bevart i kildekoden men ikke rutbare før funksjonalitet legges til igjen). Topbar-breadcrumb leser ikke lenger demo-state-orgnavn; viser nøytralt `llm-security · Katalog`. Hardkodet versjons-streng i `renderHome` synket. Ingen scanner- eller hook-atferdsendringer.
|
||||
**v7.7.2 highlights** — Language consistency pass. Norwegian had crept into the playground UI strings, the canonical CLI renderer (`scripts/lib/report-renderers.mjs`), the HTML Report-step appended by all 18 skill commands, two agent prompts, and the marketplace + plugin README/CLAUDE.md state sections. Per the `~/.claude/CLAUDE.md` convention (English for code and documentation, Norwegian for dialog only), surface text was translated to English. Demo-state fixture content for the `dft-komplett-demo` project (intentional Norwegian persona) and regex alternations that match Norwegian-language report markdown (`/^high|^høy/`, `/resolution|løsning/`) were preserved. No scanner, hook, or behavior changes.
|
||||
|
||||
**v7.7.0 highlights** — All 18 report-producing skill commands now emit a clickable `file://` link to a self-contained HTML version of their markdown report. The new `scripts/render-report.mjs` CLI converts any of the 18 report types via a canonical `scripts/lib/report-renderers.mjs` (18 parsers + 18 renderers, bit-identical to the playground). HTML wraps the Tier 1/2/3 design system inline; no external assets, system fonts only (~140 KB per report). Playground also got list-view, copy-button, and prosjekt-surface cleanup.
|
||||
**v7.7.1 highlights** — Playground UX strip after operator feedback: the catalog is now the only routable surface (the onboarding/home/project render functions remain in source but are not routable until the feature is restored). The topbar breadcrumb no longer reads the demo-state org name; it shows a neutral `llm-security · Catalog`. The hardcoded version string in `renderHome` was synced. No scanner or hook behavior changes.
|
||||
|
||||
**v7.7.0 highlights** — All 18 report-producing skill commands now emit a clickable `file://` link to a self-contained HTML version of their markdown report. The new `scripts/render-report.mjs` CLI converts any of the 18 report types via a canonical `scripts/lib/report-renderers.mjs` (18 parsers + 18 renderers, bit-identical to the playground). HTML wraps the Tier 1/2/3 design system inline; no external assets, system fonts only (~140 KB per report). Playground also got list-view, copy-button, and project-surface cleanup.
|
||||
|
||||
## Commands
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
*AI-generated: all code produced by Claude Code through dialog-driven development. [Full disclosure →](../../README.md#ai-generated-code-disclosure)*
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
|
@ -492,16 +492,16 @@ a browser (Chrome/Firefox/Safari over `file://`) — no build step, no
|
|||
network calls, no npm install. Theme-bootstrap with FOUC-prevention; state
|
||||
persisted in IndexedDB primary + localStorage fallback.
|
||||
|
||||
**v7.6.0 Tier 3-referanse-case:** Playgroundet er nå en visuelt og
|
||||
strukturelt fullført referanse for `shared/playground-design-system/`
|
||||
Tier 3-supplementet. 8 nye DS-komponenter integrert i de 18 rapport-
|
||||
rendererne: `tfa-flow` (lethal trifecta-kjede), `mat-ladder` (modenhets-
|
||||
stige), `suppressed-group` (narrative-audit), `codepoint-reveal` (Unicode-
|
||||
steganografi), `top-risks` (rangert top-funn), `recommendation-card[data-
|
||||
severity]` (severity-tinted advisory), `risk-meter` (band-visualisering
|
||||
0-100), `card--severity-{level}` (severity-color findings-cards). Pluss
|
||||
`badge--scope-security`, `verdict-pill-lg` og `form-progress`+`fp-step`
|
||||
fra wave 1.
|
||||
**v7.6.0 Tier 3 reference case:** The playground is now a visually and
|
||||
structurally complete reference for the `shared/playground-design-system/`
|
||||
Tier 3 supplement. 8 new DS components integrated into the 18 report
|
||||
renderers: `tfa-flow` (lethal trifecta chain), `mat-ladder` (maturity
|
||||
ladder), `suppressed-group` (narrative audit), `codepoint-reveal` (Unicode
|
||||
steganography), `top-risks` (ranked top findings), `recommendation-card
|
||||
[data-severity]` (severity-tinted advisory), `risk-meter` (band
|
||||
visualization 0-100), `card--severity-{level}` (severity-color findings
|
||||
cards). Plus `badge--scope-security`, `verdict-pill-lg`, and
|
||||
`form-progress`+`fp-step` from wave 1.
|
||||
|
||||
**Layout:**
|
||||
|
||||
|
|
@ -509,48 +509,50 @@ fra wave 1.
|
|||
playground/
|
||||
├── llm-security-playground.html ← single-file SPA (~10 700 lines)
|
||||
├── vendor/
|
||||
│ └── playground-design-system/ ← synket fra shared/, sjekksum-låst
|
||||
├── test-fixtures/ ← markdown-fixtures (én per kommando)
|
||||
├── screenshots/v7.5.0/ ← Playwright-genererte demobilder (12)
|
||||
├── screenshots/v7.6.0/ ← v7.6.0 demobilder (12, manuelt generert)
|
||||
└── A11Y-RAPPORT.md ← WCAG 2.1 AA verifisering + Tier 3 ARIA
|
||||
│ └── playground-design-system/ ← synced from shared/, checksum-locked
|
||||
├── test-fixtures/ ← markdown fixtures (one per command)
|
||||
├── screenshots/v7.5.0/ ← Playwright-generated demo images (12)
|
||||
├── screenshots/v7.6.0/ ← v7.6.0 demo images (12, hand-generated)
|
||||
└── A11Y-RAPPORT.md ← WCAG 2.1 AA verification + Tier 3 ARIA
|
||||
```
|
||||
|
||||
**Hva playgroundet dekker:**
|
||||
**What the playground covers:**
|
||||
|
||||
- **Onboarding (5 grupper):** organisasjon, scope, profil, plattform,
|
||||
compliance. Verdier persisteres som `shared`-state og prefylles automatisk
|
||||
i alle command-skjemaer.
|
||||
- **Home:** prosjekt-grid, fleet-tracks for posture/scan/red-team. «Last
|
||||
inn demo-data»-knappen aktiverer 3 prosjekter inkludert `dft-komplett-demo`
|
||||
med alle 18 rapporter ferdig parsed.
|
||||
- **Catalog:** alle 20 kommandoer gruppert i 5 kategorier. Søk filtrerer
|
||||
cards, og «Åpne skjema»-knapp bygger ferdig pipeline-streng for klipp-og-
|
||||
lim til terminalen.
|
||||
- **Project surface:** 4 skjermer (Oversikt / Rapporter / Kontekst /
|
||||
Eksport). Rapporter-tabben har category-tabs (discover / posture /
|
||||
findings-ops / hardening / adversarial / mcp-ops) og lim-inn-import for
|
||||
hver rapport-kommando.
|
||||
- **Onboarding (5 groups):** organization, scope, profile, platform,
|
||||
compliance. Values persist as `shared` state and prefill every command
|
||||
form automatically.
|
||||
- **Home:** project grid, fleet tracks for posture/scan/red-team. The
|
||||
"Load demo data" button activates 3 projects, including
|
||||
`dft-komplett-demo` with all 18 reports parsed in advance.
|
||||
- **Catalog:** all 20 commands grouped into 5 categories. Search filters
|
||||
cards, and the "Open form" button builds a ready-to-paste pipeline
|
||||
string for the terminal.
|
||||
- **Project surface:** 4 screens (Overview / Reports / Context / Export).
|
||||
The Reports tab has category tabs (discover / posture / findings-ops /
|
||||
hardening / adversarial / mcp-ops) and paste-import for every report
|
||||
command.
|
||||
|
||||
**Parser/renderer-arkitektur:** Hver `produces_report=true`-kommando i
|
||||
`CATALOG` har en parser (markdown → struktur) og en renderer (struktur
|
||||
→ DS-komponenter). 18 archetypes støttes: `findings`, `findings-grade`,
|
||||
`risk-score-meter`, `posture-cards`, `dashboard-fleet`, `red-team-results`,
|
||||
`diff-report`, `kanban-buckets`, `matrix-risk`. Parser-kontrakten er
|
||||
`{ ok: true, data: {...} } | { ok: false, errors: [...] }`. Test-fixtures
|
||||
under `playground/test-fixtures/` er kontrakt-anker — én markdown-fil per
|
||||
kommando som speiler `templates/unified-report.md`-formatet.
|
||||
**Parser/renderer architecture:** Every `produces_report=true` command in
|
||||
`CATALOG` has a parser (markdown → structure) and a renderer (structure
|
||||
→ DS components). 18 archetypes are supported: `findings`,
|
||||
`findings-grade`, `risk-score-meter`, `posture-cards`, `dashboard-fleet`,
|
||||
`red-team-results`, `diff-report`, `kanban-buckets`, `matrix-risk`. The
|
||||
parser contract is `{ ok: true, data: {...} } | { ok: false, errors:
|
||||
[...] }`. The test fixtures under `playground/test-fixtures/` are the
|
||||
contract anchor — one markdown file per command, mirroring the
|
||||
`templates/unified-report.md` format.
|
||||
|
||||
**Eksponerte testing/automasjons-globaler:** `__store`, `__navigate`,
|
||||
**Exposed testing/automation globals:** `__store`, `__navigate`,
|
||||
`__loadDemoState`, `__scheduleRender`, `__PARSERS`, `__RENDERERS`,
|
||||
`__CATALOG`, `__inferVerdict`, `__inferKeyStats`, `__renderPageShell`,
|
||||
`__handlePasteImport`. Aktiverer Playwright-styrt navigasjon og
|
||||
programmatisk parser/renderer-test mot fixture-katalogen.
|
||||
`__handlePasteImport`. They enable Playwright-driven navigation and
|
||||
programmatic parser/renderer tests against the fixture catalog.
|
||||
|
||||
**Begrensninger:** SPA er en lim-inn-overflate — den kjører ingen scannere
|
||||
selv. Output må komme fra Claude Code (`/security scan ...`), CLI
|
||||
(`node scanners/...`) eller stub-fixtures. Demo-state inneholder kun de
|
||||
3 inline-prosjektene; nye prosjekter er per-bruker og lagres lokalt.
|
||||
**Limitations:** The SPA is a paste-in surface — it does not run any
|
||||
scanners itself. Output must come from Claude Code (`/security scan
|
||||
...`), the CLI (`node scanners/...`), or stub fixtures. Demo state only
|
||||
contains the 3 inline projects; new projects are per-user and stored
|
||||
locally.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -626,11 +628,12 @@ demonstrations — each with `README.md`, fixture, run script, and
|
|||
|
||||
| Version | Date | Highlights |
|
||||
|---------|------|------------|
|
||||
| **7.7.1** | 2026-05-18 | **Playground UX-strip.** Operatør-feedback umiddelbart etter v7.7.0: hjem-overflaten ledet med tre prosjekt-tracks (Re-onboard / Nytt prosjekt / Command-katalog) selv om katalog var det viktige. Minimum-strip levert som tre atomic commits (`b732eee` + `2a6f73f` + `81b7beb`): (1) router tvinger alltid `activeSurface = 'catalog'` (onboarding/home/project-render-funksjonene bevart men ikke rutbare); (2) topbar `Hjem` + `Re-onboard`-knapper fjernet, `Katalog` beholdt; (3) breadcrumb-orgname (`shared.organization.name` fra demo-state) erstattet med statisk `llm-security` som nøytralt scope-anker. Fix: hardkodet `'Plugin v7.6.1'` på linje 6933 i `renderHome` (template-litteral som v7.7.0-grep-en ikke fanget) synket. Onboarding-konseptet dokumentert som v7.8.0-kandidat (per-kommando kontekst-injeksjon) i `ROADMAP.md`. Ingen scanner- eller hook-atferdsendringer. |
|
||||
| **7.7.0** | 2026-05-18 | **HTML-rapport for alle 18 skill-kommandoer.** Hver `/security <cmd>` som produserer rapport printer nå en klikkbar `file://`-lenke til en self-contained HTML-versjon. Levert over 5 sesjoner. (1) Playground katalog list-view + builder-pane med copy-knapp. (2) Playground prosjekt-surface opprydding (stub-screen-håndtering, topbar-splitt). (3) De 18 inline parserne + rendererne i playground-HTML flyttet til canonical ESM-modul `scripts/lib/report-renderers.mjs` (playground beholder bit-identisk inline-kopi siden ESM `import` ikke fungerer fra `file://`). (4) Ny zero-dep CLI `scripts/render-report.mjs` — stdin/file/stdout-modus, kebab→camel commandId-routing, inliner 6 DS-stylesheets + lokal `.report-table`-CSS, ~140 KB self-contained HTML, system-font-fallback, absolutte `file://`-paths for Ghostty cmd-click. (5) Alle 18 skills wired (4 i sesjon 4: scan/audit/posture/deep-scan, 14 i sesjon 5: plugin-audit/mcp-audit/mcp-inspect/ide-scan/supply-check/dashboard/pre-deploy/diff/watch/registry/clean/harden/threat-model/red-team). Output: `reports/<command>-<YYYYMMDD-HHmmss>.html` relativt til CWD. Ingen scanner- eller hook-atferdsendringer — purely additive. |
|
||||
| **7.6.1** | 2026-05-06 | **Playground v7.6.0 visuell-patch.** Seks bugs fanget under maintainer-verifisering i nettleser. Alle skyldtes mismatch mellom DS-klasser og rendrer-bruk (eller manglende DS-implementasjoner playground antok eksisterte). (1) `renderFindingsBlock` brukte `.findings` outer som er DS' 2-kolonners list+detail-grid → erstattet med `<section class="report-meta">` + korrekt `findings__list > findings__group`-mønster. (2) `.report-table` manglet helt i DS men brukes i 7+ rendrere → lokal CSS-implementasjon i playground-HTML. (3) `renderPreDeploy` traffic-lights brukte `.sm-card__grade` (28×28 px for én A-F-bokstav) for "PASS"/"PASS-WITH-NOTES"/"FAIL" → erstattet med bredde-tilpasset status-pill. (4) Threat-model matrix-bobler ikke klikkbare → `<button>` med `data-threat-id` + click-handler som scroller til Trusler-tabellen. (5) Radar-labels overlappet ved 6+ akser → SVG 280→380, R 105→125, dynamisk `text-anchor` (start/end/middle) basert på horisontal-posisjon. (6) `recommendation-card__body` overflow på lange tekster → `overflow-wrap: anywhere`. 4/4 fix-spesifikke smoke-tester + 18/18 renderer-regresjon passerer. Ingen scanner- eller hook-atferdsendringer — purely additive surface. |
|
||||
| **7.6.0** | 2026-05-06 | **Playground Tier 3-referanse-case.** Playground (`playground/llm-security-playground.html`) hevet til visuelt og strukturelt fullført referanse for `shared/playground-design-system/` Tier 3-supplementet. 8 nye DS-komponenter integrert i de 18 rapport-rendererne: `tfa-flow` + `tfa-leg` + `tfa-arrow` (lethal trifecta-kjede med `<button>`-elementer + ARIA), `mat-ladder` + `mat-step` (5-trinns modenhets-stige med terskler 0/25/50/75/95% PASS), `suppressed-group` (narrative-audit fra `summary.narrative_audit.suppressed_findings`), `codepoint-reveal` + `cp-tag`/`cp-zw`/`cp-bidi` (Unicode-steganografi side-ved-side), `top-risks` + `top-risk[data-severity]` (rangert top-funn-listing, semantisk `<ol>`), `recommendation-card[data-severity]` (severity-tinted advisory på `clean`/`harden`/`audit`/`posture`/`pre-deploy`/`plugin-audit`), `risk-meter` (band-visualisering 0-100 på 5 archetypes), `card--severity-{level}` (severity-color modifier på findings-cards). Wave 1: `badge--scope-security` (identitets-chip), `verdict-pill-lg` (DS Tier 3-pill), `form-progress` + `fp-step` (onboarding-wizard). Slettet ~30 duplikat-CSS-deklarasjoner (DS vinner cascade). 5 nye DS-helpers + `mapSeverityToCardLevel` + `parseNarrativeAudit`. Filendring 10209 → 10677 linjer. Levert over 5 sesjoner, atomic commits. A11Y-rapport oppdatert. Ingen scanner- eller hook-behavior-changes — purely additive surface. |
|
||||
| **7.5.0** | 2026-05-05 | **Playground.** Single-file SPA at `playground/llm-security-playground.html` (~10 200 lines) for onboarding, demoer og workshop-bruk uten Claude Code-installasjon. Parsere + renderere for alle 18 `produces_report=true`-kommandoer (Fase 2: 10 høy-prio + Fase 3: 8 gjenstående: mcp-inspect, supply-check, pre-deploy, diff, watch, registry, clean, threat-model). 18 markdown test-fixtures under `playground/test-fixtures/` som kontrakt-anker. Komplett demo-prosjekt `dft-komplett-demo` har alle 18 rapporter ferdig parsed inline. Vendor-synket design-system under `playground/vendor/` (sjekksum-låst). 9 Playwright-genererte screenshots i `playground/screenshots/v7.5.0/`. 11 nye `window`-globaler for testing/automasjon. 2 nye `KEY_STATS_CONFIG`-archetypes (`kanban-buckets`, `matrix-risk`). Bug-fix: `normalizeVerdictText` regex-rekkefølge oppdatert så GO-WITH-CONDITIONS / CONDITIONAL / BETINGET ikke lenger kollapser til ALLOW. Ingen scanner- eller hook-behavior-changes — purely additive surface. |
|
||||
| **7.7.2** | 2026-05-19 | **Language consistency pass.** Norwegian had crept into surface text across v7.5-v7.7. Per the `~/.claude/CLAUDE.md` convention (English for code and documentation, Norwegian for dialog only), this release translates: the HTML Report-step appended by all 18 skill commands, the canonical CLI renderer `scripts/lib/report-renderers.mjs` (display strings + JS comments), the playground UI strings, the `skill-scanner-agent` and `mcp-scanner-agent` system prompts, the Recent versions table and playground architecture prose in this README, the v7.7.x highlights in `CLAUDE.md`, and the llm-security entries in the marketplace root `README.md` + `CLAUDE.md`, plus six table cells in `docs/scanner-reference.md`. Demo-state fixture content for the `dft-komplett-demo` project (intentional Norwegian persona) and regex alternations that match Norwegian-language report markdown (`/^high\|^høy/`, `/resolution\|løsning/`) were preserved. No scanner, hook, or behavior changes — purely surface text. |
|
||||
| **7.7.1** | 2026-05-18 | **Playground UX strip.** Operator feedback immediately after v7.7.0: the home surface led with three project tracks (Re-onboard / New project / Command catalog) even though the catalog was the important entry point. Minimum strip delivered as three atomic commits (`b732eee` + `2a6f73f` + `81b7beb`): (1) the router always forces `activeSurface = 'catalog'` (the onboarding/home/project render functions are preserved in source but no longer routable); (2) the topbar `Home` and `Re-onboard` buttons removed, `Catalog` retained; (3) the breadcrumb org-name (`shared.organization.name` from demo state) replaced with a static `llm-security` neutral scope anchor. Fix: the hardcoded `'Plugin v7.6.1'` on line 6933 of `renderHome` (template literal not caught by the v7.7.0 grep) was synced. The onboarding concept is documented as a v7.8.0 candidate (per-command context injection) in `ROADMAP.md`. No scanner or hook behavior changes. |
|
||||
| **7.7.0** | 2026-05-18 | **HTML report for all 18 skill commands.** Every `/security <cmd>` that produces a report now prints a clickable `file://` link to a self-contained HTML version. Delivered across 5 sessions. (1) Playground catalog list-view + builder-pane with a copy button. (2) Playground project-surface cleanup (stub-screen handling, topbar split). (3) The 18 inline parsers + renderers in the playground HTML were moved to a canonical ESM module `scripts/lib/report-renderers.mjs` (the playground keeps a bit-identical inline copy since ESM `import` does not work from `file://`). (4) New zero-dep CLI `scripts/render-report.mjs` — stdin/file/stdout mode, kebab→camel commandId routing, inlines 6 DS stylesheets + a local `.report-table` CSS, ~140 KB self-contained HTML, system-font fallback, absolute `file://` paths for Ghostty cmd-click. (5) All 18 skills wired (4 in session 4: scan/audit/posture/deep-scan; 14 in session 5: plugin-audit/mcp-audit/mcp-inspect/ide-scan/supply-check/dashboard/pre-deploy/diff/watch/registry/clean/harden/threat-model/red-team). Output: `reports/<command>-<YYYYMMDD-HHmmss>.html` relative to CWD. No scanner or hook behavior changes — purely additive. |
|
||||
| **7.6.1** | 2026-05-06 | **Playground v7.6.0 visual patch.** Six bugs caught during maintainer verification in the browser. All were mismatches between DS classes and renderer usage (or missing DS implementations the playground assumed existed). (1) `renderFindingsBlock` used the `.findings` outer class, which is the DS 2-column list+detail grid → replaced with `<section class="report-meta">` + the correct `findings__list > findings__group` pattern. (2) `.report-table` was missing entirely from the DS but used in 7+ renderers → local CSS implementation in the playground HTML. (3) `renderPreDeploy` traffic-lights used `.sm-card__grade` (28×28 px for one A-F letter) for "PASS"/"PASS-WITH-NOTES"/"FAIL" → replaced with a width-adapting status pill. (4) Threat-model matrix bubbles were not clickable → `<button>` with `data-threat-id` + click handler that scrolls to the Threats table. (5) Radar labels overlapped at 6+ axes → SVG 280→380, R 105→125, dynamic `text-anchor` (start/end/middle) based on horizontal position. (6) `recommendation-card__body` overflow on long text → `overflow-wrap: anywhere`. 4/4 fix-specific smoke tests + 18/18 renderer regression passing. No scanner or hook behavior changes — purely additive surface. |
|
||||
| **7.6.0** | 2026-05-06 | **Playground Tier 3 reference case.** The playground (`playground/llm-security-playground.html`) raised to a visually and structurally complete reference for the `shared/playground-design-system/` Tier 3 supplement. 8 new DS components integrated into the 18 report renderers: `tfa-flow` + `tfa-leg` + `tfa-arrow` (lethal trifecta chain with `<button>` elements + ARIA), `mat-ladder` + `mat-step` (5-step maturity ladder with thresholds 0/25/50/75/95% PASS), `suppressed-group` (narrative audit from `summary.narrative_audit.suppressed_findings`), `codepoint-reveal` + `cp-tag`/`cp-zw`/`cp-bidi` (Unicode steganography side-by-side), `top-risks` + `top-risk[data-severity]` (ranked top-findings listing, semantic `<ol>`), `recommendation-card[data-severity]` (severity-tinted advisory on `clean`/`harden`/`audit`/`posture`/`pre-deploy`/`plugin-audit`), `risk-meter` (0-100 band visualization across 5 archetypes), `card--severity-{level}` (severity-color modifier on findings cards). Wave 1: `badge--scope-security` (identity chip), `verdict-pill-lg` (DS Tier 3 pill), `form-progress` + `fp-step` (onboarding wizard). Removed ~30 duplicate CSS declarations (DS wins the cascade). 5 new DS helpers + `mapSeverityToCardLevel` + `parseNarrativeAudit`. File size 10209 → 10677 lines. Delivered across 5 sessions, atomic commits. A11Y report updated. No scanner or hook behavior changes — purely additive surface. |
|
||||
| **7.5.0** | 2026-05-05 | **Playground.** Single-file SPA at `playground/llm-security-playground.html` (~10 200 lines) for onboarding, demos and workshop use without a Claude Code installation. Parsers + renderers for all 18 `produces_report=true` commands (Phase 2: 10 high-priority + Phase 3: 8 remaining: mcp-inspect, supply-check, pre-deploy, diff, watch, registry, clean, threat-model). 18 markdown test fixtures under `playground/test-fixtures/` as contract anchors. The complete demo project `dft-komplett-demo` has all 18 reports parsed inline. Vendor-synced design-system under `playground/vendor/` (checksum-locked). 9 Playwright-generated screenshots under `playground/screenshots/v7.5.0/`. 11 new `window` globals for testing/automation. 2 new `KEY_STATS_CONFIG` archetypes (`kanban-buckets`, `matrix-risk`). Bug-fix: `normalizeVerdictText` regex order updated so GO-WITH-CONDITIONS / CONDITIONAL / BETINGET no longer collapse to ALLOW. No scanner or hook behavior changes — purely additive surface. |
|
||||
| **7.4.0** | 2026-05-05 | **Examples + e2e suite.** Seven runnable demonstration walkthroughs under `examples/` (`prompt-injection-showcase`, `lethal-trifecta-walkthrough`, `mcp-rug-pull`, `supply-chain-attack`, `poisoned-claude-md`, `bash-evasion-gallery`, `toxic-agent-demo`, `pre-compact-poisoning`) — each with `README.md`, runtime-isolated fixture, single-command run-script, and `expected-findings.md` testable contract. Three new `tests/e2e/` suites (attack-chain 17 tests + multi-session 9 tests + scan-pipeline 19 tests = +45 tests, total 1822) prove the framework works as a coordinated system, not just isolated units. No scanner or hook behavior changes — purely additive surface. Scanner `VERSION` constants synced across `dashboard-aggregator.mjs`, `posture-scanner.mjs`, `ide-extension-scanner.mjs`. |
|
||||
| **7.3.1** | 2026-05-01 | **Stabilization patch.** Project repositioned as solo, stabilization-only, with explicit "fork & own" stance for enterprise features. New public docs: `CONTRIBUTING.md` (fork-and-own model), README "Project scope" section (out-of-scope table with commercial alternatives), updated `SECURITY.md` (v7.3.x supported, v7.0–v7.2 best-effort, < v7.0 EOL). Coherence: `package.json` files whitelist + `bugs` URL + repo URL fix; scanner `VERSION` constants synced across `dashboard-aggregator.mjs`, `posture-scanner.mjs`, `ide-extension-scanner.mjs`. Test ceiling raised on flaky pre-compact-scan timing test (500 ms → 1000 ms; design target unchanged). No behavior changes. |
|
||||
| **7.3.0** | 2026-05-01 | **Batch C release.** Wave A (T7-T9 bash normalization + rot13 comment-block decoder), Wave B (`.gitattributes` post-clone advisory + npm scope-hop typosquat + GitHub/Forgejo workflow-scanner with 23-field blacklist + re-interpolation tracking + auth-bypass detection), Wave C (MCP cumulative-drift baseline + `/security mcp-baseline-reset`), Wave D (riskScoreV1 `@deprecated`; sandbox-architecture rationale docs; env-var deprecation runway to v8.0.0; CLAUDE.md hooks count + consistency test). 1665+ → 1777 tests. Wave E (additional attack-simulator scenarios) deferred indefinitely |
|
||||
|
|
|
|||
|
|
@ -25,19 +25,21 @@ Your output is a structured security report per MCP server, including trust rati
|
|||
findings mapped to OWASP categories, and prioritized recommendations. You operate read-only —
|
||||
never modify files or install packages.
|
||||
|
||||
## Step 0: Generaliseringsgrense
|
||||
## Step 0: Generalization boundary
|
||||
|
||||
Opus 4.7 tolker instruks mer literalt enn tidligere modeller. Ikke ekstrapolér fra en
|
||||
enkelt observasjon til et bredere mønster uten eksplisitt evidens. Rapporter det du
|
||||
faktisk ser; merk spekulasjon som spekulasjon. Ved tvil: inkludér filsti og linjenummer
|
||||
som evidens, ikke en generalisering.
|
||||
Opus 4.7 interprets instructions more literally than earlier models. Do not
|
||||
extrapolate from a single observation to a broader pattern without explicit
|
||||
evidence. Report what you actually see; mark speculation as speculation. When
|
||||
in doubt, cite the filepath and line number as evidence rather than a
|
||||
generalization.
|
||||
|
||||
## Parallell Read-strategi
|
||||
## Parallel Read strategy
|
||||
|
||||
Når du trenger å lese tre eller flere filer som ikke avhenger av hverandre, send alle
|
||||
Read-kallene i samme melding (parallell), ikke sekvensielt. Dette gjelder spesielt:
|
||||
knowledge-files i oppstart, og batcher av MCP-server-filer. Sekvensiell Read er
|
||||
akseptabelt når én fils innhold avgjør hvilken neste skal leses.
|
||||
When you need to read three or more files that do not depend on each other,
|
||||
send all the Read calls in the same message (parallel), not sequentially. This
|
||||
applies especially to knowledge files during startup and to batches of
|
||||
MCP-server files. Sequential Read is acceptable when one file's contents
|
||||
determine which file to read next.
|
||||
|
||||
Reference knowledge base files before scanning:
|
||||
- `knowledge/mcp-threat-patterns.md` — 9 threat categories with detection signals (MCP01-MCP10 mapping)
|
||||
|
|
|
|||
|
|
@ -24,19 +24,21 @@ You are invoked by `/security scan` with a target path. Your `tools:` frontmatte
|
|||
simply does not grant file-modifying tools. Your output is a written security report
|
||||
— findings, severities, OWASP references, evidence excerpts, and remediation guidance.
|
||||
|
||||
## Step 0: Generaliseringsgrense
|
||||
## Step 0: Generalization boundary
|
||||
|
||||
Opus 4.7 tolker instruks mer literalt enn tidligere modeller. Ikke ekstrapolér fra
|
||||
en enkelt observasjon til et bredere mønster uten eksplisitt evidens. Rapporter det
|
||||
du faktisk ser; merk spekulasjon som spekulasjon. Ved tvil: inkludér filsti og
|
||||
linjenummer som evidens, ikke en generalisering.
|
||||
Opus 4.7 interprets instructions more literally than earlier models. Do not
|
||||
extrapolate from a single observation to a broader pattern without explicit
|
||||
evidence. Report what you actually see; mark speculation as speculation. When
|
||||
in doubt, cite the filepath and line number as evidence rather than a
|
||||
generalization.
|
||||
|
||||
## Parallell Read-strategi
|
||||
## Parallel Read strategy
|
||||
|
||||
Når du trenger å lese tre eller flere filer som ikke avhenger av hverandre, send
|
||||
alle Read-kallene i samme melding (parallell), ikke sekvensielt. Dette gjelder
|
||||
spesielt: knowledge-files i oppstart, og batcher av skannede filer. Sekvensiell
|
||||
Read er akseptabelt når én fils innhold avgjør hvilken neste skal leses.
|
||||
When you need to read three or more files that do not depend on each other,
|
||||
send all the Read calls in the same message (parallel), not sequentially. This
|
||||
applies especially to knowledge files during startup and to batches of scanned
|
||||
files. Sequential Read is acceptable when one file's contents determine which
|
||||
file to read next.
|
||||
|
||||
You have access to five knowledge base files that ground all your analysis:
|
||||
- `knowledge/skill-threat-patterns.md` — 7 threat categories with documented attack variants
|
||||
|
|
|
|||
|
|
@ -65,6 +65,6 @@ After producing the markdown audit report above:
|
|||
The CLI writes `reports/audit-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **HTML report:** [Open in browser](file:///abs/path.html)
|
||||
|
||||
If the CLI exits non-zero, mention the error but do not block — the markdown audit above is the primary deliverable.
|
||||
|
|
|
|||
|
|
@ -76,6 +76,6 @@ After producing the markdown clean report above:
|
|||
The CLI writes `reports/clean-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -76,6 +76,6 @@ After producing the markdown dashboard above:
|
|||
The CLI writes `reports/dashboard-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **HTML report:** [Open in browser](file:///abs/path.html)
|
||||
|
||||
If the CLI exits non-zero, mention the error but do not block — the markdown dashboard above is the primary deliverable.
|
||||
|
|
|
|||
|
|
@ -57,6 +57,6 @@ After producing the markdown deep-scan report (banner + synthesizer output or fa
|
|||
The CLI writes `reports/deep-scan-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -113,6 +113,6 @@ After producing the markdown diff report above:
|
|||
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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -87,6 +87,6 @@ After producing the markdown harden report above:
|
|||
The CLI writes `reports/harden-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -121,6 +121,6 @@ After producing the markdown IDE-scan report above:
|
|||
The CLI writes `reports/ide-scan-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -62,6 +62,6 @@ After producing the markdown MCP audit report (Step 3 + optional Step 4 Live Ins
|
|||
The CLI writes `reports/mcp-audit-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -69,6 +69,6 @@ After producing the markdown live-inspection report above:
|
|||
The CLI writes `reports/mcp-inspect-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -89,6 +89,6 @@ After producing the markdown plugin-audit report (Step 5) and any cleanup (Step
|
|||
The CLI writes `reports/plugin-audit-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -75,6 +75,6 @@ After producing the markdown scorecard above:
|
|||
The CLI writes `reports/posture-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **HTML report:** [Open in browser](file:///abs/path.html)
|
||||
|
||||
If the CLI exits non-zero, mention the error but do not block — the markdown scorecard above is the primary deliverable.
|
||||
|
|
|
|||
|
|
@ -116,6 +116,6 @@ After producing the markdown pre-deploy checklist + verdict above:
|
|||
The CLI writes `reports/pre-deploy-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **HTML report:** [Open in browser](file:///abs/path.html)
|
||||
|
||||
If the CLI exits non-zero, mention the error but do not block — the markdown checklist above is the primary deliverable.
|
||||
|
|
|
|||
|
|
@ -110,6 +110,6 @@ After producing the markdown red-team narrative report above:
|
|||
The CLI writes `reports/red-team-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -136,6 +136,6 @@ After producing the markdown registry output above (stats / scan-result / search
|
|||
The CLI writes `reports/registry-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **HTML report:** [Open in browser](file:///abs/path.html)
|
||||
|
||||
If the CLI exits non-zero, mention the error but do not block — the markdown output above is the primary deliverable.
|
||||
|
|
|
|||
|
|
@ -172,6 +172,6 @@ After producing the markdown report (Step 5) and any cleanup (Step 7):
|
|||
The CLI writes `reports/scan-<YYYYMMDD-HHmmss>.html` relative to CWD and prints `file:///abs/path.html` on stdout (one line).
|
||||
4. Append this to your response (markdown link, no bare URL):
|
||||
|
||||
> **HTML-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -62,6 +62,6 @@ After producing the markdown supply-check report above:
|
|||
The CLI writes `reports/supply-check-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **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.
|
||||
|
|
|
|||
|
|
@ -42,6 +42,6 @@ After the threat-modeler agent has produced the complete threat-model markdown d
|
|||
The CLI writes `reports/threat-model-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **HTML report:** [Open in browser](file:///abs/path.html)
|
||||
|
||||
If the CLI exits non-zero, mention the error but do not block — the markdown threat-model document above is the primary deliverable.
|
||||
|
|
|
|||
|
|
@ -73,6 +73,6 @@ After producing the markdown watch banner above (before starting the loop):
|
|||
The CLI writes `reports/watch-<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-rapport:** [Åpne i nettleser](file:///abs/path.html)
|
||||
> **HTML report:** [Open in browser](file:///abs/path.html)
|
||||
|
||||
If the CLI exits non-zero, mention the error but do not block — the markdown banner above is the primary deliverable.
|
||||
|
|
|
|||
|
|
@ -105,18 +105,18 @@ Scan reports are stored in `reports/` as `.docx` (for sharing) with `.md` source
|
|||
|
||||
## Examples (runnable demonstrations)
|
||||
|
||||
Self-contained, deterministic threat-fixture mappes under `examples/`. Each mappe har `README.md`, fixture/script/transcript, `run-*.{sh,mjs}`, og `expected-findings.md`. Demonstrasjoner — ikke unit-tester.
|
||||
Self-contained, deterministic threat fixtures live under `examples/`. Each directory has a `README.md`, fixture/script/transcript, `run-*.{sh,mjs}`, and `expected-findings.md`. They are demonstrations — not unit tests.
|
||||
|
||||
| Mappe | Demonstrerer | Hooks/scanners | Sentinel |
|
||||
| Directory | Demonstrates | Hooks/scanners | Sentinel |
|
||||
|-------|--------------|----------------|----------|
|
||||
| `malicious-skill-demo/` | Skill scanner end-to-end (UNI/ENT/PRM/DEP/TNT/NET + 7 LLM-kategorier) | `scan-orchestrator` + agents | BLOCK 100/100 |
|
||||
| `prompt-injection-showcase/` | 61 payloads × 19 kategorier mot `pre-prompt-inject-scan`, `post-mcp-verify`, `pre-bash-destructive` | runtime hooks | per-kategori expected outcome |
|
||||
| `lethal-trifecta-walkthrough/` | Rule-of-Two advisory på leg 3 (WebFetch → Read .env → Bash curl POST) + suppression | `post-session-guard` | advisory på stage 3 |
|
||||
| `mcp-rug-pull/` | Cumulative drift-advisory (E14, v7.3.0) — 7 stadier under per-update-terskel, kumulativt over 25% baseline | `post-mcp-verify` + `mcp-description-cache.mjs` | advisory på stage 7 |
|
||||
| `supply-chain-attack/` | PreToolUse-blokk på kompromittert pakke + scope-hop advisory + dep-auditor typosquats + postinstall curl-pipe | `pre-install-supply-chain` + `dep-auditor` + `supply-chain-data` | 6+ funn, 2 advisories, 1 BLOCK |
|
||||
| `poisoned-claude-md/` | 6 detektorer (injection / shell / URL / credential paths / permission expansion / encoded payloads) inkl. E15 agent-fil-overflate | `memory-poisoning-scanner` | ≥18 funn fordelt på 2 filer |
|
||||
| `bash-evasion-gallery/` | T1-T9 disguised destructive commands → normalisert + blokkert (defense-in-depth over Claude Code 2.1.98+) | `pre-bash-destructive` + `bash-normalize` | 10 BLOCK eksitkoder |
|
||||
| `toxic-agent-demo/` | Single-component lethal trifecta — agent med [Bash, Read, WebFetch] uten hook-guards = CRITICAL TFA-finding | `toxic-flow-analyzer` (TFA) | 1 CRITICAL `Lethal trifecta:` |
|
||||
| `pre-compact-poisoning/` | PreCompact-hook fanger injection + AWS-shaped credential i syntetisk transcript på tvers av off/warn/block-modus | `pre-compact-scan` | 9 pass: block exit 2 + reason; warn systemMessage; off skip; benign passes |
|
||||
| `malicious-skill-demo/` | Skill scanner end-to-end (UNI/ENT/PRM/DEP/TNT/NET + 7 LLM categories) | `scan-orchestrator` + agents | BLOCK 100/100 |
|
||||
| `prompt-injection-showcase/` | 61 payloads × 19 categories against `pre-prompt-inject-scan`, `post-mcp-verify`, `pre-bash-destructive` | runtime hooks | per-category expected outcome |
|
||||
| `lethal-trifecta-walkthrough/` | Rule-of-Two advisory on leg 3 (WebFetch → Read .env → Bash curl POST) + suppression | `post-session-guard` | advisory at stage 3 |
|
||||
| `mcp-rug-pull/` | Cumulative drift advisory (E14, v7.3.0) — 7 stages below the per-update threshold, cumulatively over a 25% baseline shift | `post-mcp-verify` + `mcp-description-cache.mjs` | advisory at stage 7 |
|
||||
| `supply-chain-attack/` | PreToolUse block on a compromised package + scope-hop advisory + dep-auditor typosquats + postinstall curl-pipe | `pre-install-supply-chain` + `dep-auditor` + `supply-chain-data` | 6+ findings, 2 advisories, 1 BLOCK |
|
||||
| `poisoned-claude-md/` | 6 detectors (injection / shell / URL / credential paths / permission expansion / encoded payloads) including the E15 agent-file surface | `memory-poisoning-scanner` | ≥18 findings split across 2 files |
|
||||
| `bash-evasion-gallery/` | T1-T9 disguised destructive commands → normalized + blocked (defense-in-depth over Claude Code 2.1.98+) | `pre-bash-destructive` + `bash-normalize` | 10 BLOCK exit codes |
|
||||
| `toxic-agent-demo/` | Single-component lethal trifecta — an agent with [Bash, Read, WebFetch] and no hook guards = CRITICAL TFA finding | `toxic-flow-analyzer` (TFA) | 1 CRITICAL `Lethal trifecta:` |
|
||||
| `pre-compact-poisoning/` | The PreCompact hook catches injection + an AWS-shaped credential in a synthetic transcript across off/warn/block modes | `pre-compact-scan` | 9 cases: block exit 2 + reason; warn systemMessage; off skip; benign passes |
|
||||
|
||||
State-isolering: alle eksempler som muterer global state bruker run-script PID (post-session-guard via `${ppid}.jsonl`) eller env-overrides (`LLM_SECURITY_MCP_CACHE_FILE` for MCP-cache). Brukerens reelle `/tmp/llm-security-session-*.jsonl` og `~/.cache/llm-security/` røres aldri.
|
||||
State isolation: every example that mutates global state uses the run-script PID (post-session-guard via `${ppid}.jsonl`) or env overrides (`LLM_SECURITY_MCP_CACHE_FILE` for the MCP cache). The user's real `/tmp/llm-security-session-*.jsonl` and `~/.cache/llm-security/` are never touched.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,25 @@
|
|||
|
||||
Per-release notes for v7.0.0 onward. Imported from `CLAUDE.md` via `@docs/version-history.md`.
|
||||
|
||||
## v7.7.2 — Language consistency pass
|
||||
|
||||
Norwegian had crept into surface text across v7.5–v7.7. Per the
|
||||
`~/.claude/CLAUDE.md` convention (English for code and documentation,
|
||||
Norwegian for dialog only), this release translates: the HTML Report-step in
|
||||
all 18 skill commands, the canonical CLI renderer
|
||||
`scripts/lib/report-renderers.mjs` (display strings + JS comments), the
|
||||
playground UI strings, the `skill-scanner-agent` and `mcp-scanner-agent`
|
||||
system prompts, the playground architecture prose + Recent versions table in
|
||||
the plugin `README.md`, the v7.7.x highlights in the plugin `CLAUDE.md`, the
|
||||
llm-security entries in the marketplace root `README.md` + `CLAUDE.md`, and
|
||||
six table cells in `docs/scanner-reference.md`. Demo-state fixture content
|
||||
for the `dft-komplett-demo` project (intentional Norwegian persona) and
|
||||
regex alternations that match Norwegian-language report markdown
|
||||
(`/^high|^høy/`, `/resolution|løsning/`) were preserved. CHANGELOG and this
|
||||
version-history file were deferred per operator decision — they remain in
|
||||
the language they were written in. No scanner, hook, or behavior changes —
|
||||
purely surface text.
|
||||
|
||||
## v7.0.0 — Severity-dominated risk scoring (v2 model, BREAKING)
|
||||
|
||||
Three changes target the false-positive cascade on real codebases (hyperframes.com gave `BLOCK / Extreme / 100`, ~70% noise):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "llm-security",
|
||||
"version": "7.7.1",
|
||||
"version": "7.7.2",
|
||||
"description": "Security scanning, auditing, and threat modeling for Claude Code projects",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -79,7 +79,7 @@ function renderKeyStatsGrid(stats) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Render page-shell — DS Tier 3 page__header-klyngen brukt på alle 4 overflater:
|
||||
* Render the page-shell — the DS Tier 3 page__header cluster used on all 4 surfaces:
|
||||
* - onboarding: page__eyebrow="ONBOARDING · n av 5 grupper komplette"
|
||||
* - home: page__eyebrow="HJEM" (m/ hero-modifier for editorial type-hierarki)
|
||||
* - catalog: page__eyebrow="KATALOG"
|
||||
|
|
@ -197,16 +197,16 @@ const KEY_STATS_CONFIG = {
|
|||
const crit = fs.filter(function (f) { return /crit|kritisk/i.test(f.severity || ''); }).length;
|
||||
const high = fs.filter(function (f) { return /^high|^høy/i.test(f.severity || ''); }).length;
|
||||
return [
|
||||
{ label: 'TOTALT', value: fs.length },
|
||||
{ label: 'KRITISK', value: crit, modifier: crit > 0 ? 'critical' : null },
|
||||
{ label: 'HØY', value: high, modifier: high > 0 ? 'high' : null }
|
||||
{ label: 'TOTAL', value: fs.length },
|
||||
{ label: 'CRITICAL', value: crit, modifier: crit > 0 ? 'critical' : null },
|
||||
{ label: 'HIGH', value: high, modifier: high > 0 ? 'high' : null }
|
||||
];
|
||||
},
|
||||
'findings-grade': function (d) {
|
||||
const out = [];
|
||||
if (d.grade) out.push({ label: 'GRADE', value: String(d.grade).toUpperCase(), modifier: /a|b/i.test(d.grade) ? 'low' : (/c|d/i.test(d.grade) ? 'medium' : 'critical') });
|
||||
if (d.score != null) out.push({ label: 'SCORE', value: d.score });
|
||||
if (d.findings) out.push({ label: 'FUNN', value: d.findings.length });
|
||||
if (d.findings) out.push({ label: 'FINDINGS', value: d.findings.length });
|
||||
return out;
|
||||
},
|
||||
'risk-score-meter': function (d) {
|
||||
|
|
@ -220,16 +220,16 @@ const KEY_STATS_CONFIG = {
|
|||
},
|
||||
'red-team-results': function (d) {
|
||||
return [
|
||||
{ label: 'TOTALT', value: d.total || 0 },
|
||||
{ label: 'TOTAL', value: d.total || 0 },
|
||||
{ label: 'PASS', value: d.pass_count || 0, modifier: 'low' },
|
||||
{ label: 'FAIL', value: d.fail_count || 0, modifier: (d.fail_count > 0 ? 'critical' : null) }
|
||||
];
|
||||
},
|
||||
'dashboard-fleet': function (d) {
|
||||
return [
|
||||
{ label: 'PROSJEKTER', value: (d.projects || []).length },
|
||||
{ label: 'MASKINKLASSE', value: String(d.machine_grade || 'n/a').toUpperCase() },
|
||||
{ label: 'SVAKEST', value: d.weakest_link || '–' }
|
||||
{ label: 'PROJECTS', value: (d.projects || []).length },
|
||||
{ label: 'MACHINE GRADE', value: String(d.machine_grade || 'n/a').toUpperCase() },
|
||||
{ label: 'WEAKEST', value: d.weakest_link || '–' }
|
||||
];
|
||||
},
|
||||
'posture-cards': function (d) {
|
||||
|
|
@ -246,8 +246,8 @@ const KEY_STATS_CONFIG = {
|
|||
const newCount = (d['new'] || []).length;
|
||||
const unchangedCount = (d.unchanged || []).length;
|
||||
return [
|
||||
{ label: 'NÅ-GRADE', value: String(d.current_grade || '?').toUpperCase() },
|
||||
{ label: 'AKSJONER', value: newCount, modifier: newCount > 0 ? 'medium' : 'low' },
|
||||
{ label: 'CURRENT GRADE', value: String(d.current_grade || '?').toUpperCase() },
|
||||
{ label: 'ACTIONS', value: newCount, modifier: newCount > 0 ? 'medium' : 'low' },
|
||||
{ label: 'SKIPPED', value: unchangedCount }
|
||||
];
|
||||
},
|
||||
|
|
@ -435,7 +435,7 @@ function gradeFromText(s) {
|
|||
return m ? m[1] : null;
|
||||
}
|
||||
|
||||
// Hjelper: parse Risk Dashboard-tabellen (fellesmønster)
|
||||
// Helper: parse the Risk Dashboard table (shared pattern)
|
||||
function parseRiskDashboard(md) {
|
||||
const out = {};
|
||||
const score = extractField(md, 'Risk Score');
|
||||
|
|
@ -486,7 +486,7 @@ function parseFindingsTables(md) {
|
|||
});
|
||||
if (!findingsSection) return findings;
|
||||
const body = findingsSection.body;
|
||||
// Splitt på ### -headere
|
||||
// Split on ### headers
|
||||
const subRe = /^###\s+(.+)$/gm;
|
||||
const matches = [];
|
||||
let m;
|
||||
|
|
@ -578,7 +578,7 @@ function parseNarrativeAudit(md) {
|
|||
}
|
||||
|
||||
// ============================================================
|
||||
// 10 PARSERS — én per høy-prio kommando.
|
||||
// 10 PARSERS — one per high-priority command.
|
||||
// Returner { ok: true, data: { ...domain-specific } } eller
|
||||
// { ok: false, errors: [{ section, reason }] }
|
||||
// ============================================================
|
||||
|
|
@ -1047,7 +1047,7 @@ const parseDashboard = safeOk(function (md) {
|
|||
});
|
||||
}
|
||||
}
|
||||
// Weakest link = første prosjekt sortert worst-first (allerede sortert i fixture)
|
||||
// Weakest link = first project, sorted worst-first (already sorted in the fixture)
|
||||
const weakest = projects.length ? projects[0].name : '';
|
||||
return { ok: true, data: Object.assign({}, dash, {
|
||||
machine_grade: machine_grade,
|
||||
|
|
@ -1195,8 +1195,8 @@ const parseRedTeam = safeOk(function (md) {
|
|||
});
|
||||
|
||||
// ============================================================
|
||||
// FASE 3: 8 PARSERS — én per gjenstående produces_report-kommando.
|
||||
// Mønstre gjenbrukes fra Fase 2 (parseRiskDashboard + parseFindingsTables
|
||||
// PHASE 3: 8 PARSERS — one per remaining produces_report command.
|
||||
// Patterns are reused from Phase 2 (parseRiskDashboard + parseFindingsTables
|
||||
// + safeOk). Matrix-risk-parsing er kopiert fra ms-ai-architect.
|
||||
// ============================================================
|
||||
const parseMcpInspect = safeOk(function (md) {
|
||||
|
|
@ -1614,7 +1614,7 @@ function renderEmptyState(message) {
|
|||
return '<div class="guide-panel guide-panel--info">' +
|
||||
'<div class="guide-panel__icon" aria-hidden="true">i</div>' +
|
||||
'<div class="guide-panel__body">' +
|
||||
'<p class="guide-panel__text">' + escapeHtml(message || 'Ingen data å vise.') + '</p>' +
|
||||
'<p class="guide-panel__text">' + escapeHtml(message || 'No data to display.') + '</p>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}
|
||||
|
|
@ -1627,7 +1627,7 @@ function renderFindingsBlock(findings, label) {
|
|||
});
|
||||
const items = sorted.map(function (f) {
|
||||
const sev = String(f.severity || 'info').toLowerCase();
|
||||
// DS Tier 3 (v7.6.0 fase 5h): card--severity-{level} modifier på outer
|
||||
// DS Tier 3 (v7.6.0 phase 5h): card--severity-{level} modifier on the outer
|
||||
// .findings__item gir severity-tinted left-border. Beholdes ved siden av
|
||||
// den eksisterende .findings__item-severity-dot for ARIA + visuell
|
||||
// redundans (border-farge + dot-fyll signaliserer samme severity).
|
||||
|
|
@ -1649,8 +1649,8 @@ function renderFindingsBlock(findings, label) {
|
|||
);
|
||||
}).join('');
|
||||
// DS .findings outer-class er et 2-kolonners grid (360px list + 1fr detail-panel) —
|
||||
// playgroundet bruker bare list-delen, så vi wrapper i .findings__list (uten outer
|
||||
// .findings) for å unngå at headeren ender i venstre 360px-kolonne. v7.6.1 fix.
|
||||
// the playground uses only the list part, so we wrap in .findings__list (no outer
|
||||
// .findings) to avoid the header landing in the left 360px column. v7.6.1 fix.
|
||||
return (
|
||||
'<section class="report-meta">' +
|
||||
'<h4>' + escapeHtml(label || 'Funn') + '</h4>' +
|
||||
|
|
@ -1684,7 +1684,7 @@ function renderRecommendationsList(recs, label, severity) {
|
|||
|
||||
/**
|
||||
* Map severity-string til DS-tier3 recommendation-card data-severity.
|
||||
* Aksepterer både severity-konvensjoner (critical/high/medium/low/info)
|
||||
* Accepts both severity conventions (critical/high/medium/low/info)
|
||||
* og action-types (CREATE/APPEND/MERGE/SKIP/NONE).
|
||||
*/
|
||||
function mapSeverityToCardLevel(input) {
|
||||
|
|
@ -1753,9 +1753,9 @@ function renderSmallMultiples(items) {
|
|||
function renderRadarSvg(axes) {
|
||||
// axes: [{ name, score (0-5) }]
|
||||
if (!axes || axes.length < 3) return '';
|
||||
// v7.6.1 fix: øk SVG-bredden fra 280 til 380 og r fra 105 til 125 for å gi
|
||||
// labels mer plass. Bruk text-anchor basert på horisontal-posisjon for å
|
||||
// unngå at bottom-labels overlapper hverandre ved 6+ akser.
|
||||
// v7.6.1 fix: widen the SVG from 280 to 380 and r from 105 to 125 to give
|
||||
// labels more room. Use text-anchor based on horizontal position to keep
|
||||
// bottom labels from overlapping each other at 6+ axes.
|
||||
const size = 380, cx = size / 2, cy = size / 2, r = 125;
|
||||
const n = axes.length;
|
||||
const axisRows = axes.map(function (a) {
|
||||
|
|
@ -1766,7 +1766,7 @@ function renderRadarSvg(axes) {
|
|||
const ang = angle(i);
|
||||
const lx = cx + Math.cos(ang) * (r + 28);
|
||||
const ly = cy + Math.sin(ang) * (r + 28);
|
||||
// Velg text-anchor basert på posisjon: ankerene til venstre/høyre snur.
|
||||
// Pick text-anchor based on position: left/right anchors flip.
|
||||
const dx = Math.cos(ang);
|
||||
const anchor = Math.abs(dx) < 0.2 ? 'middle' : (dx > 0 ? 'start' : 'end');
|
||||
return '<text class="radar__label" x="' + lx.toFixed(1) + '" y="' + ly.toFixed(1) + '" text-anchor="' + anchor + '" dominant-baseline="middle">' + escapeHtml(a.name) + '</text>';
|
||||
|
|
@ -1804,7 +1804,7 @@ function renderRadarSvg(axes) {
|
|||
|
||||
/**
|
||||
* Render tfa-flow + tfa-leg + tfa-arrow for et lethal trifecta-funn.
|
||||
* Brukes på scan + deep-scan-rapporter når findings inneholder
|
||||
* Used on scan + deep-scan reports when findings contain
|
||||
* en trifecta-pattern (f.eks. SCN-002 "Lethal trifecta: [Bash, Read, WebFetch]").
|
||||
* Synthesiserer 3-leddet kjede: untrusted-input → sensitive-access → exfil-sink.
|
||||
*/
|
||||
|
|
@ -1835,7 +1835,7 @@ function renderToxicFlow(findings) {
|
|||
}
|
||||
const legs = [
|
||||
{ label: 'Untrusted input', name: tools[0], source: fileLine, mit: 'unmitigated', mitText: 'Ingen pre-prompt-inject-scan eller post-mcp-verify guard' },
|
||||
{ label: 'Sensitive access', name: tools[1], source: '.env / credentials / git-history', mit: 'unmitigated', mitText: 'Ingen pre-write-pathguard på sti' },
|
||||
{ label: 'Sensitive access', name: tools[1], source: '.env / credentials / git-history', mit: 'unmitigated', mitText: 'No pre-write-pathguard on path' },
|
||||
{ label: 'Exfil sink', name: tools[2], source: 'curl / fetch til ekstern host', mit: 'unmitigated', mitText: 'Ingen post-session-guard trifecta-deteksjon' }
|
||||
];
|
||||
const legHtml = function (leg) {
|
||||
|
|
@ -1874,13 +1874,13 @@ function renderMatLadder(categories, postureScore, postureApplicable) {
|
|||
? Number(postureApplicable)
|
||||
: categories.filter(function (c) { return c.status !== 'N-A' && c.status !== 'N/A'; }).length;
|
||||
const pct = total > 0 ? Math.round((passCount / total) * 100) : 0;
|
||||
// 5 modenhetstrinn — terskler basert på % PASS
|
||||
// 5 maturity steps — thresholds based on % PASS
|
||||
const steps = [
|
||||
{ num: 1, name: 'Initial', threshold: 0, desc: 'Bare bones — ingen hooks eller minimal posture.' },
|
||||
{ num: 2, name: 'Aware', threshold: 25, desc: 'Posture-skanning aktiv, kjenner risikoene.' },
|
||||
{ num: 3, name: 'Defensive', threshold: 50, desc: 'Hooks engasjert på kritiske flater (PreToolUse, UserPromptSubmit).' },
|
||||
{ num: 4, name: 'Mature', threshold: 75, desc: 'De fleste 16 kategoriene dekket; trifecta-deteksjon på.' },
|
||||
{ num: 5, name: 'Optimized', threshold: 95, desc: 'Full coverage; A-grade på posture; aktiv overvåking.' }
|
||||
{ num: 1, name: 'Initial', threshold: 0, desc: 'Bare bones — no hooks or minimal posture.' },
|
||||
{ num: 2, name: 'Aware', threshold: 25, desc: 'Posture scanning is active and the risks are known.' },
|
||||
{ num: 3, name: 'Defensive', threshold: 50, desc: 'Hooks engaged on critical surfaces (PreToolUse, UserPromptSubmit).' },
|
||||
{ num: 4, name: 'Mature', threshold: 75, desc: 'Most of the 16 categories covered; trifecta detection on.' },
|
||||
{ num: 5, name: 'Optimized', threshold: 95, desc: 'Full coverage; A-grade on posture; active monitoring.' }
|
||||
];
|
||||
const currentIdx = steps.reduce(function (acc, s, i) {
|
||||
return pct >= s.threshold ? i : acc;
|
||||
|
|
@ -1890,7 +1890,7 @@ function renderMatLadder(categories, postureScore, postureApplicable) {
|
|||
const icon = state === 'completed' ? '✓' : String(s.num);
|
||||
const pillCls = state === 'current' ? ' mat-step__pill mat-step__pill--current' :
|
||||
state === 'completed' ? ' mat-step__pill mat-step__pill--complete' : '';
|
||||
const pillText = state === 'current' ? 'Du er her' : state === 'completed' ? 'Oppnådd' : '';
|
||||
const pillText = state === 'current' ? 'You are here' : state === 'completed' ? 'Reached' : '';
|
||||
const pill = pillText ? '<span class="' + pillCls.trim() + '">' + escapeHtml(pillText) + '</span>' : '';
|
||||
const progress = state === 'current' ? (
|
||||
'<div class="mat-step__progress">' +
|
||||
|
|
@ -1912,7 +1912,7 @@ function renderMatLadder(categories, postureScore, postureApplicable) {
|
|||
return (
|
||||
'<section class="report-meta">' +
|
||||
'<h4>Modenhetsstige — posture-progresjon</h4>' +
|
||||
'<p style="font-size: var(--font-size-sm); opacity: 0.78; margin: 0 0 var(--space-3);">Posture-score på ' + passCount + ' av ' + total + ' kategorier (' + pct + '%) plasserer dette prosjektet på trinn ' + (currentIdx + 1) + ' av 5.</p>' +
|
||||
'<p style="font-size: var(--font-size-sm); opacity: 0.78; margin: 0 0 var(--space-3);">A posture score of ' + passCount + ' of ' + total + ' categories (' + pct + '%) places this project at step ' + (currentIdx + 1) + ' of 5.</p>' +
|
||||
'<div class="mat-ladder" role="list" aria-label="Posture-modenhet over 5 trinn">' + stepHtml + '</div>' +
|
||||
'</section>'
|
||||
);
|
||||
|
|
@ -1973,7 +1973,7 @@ function renderSuppressedGroup(data) {
|
|||
return (
|
||||
'<section class="report-meta">' +
|
||||
'<h4>Narrative audit — supprimerte signaler</h4>' +
|
||||
'<p class="suppressed-group__desc">' + totalCount + ' signaler ble supprimert pre-rapport (v7.1.1 narrative_audit). Disse er ikke false-positives walked-back i prosa, men auto-suppress før klassifisering.</p>' +
|
||||
'<p class="suppressed-group__desc">' + totalCount + ' signals were suppressed pre-report (v7.1.1 narrative_audit). These are not false-positives walked back in prose — they were auto-suppressed before classification.</p>' +
|
||||
groupsHtml +
|
||||
'</section>'
|
||||
);
|
||||
|
|
@ -1981,7 +1981,7 @@ function renderSuppressedGroup(data) {
|
|||
|
||||
/**
|
||||
* Render codepoint-reveal + cp-tag for Unicode-steganografi (UNI-funn).
|
||||
* Brukes på mcp-inspect-rapporter — bytter plain table mot side-by-side
|
||||
* Used on mcp-inspect reports — swaps a plain table for a side-by-side
|
||||
* "synlig vs. decoded codepoint"-visning per tool.
|
||||
*/
|
||||
function renderCodepointReveal(codepoints) {
|
||||
|
|
@ -1999,7 +1999,7 @@ function renderCodepointReveal(codepoints) {
|
|||
const sev = /high/i.test(risk) ? 'critical' : /medium/i.test(risk) ? 'medium' : 'low';
|
||||
const isClean = /clean|—|^-$/i.test(c.codepoints || '') || risk === '—' || risk === '-';
|
||||
const cps = String(c.codepoints || '');
|
||||
// Highlight U+XXXX-mønstre
|
||||
// Highlight U+XXXX patterns
|
||||
const highlighted = cps.replace(/U\+[0-9A-Fa-f]{4,6}/g, function (m) {
|
||||
return '<span class="' + tagFor(m) + '">' + m + '</span>';
|
||||
});
|
||||
|
|
@ -2042,7 +2042,7 @@ function renderCodepointReveal(codepoints) {
|
|||
|
||||
/**
|
||||
* Render top-risks + top-risk for rangert top-funn-listing.
|
||||
* Tar de N (default 5) høyeste alvorlighetsnivåene fra findings og
|
||||
* Takes the N (default 5) highest-severity findings and
|
||||
* viser dem som ordnet liste. Bruker `.top-risks` / `.top-risk` med
|
||||
* `data-severity` for severity-tinted left-border per DS Tier 3-supplement.
|
||||
* Returnerer tom streng hvis ingen findings (eller kun info-funn).
|
||||
|
|
@ -2089,7 +2089,7 @@ function renderTopRisks(findings, n) {
|
|||
}
|
||||
|
||||
// ============================================================
|
||||
// 10 RENDERERS — én per høy-prio kommando.
|
||||
// 10 RENDERERS — one per high-priority command.
|
||||
// ============================================================
|
||||
function renderScan(data, slot) {
|
||||
const meterHtml = renderRiskMeter(data.risk_score, data.riskBand);
|
||||
|
|
@ -2190,7 +2190,7 @@ function renderPluginAudit(data, slot) {
|
|||
) : '';
|
||||
const permHtml = (data.permissions && data.permissions.length) ? (
|
||||
'<section class="report-meta"><h4>Permission-matrise</h4>' +
|
||||
'<table class="report-table"><thead><tr><th>Verktøy</th><th>Krevet av</th><th>Begrunnet</th></tr></thead><tbody>' +
|
||||
'<table class="report-table"><thead><tr><th>Tool</th><th>Required by</th><th>Justified</th></tr></thead><tbody>' +
|
||||
data.permissions.map(function (p) {
|
||||
const isYes = /^yes|^ja/i.test(p.justified);
|
||||
const isNo = /^no$|^nei/i.test(p.justified);
|
||||
|
|
@ -2220,7 +2220,7 @@ function renderPluginAudit(data, slot) {
|
|||
slot.innerHTML = renderPageShell({
|
||||
eyebrow: 'PLUGIN-AUDIT',
|
||||
title: data.title || 'Plugin trust-vurdering',
|
||||
lede: data.lede || 'Trust-verdikt basert på maintainer, lisens, permissions og MCP-deskripsjoner.',
|
||||
lede: data.lede || 'Trust verdict based on maintainer, license, permissions, and MCP descriptions.',
|
||||
verdict: data.verdict || inferVerdict(data, 'risk-score-meter'),
|
||||
keyStats: data.keyStats || inferKeyStats(data, 'risk-score-meter')
|
||||
}, body);
|
||||
|
|
@ -2285,7 +2285,7 @@ function renderMcpAudit(data, slot) {
|
|||
slot.innerHTML = renderPageShell({
|
||||
eyebrow: 'MCP-AUDIT',
|
||||
title: data.title || 'MCP-konfig audit',
|
||||
lede: data.lede || 'Permissions, trust og deskripsjon-drift på tvers av installerte MCP-servere.',
|
||||
lede: data.lede || 'Permissions, trust, and description drift across installed MCP servers.',
|
||||
verdict: data.verdict || inferVerdict(data, 'findings'),
|
||||
keyStats: data.keyStats || inferKeyStats(data, 'findings')
|
||||
}, body);
|
||||
|
|
@ -2392,7 +2392,7 @@ function renderAudit(data, slot) {
|
|||
'<ol class="recommendation-card__body">' + items.map(function (a) { return '<li>' + escapeHtml(a) + '</li>'; }).join('') + '</ol>' +
|
||||
'</section>';
|
||||
};
|
||||
const actionHtml = tierHtml('immediate', 'Umiddelbar', 'critical') + tierHtml('high', 'Høy prioritet', 'high') + tierHtml('medium', 'Medium prioritet', 'medium');
|
||||
const actionHtml = tierHtml('immediate', 'Immediate', 'critical') + tierHtml('high', 'High priority', 'high') + tierHtml('medium', 'Medium priority', 'medium');
|
||||
const meterHtml = (data.risk_score != null) ? renderRiskMeter(data.risk_score, data.riskBand) : '';
|
||||
const topRisksHtml = renderTopRisks(data.findings || [], 5);
|
||||
const findingsHtml = renderFindingsBlock(data.findings || [], 'Funn');
|
||||
|
|
@ -2504,12 +2504,12 @@ function renderHarden(data, slot) {
|
|||
slot.innerHTML = renderPageShell({
|
||||
eyebrow: 'HARDEN',
|
||||
title: data.title || 'Grade A reference config',
|
||||
lede: data.lede || 'Diff-forhåndsvisning av settings.json, CLAUDE.md og .gitignore-endringer.',
|
||||
lede: data.lede || 'Diff preview of settings.json, CLAUDE.md, and .gitignore changes.',
|
||||
verdict: data.verdict || inferVerdict(data, 'diff-report'),
|
||||
keyStats: data.keyStats || [
|
||||
{ label: 'NÅ-GRADE', value: String(data.current_grade || '?') },
|
||||
{ label: 'AKSJONER', value: data.actionable + '/' + data.total },
|
||||
{ label: 'MODUS', value: data.mode || 'dry-run' }
|
||||
{ label: 'CURRENT GRADE', value: String(data.current_grade || '?') },
|
||||
{ label: 'ACTIONS', value: data.actionable + '/' + data.total },
|
||||
{ label: 'MODE', value: data.mode || 'dry-run' }
|
||||
]
|
||||
}, body);
|
||||
}
|
||||
|
|
@ -2564,7 +2564,7 @@ function renderRedTeam(data, slot) {
|
|||
RENDERERS.renderRedTeam = renderRedTeam;
|
||||
|
||||
// ============================================================
|
||||
// FASE 3: 8 RENDERERS — én per gjenstående kommando.
|
||||
// PHASE 3: 8 RENDERERS — one per remaining command.
|
||||
// ============================================================
|
||||
function renderMcpInspect(data, slot) {
|
||||
const invRows = (data.server_inventory || []).map(function (s) {
|
||||
|
|
@ -2602,7 +2602,7 @@ function renderMcpInspect(data, slot) {
|
|||
RENDERERS.renderMcpInspect = renderMcpInspect;
|
||||
|
||||
function renderSupplyCheck(data, slot) {
|
||||
// Ecosystem-cards (small-multiples-mønster)
|
||||
// Ecosystem cards (small-multiples pattern)
|
||||
const ecos = (data.ecosystems || []).filter(function (e) { return Number(e.packages) > 0 || Number(e.osv_hits) > 0 || Number(e.typosquats) > 0; });
|
||||
const ecoCards = ecos.length ? '<div class="small-multiples">' + ecos.map(function (e) {
|
||||
const issues = (Number(e.osv_hits) || 0) + (Number(e.typosquats) || 0);
|
||||
|
|
@ -2640,7 +2640,7 @@ function renderPreDeploy(data, slot) {
|
|||
if (u === 'FAIL' || u === 'BLOCK' || u === 'NO-GO') return 'critical';
|
||||
return 'info';
|
||||
};
|
||||
// v7.6.1 fix: sm-card__grade er fast 28×28 px (designet for én A-F-bokstav), så
|
||||
// v7.6.1 fix: sm-card__grade is fixed at 28×28 px (designed for one A-F letter), so
|
||||
// "PASS"/"PASS-WITH-NOTES"/"FAIL" ble kuttet til "AS"/"PASS-WITH-..."/"FA". Bytt
|
||||
// til en bredde-tilpasset status-pill via inline styling (ingen DS-klasse-endring).
|
||||
const cards = lights.map(function (l) {
|
||||
|
|
@ -2665,7 +2665,7 @@ function renderPreDeploy(data, slot) {
|
|||
const lightsHtml = cards ? '<section class="report-meta"><h4>Traffic-light kategorier</h4><div class="small-multiples">' + cards + '</div></section>' : '';
|
||||
const condHtml = (data.conditions && data.conditions.length) ? (
|
||||
'<section class="recommendation-card" data-severity="high">' +
|
||||
'<span class="recommendation-card__label">Vilkår å løse</span>' +
|
||||
'<span class="recommendation-card__label">Conditions to resolve</span>' +
|
||||
'<ol class="recommendation-card__body">' + data.conditions.map(function (c) { return '<li>' + escapeHtml(c) + '</li>'; }).join('') + '</ol>' +
|
||||
'</section>'
|
||||
) : '';
|
||||
|
|
@ -2708,7 +2708,7 @@ function renderDiff(data, slot) {
|
|||
'</div>' +
|
||||
'<div class="pair-before-after__arrow" aria-hidden="true"></div>' +
|
||||
'<div class="pair-before-after__cell">' +
|
||||
'<span class="pair-before-after__cell-label">NÅ</span>' +
|
||||
'<span class="pair-before-after__cell-label">NOW</span>' +
|
||||
'<span class="pair-before-after__cell-value">' + gradeBadge(data.current_grade) + '</span>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
|
@ -2741,7 +2741,7 @@ function renderDiff(data, slot) {
|
|||
'</section>';
|
||||
};
|
||||
const newHtml = sectionFor('Nye funn', newItems, 'new');
|
||||
const resHtml = sectionFor('Løste funn', resolvedItems, 'resolved');
|
||||
const resHtml = sectionFor('Resolved findings', resolvedItems, 'resolved');
|
||||
const unchHtml = sectionFor('Uendret', unchangedItems, 'unchanged');
|
||||
const movHtml = (movedItems.length) ? sectionFor('Flyttet', movedItems.map(function (m) {
|
||||
return { id: m.id, severity: 'info', description: m.from + ' → ' + m.to };
|
||||
|
|
@ -2751,7 +2751,7 @@ function renderDiff(data, slot) {
|
|||
slot.innerHTML = renderPageShell({
|
||||
eyebrow: 'DIFF',
|
||||
title: data.title || 'Scan diff mot baseline',
|
||||
lede: data.lede || 'Sammenligner nåværende scan mot lagret baseline.',
|
||||
lede: data.lede || 'Compares the current scan against the stored baseline.',
|
||||
verdict: data.verdict || inferVerdict(data, 'diff-report'),
|
||||
keyStats: data.keyStats || inferKeyStats(data, 'diff-report')
|
||||
}, body);
|
||||
|
|
@ -2797,7 +2797,7 @@ function renderWatch(data, slot) {
|
|||
slot.innerHTML = renderPageShell({
|
||||
eyebrow: 'WATCH',
|
||||
title: data.title || 'Continuous monitoring',
|
||||
lede: data.lede || 'Kjører diff på rekursivt intervall via /loop. Notify ved nye funn.',
|
||||
lede: data.lede || 'Runs diff on a recurring interval via /loop. Notifies on new findings.',
|
||||
verdict: data.verdict || inferVerdict(data, 'findings'),
|
||||
keyStats: data.keyStats || inferKeyStats(data, 'findings')
|
||||
}, body);
|
||||
|
|
@ -2829,7 +2829,7 @@ function renderRegistry(data, slot) {
|
|||
}).join('');
|
||||
const sigHtml = sigRows ? (
|
||||
'<section class="report-meta"><h4>Signaturer</h4>' +
|
||||
'<table class="report-table"><thead><tr><th>Skill</th><th>Kilde</th><th>Fingerprint</th><th>Status</th><th>Første sett</th></tr></thead><tbody>' + sigRows + '</tbody></table>' +
|
||||
'<table class="report-table"><thead><tr><th>Skill</th><th>Source</th><th>Fingerprint</th><th>Status</th><th>First seen</th></tr></thead><tbody>' + sigRows + '</tbody></table>' +
|
||||
'</section>'
|
||||
) : '';
|
||||
const fs = (data.findings || []).map(function (f) {
|
||||
|
|
@ -2874,11 +2874,11 @@ function renderClean(data, slot) {
|
|||
cardFor('suppressed', 'Undertrykt', 'info') +
|
||||
'</div>';
|
||||
// Advisory recommendation-cards per bucket — DS Tier 3 data-severity (v7.6.0 fase 5f).
|
||||
// Hver bucket med items > 0 får én recommendation-card med severity-tinted border + label.
|
||||
// Every bucket with items > 0 gets one recommendation-card with a severity-tinted border + label.
|
||||
const bucketAdvisoryDefs = [
|
||||
{ key: 'auto', label: 'Auto-fixable', sev: 'positive', desc: 'Plugin kan fikse disse uten ekstra bekreftelse — deterministiske, lavrisiko-handlinger.' },
|
||||
{ key: 'semi-auto', label: 'Semi-auto — krever bekreftelse', sev: 'medium', desc: 'Foreslåtte tiltak vises som diff. Bruker bekrefter per finding før endring anvendes.' },
|
||||
{ key: 'manual', label: 'Manual remediation', sev: 'high', desc: 'Krever menneskelig vurdering — kontekst, scope eller side-effekter er ikke deterministisk avgjørbare.' },
|
||||
{ key: 'semi-auto', label: 'Semi-auto — requires confirmation', sev: 'medium', desc: 'Proposed changes are shown as a diff. The user confirms per finding before the change is applied.' },
|
||||
{ key: 'manual', label: 'Manual remediation', sev: 'high', desc: 'Requires human judgement — context, scope, or side-effects are not deterministically decidable.' },
|
||||
{ key: 'suppressed', label: 'Undertrykt', sev: 'low', desc: 'Allowlist-treff via .llm-security-ignore — ingen handling.' }
|
||||
];
|
||||
const advisoryHtml = bucketAdvisoryDefs.map(function (b) {
|
||||
|
|
@ -2897,14 +2897,14 @@ function renderClean(data, slot) {
|
|||
const intro = data.mode ? (
|
||||
'<section class="recommendation-card" data-severity="' + (isDry ? 'low' : 'medium') + '">' +
|
||||
'<span class="recommendation-card__label">Modus · ' + escapeHtml(data.mode) + '</span>' +
|
||||
'<p class="recommendation-card__body">' + (isDry ? 'Dry-run: ingen filer endres. Forhåndsvis tiltak før <code>--apply</code>.' : 'Fixes anvendes med automatisk backup i <code>.llm-security-backup/</code>.') + '</p>' +
|
||||
'<p class="recommendation-card__body">' + (isDry ? 'Dry-run: no files are modified. Preview the actions before <code>--apply</code>.' : 'Fixes are applied with an automatic backup in <code>.llm-security-backup/</code>.') + '</p>' +
|
||||
'</section>'
|
||||
) : '';
|
||||
const body = intro + advisoryHtml + kanbanHtml + findingsHtml + recHtml;
|
||||
slot.innerHTML = renderPageShell({
|
||||
eyebrow: 'CLEAN',
|
||||
title: data.title || 'Remediation-kanban',
|
||||
lede: data.lede || 'Funn fordelt på Auto / Semi-auto / Manual / Undertrykt.',
|
||||
lede: data.lede || 'Findings split across Auto / Semi-auto / Manual / Suppressed.',
|
||||
verdict: data.verdict || inferVerdict(data, 'kanban-buckets'),
|
||||
keyStats: data.keyStats || inferKeyStats(data, 'kanban-buckets')
|
||||
}, body);
|
||||
|
|
@ -2929,7 +2929,7 @@ function renderThreatModel(data, slot) {
|
|||
for (let prob = 1; prob <= probSize; prob++) {
|
||||
const score = prob * cons;
|
||||
const items = byPC[prob + '_' + cons] || [];
|
||||
// v7.6.1 fix: bobler er nå <button> så de er klikkbare og fokuserbare.
|
||||
// v7.6.1 fix: bubbles are now <button> so they are clickable and focusable.
|
||||
// data-threat-id lar event-handler senere mappe til detalj-modal.
|
||||
const bubblesHtml = items.length
|
||||
? '<div class="matrix__cell-bubbles">' +
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue