D2b, order 20260821T041145Z-8516817669-from-.claude. Measured by .claude
against the org: llms.txt was missing in 23 of 23 org repos (probe verified
both ways in the same call chain: README.md -> 200, a nonexistent path -> 404).
The operator decision of 21.08 creates it in 6 repos -- the catalog plus the 5
artifacts with their own run path -- and deliberately not in the 12 plugin
repos, whose entry surface is already uniform.
The reader is an AI agent already standing in this repository that needs one
deterministic place to find what this artifact is and how it is started. Not
crawlers: measurements show the major agent crawlers skip /llms.txt and read
the HTML directly, so that would not be a reason that holds.
Follows the llmstxt.org convention: H1, one blockquote summary, then H2
sections holding lists of markdown links, with "Optional" naming the links an
agent may skip. Deliberately minimal -- llms.txt is a convention, not a
ratified standard, and a W3C proposal from June 2026 diverges from the
Answer.AI spec, so a format change should stay cheap.
The install block is quoted byte-identical from README.md's first code block
(verified with diff against README.md:67-68), not rewritten. A rewritten
variant would be a second source of truth, not an entry point.
Docs only; the Iron Law does not fire. Full suite unchanged vs HEAD:
2253 tests / 2247 pass / fail 0, exit 1 from the known jetbrains-parser
after()-hook assertion, measured identically on a stashed HEAD tree.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7TAHJfxBoCm9YwhMWm6y5
Closes Phase 3 (B11) of the v8.0.0 plan. Three parts, all with the failing
test written first.
riskScoreV1 removed. scanners/lib/severity.mjs drops riskScoreV1() and its
SEVERITY_WEIGHTS_V1 table - @deprecated since v7.0.0, kept for diff/comparison,
zero callers in code or tests (re-verified, not taken from the plan). The v1
weights are recorded in CHANGELOG so an old score stays re-derivable. riskScore
(v2) is untouched; a test pins that one critical still lands in the 70-95 tier
and that 50 lows score below it, which is exactly the case v1 collapsed to 100.
Posture category 12 no longer keys off an identifier name. The check was
/TRIFECTA_MODE/i over the session-guard source, which measured what a constant
was CALLED rather than whether enforcement was configurable. With the env-var
gone, that regex would have dropped every correctly-migrated project from PASS
to PARTIAL - the gate punishing the migration it exists to encourage. It now
matches getPolicyValue('trifecta', 'mode', ...) and still accepts a pre-v8
vendored guard reading the old env-var, because a third-party project carries
its own hook copy and is equally configurable either way; the evidence line
says which of the two was found. The PARTIAL finding recommended setting an
env-var that v8 ignores; it now names the policy key. The grade-a fixture hook
moves to the policy-era form.
Two never-implemented env-vars deleted from the docs. LLM_SECURITY_SCR_OFFLINE
(ci-cd-guide) and LLM_SECURITY_OFFLINE (supply-chain-attack example) were
documented as OSV.dev / npm-audit kill-switches. No code has ever read either -
verified by grep across scanners, hooks and scripts, which finds them only in
markdown. A promised kill-switch that does nothing is worse than a documented
absence: it is trusted precisely when the run is meant to be air-gapped. The
docs now say there is none and that egress must be blocked at the network
layer. The LLM_SECURITY_AUDIT_* wildcard is narrowed to the one real key.
Docs. Migration section in README + CHANGELOG with the env-var -> policy-key
table, the detection commands (env + shell rc + .envrc + workflows), and the
explicit warning that a removed variable is now INERT rather than an error -
which is the failure mode that loses a project its configuration silently. The
hardening-guide env table splits into surviving vars and a removed-vars
migration table; its "promote to block" runbook named two variables that no
longer exist. Also swept: CLAUDE.md hook table, scanner-reference, ci-cd-guide,
both lethal-trifecta example docs, mitigation-matrix, injection-research.
Test counts in README/CLAUDE.md synced 2034 -> 2045.
Suite 2045 tests, 0 fail (2039 + 4 posture-trifecta + 2 riskScoreV1). The two
known parallel-load flakes did not recur this run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BB4vXvwvtW4dxbPRd6vsez
The PostToolUse hook read input.tool_output, but live Claude Code delivers the tool result as tool_response — so the indirect-injection scan on MCP tool output silently never fired outside the test harness (which sent tool_output). The hook now reads tool_response with a tool_output fallback for older harnesses/fixtures. +3 tests covering string and object tool_response and the precedence. Found via a live-session check during the v7.8.3 sweep; not one of the 52 MEDIUM-tier findings. Suite 2016/0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQyMTQfyrsAapaCMPxTtQ
Bumps plugin to 7.8.3 (package.json, plugin.json, README version badge) and syncs the documentation surfaces that had drifted: orchestrated scanner count 9/10/13 to 14 (#8; the WFL/workflow scanner was omitted from the reference list), posture categories 13 to 16 (#44), red-team scenarios 64 to 72 (#45), tests badge/prose 1822 to 2013 (#46). Corrects the pathguard hook-table matcher and header comment to Edit|Write (follows the #9 fix) and removes the two dangling ROADMAP.md references (#47; the roadmap is not a public file). Adds the v7.8.3 CHANGELOG entry, README Recent-versions row, and CLAUDE.md highlights. The '23 scanners' total is a separate module count and is left unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQyMTQfyrsAapaCMPxTtQ
Bumps package.json, .claude-plugin/plugin.json and the README badge to
7.8.2; adds the release entry to CHANGELOG.md, docs/version-history.md,
the README recent-versions table and the CLAUDE.md highlights block.
Also fixes test pollution introduced with the ide-extension regression
suite: its temp roots used an `llmsec-jb-plugin-` prefix, and
jetbrains-parser.test.mjs asserts globally that no `llmsec-jb-*`
directory survives anywhere in tmpdir. The shared prefix made that
assertion fail depending on test order — it passed on the first full run
and failed on the next. Prefix is now `llmsec-nullmanifest-`.
npm test: 1901/1901 green, three consecutive runs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQyMTQfyrsAapaCMPxTtQ
Version bump + release notes for the auto-cleaner command-injection fix
(f083cda). Security patch only; no feature changes. 1865 tests, 0 fail.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQyMTQfyrsAapaCMPxTtQ
Reword the v7.8.0 release notes to refer to the scanners as TRG/SIG/AST only;
the internal codename is removed from CHANGELOG, CLAUDE.md, README, the
version-history section, and STATE. No behaviour or version change.
Session C of the security-fix track: cut the TRG/SIG/AST release now that the
F-1/F-2/F-3 security gates pass. Pure version-sync — the three scanners shipped
in Steps 1-7 (616e7ff..fc7cf57); no production code changes here.
Version-sync 7.7.2 -> 7.8.0 across every current pointer: .claude-plugin/
plugin.json, package.json, README.md badge, and the CLAUDE.md header + "release
notes" range sentinel. Narrative additions (prior releases kept as history):
- CHANGELOG.md: new [7.8.0] entry (Added: TRG/SIG/AST; Changed: prefix
registration + knowledge/ packaging).
- docs/version-history.md: new v7.8.0 section describing the three scanners.
- README.md "Recent versions": new 7.8.0 row.
- CLAUDE.md: new v7.8.0 highlights paragraph above the v7.7.2 one.
TRG/SIG/AST recap (built Steps 1-7, behind the security-fix gate):
- TRG (scanners/trigger-scanner.mjs) — trigger/activation-abuse: TRG-shadow /
TRG-baiting / TRG-broad over name+description frontmatter, decode pipeline
first (LLM06/AST04).
- SIG (scanners/signature-scanner.mjs) — pure-Node known-malware identity engine
over raw bytes + decode pipeline; rules in knowledge/signatures.json
(LLM03/LLM02).
- AST (scanners/ast-taint-scanner.mjs) — parse-only python3 taint helper
(scanners/lib/py-ast-taint.py) with graceful regex fallback (LLM01/LLM02/AST02).
Release gate: full node --test suite 1863/0 after the doc edits. No scanner,
hook, or command behaviour changes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3s6WnubSSrFjAQTLQdVbG
Tre fixes commited etter v7.7.0-tagen (adffb60 + 52afd12 + 02a66f3) viste
versjons-inkonsistens: package.json + plugin.json + README badge + CLAUDE.md
header satt fortsatt på v7.7.0 mens commit-meldinger og inline-kommentarer
refererte v7.7.1 som om det var en release. Per feedback_version_sync.md
skal alle versjonsreferanser stemme — denne commiten lukker gapet.
Endringer:
- package.json: 7.7.0 → 7.7.1
- .claude-plugin/plugin.json: 7.7.0 → 7.7.1
- plugin README badge: version-7.7.0-blue → version-7.7.1-blue
- plugin README "Recent versions"-tabell: ny [7.7.1]-rad
- plugin CLAUDE.md header + v7.7.1-highlights state-seksjon
- docs/version-history.md: ny v7.7.1-seksjon
- playground HTML linje 6935: 'Plugin v7.7.0' → 'Plugin v7.7.1'
(samme template-litteral som v7.7.0-bumpen ikke fanget, nå synket)
- CHANGELOG.md: ny [7.7.1]-seksjon med full Changed/Fixed/Notes
- rot README llm-security-entry: v7.7.0 → v7.7.1 + ny v7.7.1-bullet
- rot CLAUDE.md plugin-katalog: v7.7.1-bump
Verifisert:
- 1820/1820 tester grønne (pre-compact-flake fyrte ikke)
- CLI rapporterer fornuftig feilmelding på tom input
- Ingen kildefil-treff på 7.7.0 utenfor CHANGELOG/version-history/REMEMBER/TODO/ROADMAP
Ingen ny atferd. Kun versjons-synking + dokumentasjon av tre fixes som var
deployert som ad-hoc-commits.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Hver /security <cmd> som produserer rapport printer nå en klikkbar
file://-lenke til en self-contained HTML-versjon. Levert over fem
sesjoner; sesjon 5 wirer de 14 resterende skill-filene + slipper
v7.7.0 (versjonsbump + docs).
Sesjon-historikk:
- Sesjon 1 (de23a63) — playground katalog list-view + builder-pane med
copy-knapp på alle 18 rapporter
- Sesjon 2 (ea8da55) — playground prosjekt-surface opprydding
(stub-screen + topbar-splitt)
- Sesjon 3 (01a8947) — extract 18 inline parsers + 18 inline renderers
fra playground til canonical ESM-modul scripts/lib/report-renderers.mjs
(playground beholder bit-identisk inline-kopi siden ESM import ikke
fungerer fra file://)
- Sesjon 4 (c7748d5) — ny zero-dep CLI scripts/render-report.mjs
(stdin/file/stdout-modus, kebab→camel commandId-routing, ~140 KB
self-contained HTML med 6 inlined DS-stylesheets + lokal .report-table,
absolutte file://-paths for Ghostty cmd-click). 4 skills wired:
scan, audit, posture, deep-scan.
- Sesjon 5 (denne) — 14 resterende skills wired: plugin-audit, mcp-audit,
mcp-inspect, ide-scan, supply-check, dashboard, pre-deploy, diff,
watch, registry, clean, harden, threat-model, red-team. Hver skill-fil
har nå en HTML Report-step som instruerer Claude å skrive markdown
verbatim, kjøre CLI, og appende klikkbar file://-lenke til respons.
Release-arbeid:
- Versjonsbump v7.6.1 → v7.7.0 i 6 plugin-filer + 2 rot-filer
(package.json, .claude-plugin/plugin.json, README badge, CLAUDE.md
header + state-seksjon, docs/version-history.md, plugin Recent versions-
tabell, rot README plugin-entry, rot CLAUDE.md plugin-katalog)
- CHANGELOG [7.7.0] med full historikk fra sesjon 1-5
- docs/version-history.md v7.7.0-seksjon
Verifisert:
- 18/18 commandIds i CLI gir > 138 KB self-contained HTML
- 1819/1820 tester grønne (pre-compact-scan-perf-flake fyrte under last,
passerer i isolasjon på 1582 ms — pre-eksisterende, defer til v7.7.x)
- 18/18 skill-filer har HTML Report-step
- Ingen kildefil-treff på 7.6.1 utenfor historiske changelog/version-
history/README releases-tabell
Ingen scanner- eller hook-atferdsendringer — purely additive surface.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Seks bugs fanget av maintainer ved manuell verifisering i nettleser etter
v7.6.0-release. Alle skyldes mismatch mellom DS-klasser og hvordan
playground-rendrere brukte dem, eller manglende DS-implementasjoner av
klasser playground-rendrere antok eksisterte.
Fixes:
- renderFindingsBlock brukte .findings outer-class som DS har som
2-kolonners grid (360px list + 1fr detail-panel) — headeren havnet
i venstre kolonne, items i høyre, brutt layout i alle 18 rapporter
med findings. Erstattet med .report-meta + h4 + findings__list >
findings__group + findings__group-header + findings__items
(korrekt DS-mønster, kun list-delen).
- .report-table manglet helt i DS men brukes i 7+ rendrere (OWASP,
Supply chain, Scanner Risk Matrix, Plugin-meta, Permission-matrise,
Live-meter, Siste runs, Godkjenninger, Mitigation roadmap). Lagt
lokal CSS-implementasjon i playground-HTML style-blokk: border-
collapse, zebra-hover, header-styling. Komplementerer DS-tokens
uten å modifisere vendor.
- renderPreDeploy traffic-lights brukte .sm-card__grade som er fast
28x28 px (én A-F-bokstav) — kuttet PASS til AS og PASS-WITH-NOTES
til PASS-WITH-... i alle traffic-light-cards. Erstattet med
bredde-tilpasset status-pill via inline styling (severity-soft +
on tokens).
- Threat-model matrix-bobler ikke klikkbare. Erstattet span med
button type=button data-threat-id + aria-label. Click-handler
scroller til tilsvarende rad i Trusler-tabellen og fremhever
den i 1.6 sek.
- Radar-labels overlappet ved 6+ akser fordi alle brukte
text-anchor=middle. Økt SVG-størrelse 280 → 380, radius 105 → 125.
Bytter text-anchor fra middle til start/end basert på horisontal-
posisjon.
- recommendation-card__body tekstoverflyt på lange single-line tekster
(vilkår, owner-tags, dato). Lagt overflow-wrap: anywhere;
word-break: break-word i lokal style-blokk.
Verifisering:
- 4/4 fix-spesifikke smoke-tester passerer
- 18/18 renderere produserer fortsatt komplett HTML mot
dft-komplett-demo (regresjons-test)
- Filendring playground.html 10677 → 10753 linjer (+76 netto)
Versjonsbump v7.6.0 → v7.6.1 (patch — bugfix-only, ingen scanner- eller
hook-atferdsendringer):
- plugins/llm-security/.claude-plugin/plugin.json
- plugins/llm-security/package.json
- plugins/llm-security/README.md (badge)
- plugins/llm-security/CHANGELOG.md ([7.6.1] entry)
- plugins/llm-security/playground/llm-security-playground.html (footer)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Bumps from v7.3.1 to v7.4.0. Purely additive surface — no scanner
or hook behavior changes, no breaking changes.
Headline content (already merged on main since v7.3.1):
- examples/ utvidelse — seven runnable demonstration walkthroughs
shipped over three sessions (sesjon 1 pre-existing
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 is self-contained: README + fixture + run-script +
expected-findings testable contract. State-isolation pattern
(PID-suffixed JSONL or env-overrides like
LLM_SECURITY_MCP_CACHE_FILE) keeps the user's real cache and
/tmp state untouched.
- tests/e2e/ — three new suites totalling 45 tests:
attack-chain.test.mjs (17), multi-session.test.mjs (9),
scan-pipeline.test.mjs (19). Test count 1777 to 1822. These
exercise the framework as a coordinated system rather than as
isolated unit-tests.
Version sync (8 files):
- package.json
- .claude-plugin/plugin.json
- CLAUDE.md (header)
- README.md (badge + Recent versions tabellen new row)
- CHANGELOG.md (Unreleased to [7.4.0] - 2026-05-05 with summary)
- scanners/dashboard-aggregator.mjs VERSION constant
- scanners/ide-extension-scanner.mjs VERSION constant
- scanners/posture-scanner.mjs VERSION constant
Stabilization-stance unchanged. v8.0.0 remains the planned
deprecation-cleanup release. v7.x continues as the stable line.
Tests: 1822/1822 grønne lokalt etter bump.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Runnable demonstration of hooks/scripts/pre-compact-scan.mjs (the
only PreCompact hook in the plugin) detecting both a CRITICAL
injection pattern and an AWS-shaped credential inside a synthetic
JSONL transcript, exercised across all three values of
LLM_SECURITY_PRECOMPACT_MODE plus a benign-transcript control case
in block mode that proves the gate is not a brick wall.
The transcript is generated at runtime in a per-invocation tempdir
under os.tmpdir() and the directory is removed in a finally block,
so the user's real ~/.claude/projects/.../transcripts/ are never
touched. The AWS-shaped key uses the same 'AK' + 'IA' + ...
fragmentation idiom as tests/e2e/attack-chain.test.mjs so this
source contains no literal credentials and pre-edit-secrets does
not block writes during development.
Nine independent assertions (9/9 must pass):
- block mode + poisoned: exit 2, decision=block JSON, reason text
covers both injection and AWS labels (3 assertions)
- warn mode + poisoned: exit 0, systemMessage JSON, no decision
field (2 assertions)
- off mode + poisoned: exit 0, no JSON on stdout (2 assertions)
- block mode + benign: exit 0, no decision=block JSON (2 assertions)
OWASP / framework mapping: LLM01, LLM02, ASI01, AT-1, AT-3.
Docs updated: plugin README "Other runnable examples", plugin
CLAUDE.md "Examples" tabellen, CHANGELOG [Unreleased] Added.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Single-component lethal-trifecta walkthrough that drives
scanners/toxic-flow-analyzer.mjs against a deliberately
misconfigured fixture plugin. The fixture agent declares
tools: [Bash, Read, WebFetch], which alone covers all three
trifecta legs (input surface + data access + exfil sink). No
hooks/hooks.json is shipped, so TFA's mitigation logic finds
no active guards and emits a CRITICAL "Lethal trifecta:"
finding without downgrade.
Plugin marker is plugin.fixture.json (recognised by isPlugin())
rather than .claude-plugin/plugin.json — the latter is blocked
by the plugin's own pre-write-pathguard hook, and
plugin.fixture.json exists in isPlugin() specifically so
example fixtures can self-mark without touching guarded paths.
Three independent assertions (3/3 must pass): direct trifecta
present and CRITICAL; finding mentions the exfil-helper
component; description confirms "no hook guards detected"
(proves the mitigation path stayed inactive). expected-findings.md
documents the contract.
OWASP / framework mapping: ASI01, ASI02, ASI05, LLM01, LLM02, LLM06.
Docs updated: plugin README "Other runnable examples", plugin
CLAUDE.md "Examples" tabellen, CHANGELOG [Unreleased] Added.
[skip-docs] is appropriate because examples don't change what
the plugin "synes å dekke utad" — marketplace root README is
unaffected.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Three new self-contained, runnable threat demonstrations under
examples/, continuing the batch started in 24b65b3. Each example
has README.md + run-*.mjs + expected-findings.md and uses
state-isolation discipline so the user's real cache/state files
are never polluted.
- examples/supply-chain-attack/ — two-layer demonstration:
pre-install-supply-chain (PreToolUse) blocks compromised
event-stream version 3.3.6 and emits a scope-hop advisory for
the @evilcorp scope; dep-auditor (DEP scanner, offline) flags
5 typosquat dependencies plus a curl-piped install-script
vector in the fixture package.json. Maps to LLM03/LLM05/ASI04.
- examples/poisoned-claude-md/ — all 6 memory-poisoning detectors
fire on a deliberately poisoned CLAUDE.md plus a fixture
agent file under .claude/agents (E15/v7.2.0 surface):
detectInjection, detectShellCommands, detectSuspiciousUrls,
detectCredentialPaths, detectPermissionExpansion,
detectEncodedPayloads. No agent runtime needed — scanner
imported directly. Maps to LLM01/LLM06/ASI04.
- examples/bash-evasion-gallery/ — one disguised variant per
T1 through T9 evasion technique fed through pre-bash-destructive,
verified BLOCK after bash-normalize strips the evasion. T8
base64-pipe-shell uses its own BLOCK_RULE. The canonical
destructive form uses a path token rather than the bare slash
(regex word-boundary requires it). Source-string fragmentation
pattern reused from the e2e attack-chain test. Maps to
LLM06/ASI01/LLM01.
Plugin README "Other runnable examples" section + plugin
CLAUDE.md "Examples" table + CHANGELOG Unreleased/Added
all updated. Marketplace root README unchanged
([skip-docs] for marketplace-level gate — plugin's outward
coverage is unchanged, only demonstrations were added).
Two new self-contained, runnable threat demonstrations under examples/:
- lethal-trifecta-walkthrough/ — feeds 5 hook calls (WebFetch, Read .env,
Bash curl POST + suppression follow-ups) into post-session-guard and
verifies the Rule-of-Two advisory fires exactly on leg 3. State
isolated via run-script PID so /tmp/llm-security-session-*.jsonl is
not polluted. Treffer post-session-guard, ASI01/ASI02, LLM01/LLM02.
- mcp-rug-pull/ — mutates an MCP tool description across 8 stages.
Each per-update <10% Levenshtein, cumulative reaches 32.2% by stage
7 — proves the v7.3.0 (E14) mcp-cumulative-drift MEDIUM advisory
catches slow-burn rug-pulls that the per-update detection would
miss. Uses LLM_SECURITY_MCP_CACHE_FILE to isolate cache. Treffer
post-mcp-verify, mcp-description-cache.mjs, OWASP MCP05/LLM03/ASI04.
Each example: README.md + run-*.mjs + expected-findings.md.
Plugin README "Other runnable examples" section + CHANGELOG
[Unreleased] Added bullets + plugin CLAUDE.md "Examples" section
all updated in this commit. Marketplace root README unchanged
since plugin's outward coverage is unchanged ([skip-docs]
covers the marketplace-level gate).
Three new files in tests/e2e/ (45 tests, 1777 -> 1822):
- attack-chain.test.mjs (17): full hook stack against attack payloads in
sequence -- prompt injection at the gate; T1/T5/T8 bash evasions;
pathguard on .env / .ssh; secrets hook on AWS-shaped keys and PEM
headers; markdown link-title and HTML-comment poisoning in tool
output; trifecta accumulation over a single session with dedup on
the next benign call.
- multi-session.test.mjs (9): state persistence across simulated
session boundaries. Uses the fact that a hook child's process.ppid
equals the test runner's process.pid, so writing the session state
file directly simulates "previous session" history. Covers slow-burn
trifecta (legs spread >50 calls), MCP cumulative description drift
via LLM_SECURITY_MCP_CACHE_FILE override, and pre-compact transcript
poisoning in warn / block / clean / missing-file modes.
- scan-pipeline.test.mjs (19): scan-orchestrator + all 10 scanners +
toxic-flow correlator against poisoned-project (BLOCK / 95 / Extreme)
and grade-a-project (WARNING / 48 / High). Asserts envelope shape,
verdict, risk_score, severity counts, OWASP coverage, scanner
enumeration, and a narrative-coherence cross-check that the BLOCK
scan strictly outranks the WARNING scan along every axis.
Test files build credential-shaped payloads at runtime via concatenation
so they contain no literal matches for the pre-edit-secrets regexes
(memory rule feedback_secrets_hook_test_fixtures.md).
Doc updates in same commit per marketplace policy:
- CLAUDE.md header: 1777+ -> 1822+ tests, mentions tests/e2e/
- README.md badge tests-1777 -> tests-1822, body text updated
- CHANGELOG.md: new [Unreleased] Added section describing scope
No version bump. No behavior changes outside tests/.
The plugin lives in ktg-plugin-marketplace and is distributed via the
Claude Code marketplace mechanism. There is no standalone
open/claude-code-llm-security repo; references to it were aspirational
and never realized.
- package.json: homepage now deep-links to plugins/llm-security/ in the
marketplace; repository.url uses the marketplace repo with directory
field (npm convention for monorepo plugins); bugs.url routes to
marketplace issue tracker.
- CLAUDE.md: "Public Repository" section replaced with "Distribution"
section documenting the marketplace install path.
- CONTRIBUTING.md: issue tracker URL points at marketplace issues with
[llm-security] prefix convention.
- CHANGELOG.md: v7.3.1 entry rewritten to reflect actual change
(URLs corrected to marketplace, not "fixed from one wrong URL to
another wrong URL").
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
No behavior changes. Sets the public stance, tightens documentation, and
removes coherence drift so anyone forking or downloading the plugin gets
a consistent starting point.
Added:
- CONTRIBUTING.md — public fork-and-own guide. Why PRs are not accepted,
how to fork well, what is welcome via issues.
- README "Project scope" section — out-of-scope table naming what is
fork-and-own territory (web dashboard, fleet policy, runtime firewall,
IDE LSP, compliance pack, ticketing, multi-tenancy, ML detectors,
marketplace UI, SSO/SCIM/RBAC) with commercial alternatives.
- package.json: bugs.url, CONTRIBUTING/SECURITY/CHANGELOG in files
whitelist for npm publishing.
Changed:
- SECURITY.md rewritten. Supported-versions table from stale 5.1.x to
current reality (7.3.x active, 7.0-7.2 best-effort, <7.0 EOL).
Best-effort solo response timeline. Scope expanded to bin/.
- Scanner VERSION constants synced to plugin version. Was 6.0.0 in
dashboard-aggregator and posture-scanner.
- package.json repository.url corrected from fromaitochitta/ to open/.
- README "Feedback & contributing" links to CONTRIBUTING.md.
Fixed:
- pre-compact-scan size-cap timing test ceiling raised 500ms -> 1000ms.
Was a flake on Intel Mac and CI under load. Design target unchanged
(<500ms, documented in CLAUDE.md).
Notes:
- First patch on the stabilization line (post-2026-05-01).
- Wave E attack-simulator scenarios deferred indefinitely; coverage
remains at 72.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Batch C release. Closes 12 implementation tasks (E3, E8-E14, 8.4, 8.6,
8.7, 8.10) across four execution waves: A (bash + decoder), B (supply
chain + workflow scanner), C (MCP cumulative drift), D (code quality).
Wave E (9 new attack-simulator scenarios for the new defenses) deferred
to v7.3.1 — defenses are unit-tested per wave; the deferred work adds
attack-simulator regression coverage on top, not the primary safety net.
Tests: 1665+ → 1777 (Wave A-D cumulative, +112).
Version sync targets touched:
- package.json
- .claude-plugin/plugin.json
- CLAUDE.md (header)
- README.md (badge + new release-history row)
- scanners/ide-extension-scanner.mjs (VERSION constant)
- ../../README.md (marketplace root plugin entry)
- CHANGELOG.md (new [7.3.0] section per Keep a Changelog, all 12 task
IDs covered individually under Added/Changed/Documentation/Tests/Notes)
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Documents the v7.1.1 narrative-coherence patch in CLAUDE.md (mini-block
appended after the v7.0.0 paragraph) and CHANGELOG.md (new [7.1.1]
section per Keep a Changelog convention, placed above [7.1.0]).
Plan: .claude/plans/ultraplan-2026-04-29-report-coherence.md
Brief: .claude/ultraplan-spec-2026-04-29-report-coherence.md
Verification gates passed:
- npm test: 1522/1522 (was 1511; +11 from new narrative test)
- node --test tests/lib/severity.test.mjs: 86/86 (co-monotonicity sweep
at lines 252-303 unchanged and green)
- node --test tests/scanners/skill-scanner-narrative.test.mjs: 11/11
- Orchestrator against fixture: WARNING / 48 / 1 HIGH (HITL trap caught
correctly, no whiplash)
- SARIF inline check via toSARIF import: sarif-version 2.1.0, runs: 1
- Zero remaining v1 cutoffs in agent + template
Out of scope but flagged for Batch B (deferred to v7.2.0):
- commands/scan.md:113-114 retains v1 risk formula
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Closes A2 of v7.1.0 critical-review patch (docs/critical-review-2026-04-20.md):
- B4 (severity JSDoc): 4 critical = 93, not 90. Fixed in scanners/lib/severity.mjs:23
and CHANGELOG.md v7.0.0 tier description. The actual computation has always been
93 (70 + log2(5)*10 = 93.22 → round); only the docs were wrong.
- §5.4 co-monotonicity: new sweep test in tests/lib/severity.test.mjs over 15
representative count vectors. Asserts that (verdict, riskBand) agree under the
v7.0.0 contract for every case — catches future drift between riskScore tiers,
verdict cutoffs, and riskBand cutoffs. Includes a B4 anchor test (riskScore
{critical: 4} === 93) so doc/code drift fails loudly.
- B8 (CaMeL claims toned down): post-session-guard.mjs:646 comment block and
CLAUDE.md:184 Defense Philosophy bullet now describe the implementation
honestly — opportunistic byte-matching of truncated output fingerprints
(first 200 bytes, SHA-256/16-hex), not semantic data-flow tracking.
Trivially bypassed by mutation, summarisation, or re-encoding. Inspired by
CaMeL (DeepMind 2025), but not a CaMeL capability-tracking implementation.
Tests: 1495 → 1511 (+16: 15 sweep cases + 1 B4 anchor). All green.
E2E verification against content-heavy repo (`content-claude-code`) revealed
413 entropy findings (8 HIGH / 405 MEDIUM) from markdown image CDN URLs in
JSON content indexes — e.g., ``.
These are legitimate content-repo artifacts, not credentials. The 40-char
hash segment in the CDN URL trips Shannon entropy (H=5.29 over 300 chars),
and rule 13 (inline <svg>) doesn't match since there's no literal `<svg>`
tag — the `.svg` is just a URL path suffix.
Added rule 18 `MARKDOWN_IMAGE = /!\[[^\]]*\]\(\s*https?:\/\//` — matches
`` / ``. Line-level (not string-level) so URL
is not over-specific.
E2E impact on `content-claude-code`:
- Before: BLOCK / 65 / 8H 437M 0L
- After: WARNING / 56 / 3H 427M 0L
Hyperframes unchanged: BLOCK / 80 / 1C 4H 92M — real CRITICAL SQL-injection
and HIGH findings still detected.
Tests: 2 new (positive + negative fixture) bringing entropy-context to 26,
total suite 1485 → 1487.
Docs updated to "rules 11-18" and "8 new line-suppression rules".
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Final commit in the trustworthy-scoring series. Bundles verdict cutoff
alignment, the last suite of tests, and all documentation touch-points
that quote version numbers or describe v7.0.0 behaviour.
Verdict/band co-monotonicity
- `scanners/lib/severity.mjs` — verdict cutoffs moved from 61/21 to 65/15
so `BLOCK >= 65`, `WARNING >= 15` locks onto the v2 riskBand() boundaries.
Prevents "BLOCK / Medium band" contradictions under the v2 formula.
Scanner hardening (bug fixes from v7.0.0 testing)
- `scanners/entropy-scanner.mjs` — `policy_source` now uses
`existsSync('.llm-security/policy.json')` instead of value-based check.
Old heuristic always reported 'policy.json' because DEFAULT_POLICY now
carries an `entropy.thresholds` section.
- `scanners/lib/file-discovery.mjs` — `.sass` and GPU shader extensions
(`.glsl, .frag, .vert, .shader, .wgsl`) added to TEXT_EXTENSIONS. Without
this, shader files were invisible to file-discovery, so they were never
counted as skipped by the entropy-scanner extension filter.
Tests
- `tests/scanners/entropy-context.test.mjs` (new, 24 tests) — A. File-ext
skip (4), B. Line-level rules 11-17 (8), C. Policy overrides (3).
Fixtures generate 80-char base64 payloads at runtime via
`crypto.randomBytes` to dodge the plugin's own pre-edit credential hook
on the test source.
- `tests/lib/severity.test.mjs` — rewritten with v2 scoring table (70
tests total, was 52).
- `tests/lib/output.test.mjs:243` — "1 critical = score 80" under v2
(was 25 under v1).
- Full suite: 1485/1485 green (was 1461).
Docs
- `CHANGELOG.md` — v7.0.0 entry with BREAKING CHANGES section.
- `README.md` (plugin + marketplace root) — version badge, history table,
plugin-card version string, test count.
- `CLAUDE.md` — header version, "v7.0.0 — Trustworthy scoring" summary
paragraph at the top.
- `docs/security-hardening-guide.md` — new section 6 "Calibration & false
positives" documenting v2 formula, context-aware entropy scanner,
typosquat allowlist, and §6.4 tuning workflow. Existing "Recommended
baseline" section renumbered to §7.
Version bump
- `6.6.0 -> 7.0.0` across package.json, .claude-plugin/plugin.json,
scanners/ide-extension-scanner.mjs VERSION const, README badge,
CLAUDE.md header, marketplace root README card.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
VSIX fetch + extract for URL targets now runs in a sub-process wrapped by
sandbox-exec (macOS) or bwrap (Linux), reusing the same primitives proven
by the v5.1 git-clone sandbox. Defense-in-depth — even if our own
zip-extract.mjs ever has a bypass, the kernel refuses any write outside
the per-scan temp directory.
New files:
- scanners/lib/vsix-fetch-worker.mjs — sub-process worker. Argv: --url
--tmpdir; emits one JSON line on stdout (ok/sha256/size/source/extRoot
or ok:false/error/code). Silent on stderr. Exit 0/1.
- scanners/lib/vsix-sandbox.mjs — wrapper. Exports buildSandboxProfile,
buildBwrapArgs, buildSandboxedWorker, runVsixWorker. 35s timeout, 1 MB
stdout cap.
Changes:
- scanners/ide-extension-scanner.mjs: fetchAndExtractVsixUrl is now
sandbox-aware (useSandbox option, default true). In-process logic
preserved as fallback. New meta.source.sandbox field:
'sandbox-exec' | 'bwrap' | 'none' | 'in-process'.
- scan(target, { useSandbox }) defaults to true; tests pass false because
globalThis.fetch mocks do not cross process boundaries.
- Windows fallback: in-process with meta.warnings advisory.
Tests:
- 8 new tests in tests/scanners/vsix-sandbox.test.mjs (per-platform
profile generation, worker arg construction, live worker exit
behavior on invalid URLs — no network).
- Existing URL tests updated to opt out of sandbox (useSandbox: false).
- 1344 → 1352 tests, all green.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Pre-installation verification of VS Code extensions via URL — fetch a remote
VSIX, extract it in a hardened sandbox, and run the existing IDE scanner
pipeline against it. No npm dependencies.
Sources:
- VS Code Marketplace (publisher.gallery.vsassets.io direct download)
- OpenVSX (open-vsx.org official API)
- Direct .vsix HTTPS URLs
Defenses:
- HTTPS-only, TLS verified, manual redirect with per-source host whitelist
- 30s total timeout via AbortController
- 50MB compressed cap, 500MB uncompressed, 100x expansion ratio
- Zero-dep ZIP extractor: zip-slip, absolute paths, drive letters, NUL bytes,
symlinks (Unix mode 0xA000), depth limits, ZIP64 rejected, encrypted rejected
- SHA-256 streamed during fetch, surfaced in meta.source
- Temp dir cleanup in all paths (try/finally)
Files:
- scanners/lib/vsix-fetch.mjs (HTTPS fetcher, host whitelist, streaming SHA-256)
- scanners/lib/zip-extract.mjs (zero-dep parser with hardening caps)
- knowledge/marketplace-api-notes.md (endpoint reference)
- 3 test files (48 tests added: vsix-fetch, zip-extract, ide-extension-url)
Tests: 1296 → 1344 (all green).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add threshold-based exit codes (--fail-on <severity>) and compact
output mode (--compact) to scan-orchestrator and CLI. Pipeline
templates for GitHub Actions, Azure DevOps, GitLab CI with SARIF
upload. CI/CD guide with Schrems II/NSM compliance documentation.
npm publish preparation (files whitelist, .npmignore). Policy ci
section for distributable CI defaults. Version 6.1.0.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add /ultraresearch-local for structured research combining local codebase
analysis with external knowledge via parallel agent swarms. Produces research
briefs with triangulation, confidence ratings, and source quality assessment.
New command: /ultraresearch-local with modes --quick, --local, --external, --fg.
New agents: research-orchestrator (opus), docs-researcher, community-researcher,
security-researcher, contrarian-researcher, gemini-bridge (all sonnet).
New template: research-brief-template.md.
Integration: --research flag in /ultraplan-local accepts pre-built research
briefs (up to 3), enriches the interview and exploration phases. Planning
orchestrator cross-references brief findings during synthesis.
Design principle: Context Engineering — right information to right agent at
right time. Research briefs are structured artifacts in the pipeline:
ultraresearch → brief → ultraplan --research → plan → ultraexecute.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>