chore(llm-security): v7.3.1 — stabilization patch for forkers and downstream users

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>
This commit is contained in:
Kjell Tore Guttormsen 2026-05-01 06:14:03 +02:00
commit 62a9335772
12 changed files with 336 additions and 30 deletions

View file

@ -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.3.0`
### [LLM Security](plugins/llm-security/) `v7.3.1`
Security scanning, auditing, and threat modeling for agentic AI projects.

View file

@ -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.3.0"
"version": "7.3.1"
}

View file

@ -4,6 +4,72 @@ All notable changes to the LLM Security Plugin are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [7.3.1] - 2026-05-01
Stabilization patch. No behavior changes. Sets the public stance, tightens
documentation, and removes coherence drift so forkers and downstream
organizations get a consistent starting point.
### Added
- `CONTRIBUTING.md` — public fork-and-own guide. Explains why PRs are not
accepted on the upstream repo, how to fork well (rename plugin, change
security contact, preserve LICENSE, re-establish trust), what is welcome
via issues, and the bar for inline-diff suggestions the maintainer may
apply directly.
- `README.md` "Project scope" section — public statement of stabilization
mode (effective 2026-05-01) plus an out-of-scope table naming what is
fork-and-own territory: web dashboard, fleet policy server, runtime
prompt firewall, IDE LSP, compliance PDF/DOCX pack, enterprise ticketing
connectors, multi-tenancy, ML-based detectors, marketplace UI,
SSO/SCIM/RBAC. Each row points at the commercial alternative
(Snyk, Lakera, Vanta, Splunk SOAR, parry-guard, etc.).
- `package.json`: `bugs.url` field, `CONTRIBUTING.md` / `SECURITY.md` /
`CHANGELOG.md` added to the `files` whitelist so npm-published artifacts
ship with full project documentation.
### Changed
- `SECURITY.md` rewritten. Supported-versions table moves from `5.1.x`
(stale since v6.0.0) to current reality: 7.3.x active, 7.07.2 best-effort,
< 7.0 EOL. Adds explicit best-effort solo-project response timeline (7
days ack, 14 days triage, 30 days fix for High/Critical), expands scope
list to cover `bin/llm-security.mjs`, and notes that out-of-scope
vulnerabilities (e.g., adaptive ML-based bypass) get an explanatory
response rather than silent ignore.
- `README.md` "Feedback & contributing" section now links to
`CONTRIBUTING.md` and the new "Project scope" section.
- `package.json` `repository.url` corrected from
`fromaitochitta/claude-code-llm-security` to
`open/claude-code-llm-security` (matches `homepage` and the canonical
Forgejo path).
- Scanner `VERSION` constants synced to plugin version. Previously
`dashboard-aggregator.mjs` and `posture-scanner.mjs` reported `6.0.0`
in scan output and SARIF, mismatching the actual plugin version.
All three standalone scanners (`dashboard-aggregator`, `posture-scanner`,
`ide-extension-scanner`) now report `7.3.1`.
### Fixed
- `tests/hooks/pre-compact-scan.test.mjs` size-cap timing test ceiling
raised from 500 ms to 1000 ms. The 500 ms hard cap was a flake source
on Intel Mac and CI runners under load, while the design target
(documented in `CLAUDE.md`) remains <500 ms. The test now catches
order-of-magnitude regressions without breaking on hardware/CI noise.
### Notes
- This is the first patch on the stabilization line. Future 7.3.x
releases will be limited to bug + security fixes and small
knowledge-base refreshes that fit the existing deterministic
architecture. v8.0.0 remains scheduled as the deprecation cleanup
for the env vars and `riskScoreV1` constant deprecated in v7.3.0;
see "Project scope" in `README.md` for the longer-term direction.
- Wave E (additional attack-simulator scenarios mentioned in the v7.3.0
changelog as "deferred to v7.3.1") is now deferred indefinitely.
Coverage remains at 72 scenarios. Forkers who want broader red-team
coverage are encouraged to extend `knowledge/attack-scenarios.json`.
## [7.3.0] - 2026-05-01
Batch C release. Closes 12 implementation tasks (E3, E8-E14, 8.4, 8.6,

View file

@ -1,4 +1,4 @@
# LLM Security Plugin (v7.3.0)
# LLM Security Plugin (v7.3.1)
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). 1777+ unit and integration tests; mutation-testing coverage not published.

View file

@ -0,0 +1,161 @@
# Contributing
Thanks for the interest. This document is the honest answer to "how do I
contribute?" — and the answer is mostly *fork and own*. Read on.
---
## TL;DR
| You want to … | Do this |
|---------------|---------|
| Report a bug | Open an issue on Forgejo |
| Ask a question | Open an issue on Forgejo |
| Suggest a small fix | Open an issue with the diff inline; the maintainer may apply it |
| Propose a new scanner / hook / command | Open an issue first; expect "fork & own" for anything beyond stabilization |
| Build enterprise features (dashboards, fleet policy, runtime firewall, IDE LSP, compliance pack, ticketing connectors) | **Fork the repo. Build it. Ship it under your own name.** This is encouraged. |
| Report a security vulnerability | See [`SECURITY.md`](SECURITY.md) — **do not open a public issue** |
---
## Why this project does not accept pull requests
This is a solo open-source project, MIT-licensed, maintained alongside a
day job by one person. Accepting PRs sounds nice but in practice creates
problems the maintainer cannot solve sustainably:
- **Review cost.** Every PR needs careful security review (this is a
*security* plugin — a malicious PR is the literal threat model). Solo
capacity does not scale to that.
- **Maintenance burden.** Merged code becomes the maintainer's
responsibility forever. Every contributed scanner is one more thing to
test, port across Claude Code versions, and keep current.
- **Direction control.** The project has a deliberate scope (see README
"Project scope"). PRs that expand scope force a "no, sorry" that is
worse for the contributor than "fork it and ship your version."
The MIT license already gives you everything you need to take the code in
any direction. Use it.
---
## Issues are welcome
Open issues for:
- **Bugs** — reproducer, expected vs actual behavior, plugin version
(`cat .claude-plugin/plugin.json`), Claude Code version, OS
- **False positives** — minimal example that triggers a finding that
shouldn't fire, plus the `.llm-security-ignore` rule you ended up using
(or "no clean way to suppress" — that's useful signal)
- **False negatives** — known attack pattern that *should* trigger a
finding but doesn't. Cite the OWASP / research source if you have one.
- **Documentation gaps** — places where the README, hardening guide, or
threat model is wrong, stale, or missing
- **Compatibility regressions** — Claude Code version X stopped working
Issues are tracked on the canonical Forgejo repo:
`https://git.fromaitochitta.com/open/claude-code-llm-security`
The maintainer reads them. Response is best-effort, not real-time.
---
## Forking — the recommended path
If you have feature ideas larger than a paragraph, **fork the repo**. The
MIT license permits it, this contributing guide encourages it, and the
project is intentionally architected so a fork can diverge cleanly.
### What forking gives you
- Full ownership of direction, release cadence, and roadmap
- Freedom to add enterprise features that this project will never accept
(web dashboard, fleet policy server, runtime firewall, IDE LSP scanner,
compliance PDF generator, Jira/ServiceNow/Slack/PagerDuty integrations,
multi-tenancy, ML-based detectors, marketplace UI, central audit
storage, SSO/SCIM, RBAC)
- Ability to charge for it. MIT does not require attribution beyond
preserving the LICENSE file in source distributions.
### How to fork well
1. **Clone, don't subtree.** Copy `plugins/llm-security/` into a fresh
repo. Keep the LICENSE file. Keep the SECURITY.md (or replace with
your own — but **change the contact address**).
2. **Rename the plugin.** Update `.claude-plugin/plugin.json` `name`,
`description`, and `repository`. Update the `bin` entry in
`package.json` if you publish to npm. **Do not ship a plugin called
`llm-security` from a fork** — it confuses users and breaks issue
triage upstream.
3. **Decide your knowledge-base policy.** The `knowledge/` directory
cites OWASP, DeepMind, Pillar, ToxicSkills, and other published
research. Citations belong to the original sources, not to this
project. Keep them.
4. **Run the self-scan.** `node scanners/scan-orchestrator.mjs .` should
produce 0 findings on a healthy fork — the `.llm-security-ignore`
rules are documented and reasoned. If your fork triggers new findings,
resolve them or document the suppression.
5. **Re-establish trust.** A fork is a new project. Document who you are,
what your release cadence is, what your security disclosure process is
(don't reuse `security@fromaitochitta.com` — that mailbox routes to
the original maintainer).
6. **Track upstream loosely.** When a security fix lands here, port it.
When a feature lands here, decide if it fits your direction. Diverge
on purpose.
### What not to do when forking
- **Do not rebrand and silently republish under the same name.** It
breaks downstream trust.
- **Do not strip the LICENSE.** MIT requires you preserve it.
- **Do not represent your fork as the upstream project.** "Fork of
llm-security by Kjell Tore Guttormsen, maintained by [you]" is the
honest framing.
---
## Small fixes the maintainer may apply
For tiny corrections — a typo, a broken link, a clearly wrong regex, a
missing entry in a blocklist — open an issue with the proposed change
inline. The maintainer may apply it directly. Credit goes in the commit
message.
This is not a back-door for PRs. It is a pragmatic shortcut for changes
that take less time to apply than to review.
---
## Development setup (for forkers)
```bash
git clone <your-fork-url>
cd <your-fork>
npm install # zero runtime deps; this only installs node:test for testing
npm test # 1777+ tests at v7.3.0
npm run lint # if your fork adds a linter
```
Tests live in `tests/`. The shape is `tests/<area>/<file>.test.mjs` using
Node's built-in `node:test`. No Jest, no Vitest, no Mocha. The dependency
budget is intentionally zero for hooks and scanners.
For details on architecture, see [`CLAUDE.md`](CLAUDE.md) — that file is
the authoritative architecture overview.
---
## Code of conduct
Be respectful. The maintainer reserves the right to close issues that are
abusive, off-topic, or in bad faith. There is no separate Code of Conduct
document because there is no community process to govern; this is a solo
project with an issue tracker.
---
## License
[MIT](LICENSE). All contributions submitted via issues — including
inline-diff suggestions — are accepted under the same license.

View file

@ -6,7 +6,7 @@
*AI-generated: all code produced by Claude Code through dialog-driven development. [Full disclosure →](../../README.md#ai-generated-code-disclosure)*
![Version](https://img.shields.io/badge/version-7.3.0-blue)
![Version](https://img.shields.io/badge/version-7.3.1-blue)
![Platform](https://img.shields.io/badge/platform-Claude_Code_Plugin-purple)
![Commands](https://img.shields.io/badge/commands-20-orange)
![Agents](https://img.shields.io/badge/agents-6-orange)
@ -421,6 +421,43 @@ These gaps are surfaced advisorily through `/security threat-model` and `/securi
---
## Project scope
This is a **solo open-source project in stabilization mode** as of 2026-05-01.
The current feature set (5 frameworks, 23 scanners, 9 hooks, 6 agents,
20 commands, 22 knowledge files, 1777+ tests) is the natural plateau for
what a deterministic + advisory plugin can defend against without crossing
into commercial-grade territory. Going forward, work focuses on:
- **Bug fixes** and security patches
- **Compatibility** with new Claude Code releases
- **Knowledge-base refresh** (OWASP updates, new published research, new attack patterns)
- **Deprecation cleanup** — v8.0.0 removes the `LLM_SECURITY_*` env vars and `riskScoreV1` constant deprecated in v7.3.0
- **Opportunistic small additions** that fit the existing deterministic architecture
The following are **explicitly out of scope — fork the repo and own them**
under your organization's name. The MIT license permits this and the project
is architected to be forkable. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for
the fork-and-own guide.
| Out of scope | Why | Where to look instead |
|--------------|-----|------------------------|
| Web dashboard / fleet policy server | Multi-tenant UX + ongoing infra work | Snyk, Lakera Cloud |
| Runtime prompt firewall (real-time blocking proxy) | Inline gateway architecture | Lakera Guard, Protect AI Rebuff, [parry-guard](https://github.com/vaporif/parry) |
| IDE real-time LSP scanning | IDE integration + always-on perf budget | Snyk IDE, Semgrep IDE |
| Compliance PDF/DOCX evidence pack | Auditor-formatted reports as a product | Vanta, Drata, Secureframe |
| Enterprise ticketing / chat connectors (Jira, ServiceNow, Slack, Teams, PagerDuty) | Per-vendor SDK + auth + ongoing API drift | Splunk SOAR, Tines, custom integration |
| Multi-tenancy / centralized plugin runtime / fleet state | Hosted-product surface area | Build it on a fork |
| ML-based detectors requiring model hosting | Model-serving infra (training, eval, drift) | parry-guard (DeBERTa v3 + Llama Prompt Guard 2) |
| Marketplace UI / web catalog | Frontend product | This is not that kind of project |
| SSO / SCIM / RBAC | Platform-level enterprise concerns | Anthropic Admin Console + your IdP |
If you need any of the above and your organization has the headcount to
maintain it, **fork freely**. The maintainer encourages it. Issues and
support flow back to the fork, not here.
---
## Defense philosophy
Prompt injection is **structurally unsolvable** with current architectures (joint paper, 14 researchers, 2025: 95-100 % ASR against all 12 tested defenses by motivated red-teamers). v5.0+ does not claim to "prevent" injection. It implements defense-in-depth:
@ -463,7 +500,8 @@ node scanners/scan-orchestrator.mjs examples/malicious-skill-demo/evil-project-h
| Version | Date | Highlights |
|---------|------|------------|
| **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 (9 new attack-simulator scenarios) deferred to v7.3.1 |
| **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.0v7.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 |
| **7.2.0** | 2026-04-29 | **Batch B release.** Critical-review B-tier scanner defects + v7.2.0 evasion-arsenal (PUA-A/B Unicode coverage, NFKC homoglyph fold, escalation-after-input window, markdown link-title + SVG `<desc>`/`<foreignObject>` + HTML comment extractors). Two-stage entropy context classification. v1→v2 risk-formula constants unified across docs. 8 new red-team scenarios (64 → 72). 1522 → 1665 tests |
| **7.1.0** | 2026-04-29 | **Critical-review patch.** Pathguard regex hole closed (`.env.production.local.backup`-class). Distributed-trifecta block-mode AND-gate removed. CaMeL claim toned down to honest "byte-fingerprint matching". Documentation honesty-sweep across 7 overclaim sites. 1487 → 1511 tests |
@ -481,4 +519,11 @@ Built on published research from OWASP, ToxicSkills (Xi'an Jiaotong, 2025), Claw
## Feedback & contributing
Bug reports and feature requests: open an issue. Pull requests are not accepted on this repo (solo project, dialog-driven development with Claude Code). Security disclosures: see [`SECURITY.md`](SECURITY.md).
- **Bug reports + feature requests:** open an issue on Forgejo
- **Pull requests:** not accepted on this repo (solo project, dialog-driven
development with Claude Code). For larger changes, see
[`CONTRIBUTING.md`](CONTRIBUTING.md) and the **fork-and-own** model
- **Security disclosures:** see [`SECURITY.md`](SECURITY.md) — please email,
do not open a public issue
- **Project scope:** see "Project scope" section above for what is and
isn't on the roadmap, and what to fork for instead

View file

@ -1,15 +1,26 @@
# Security Policy
## Supported Versions
## Supported versions
| Version | Supported |
|---------|-----------|
| 5.1.x | Yes |
| < 5.0 | No |
This is a solo-maintained open-source project. "Supported" here means the
maintainer will look at security reports — not that there is an SLA, paid
support, or backporting policy. Forks are encouraged for organizations that
need stronger guarantees (see [`CONTRIBUTING.md`](CONTRIBUTING.md)).
## Reporting a Vulnerability
| Version | Status |
|---------------|------------------------------------------------|
| 7.3.x | **Active.** Bug + security fixes. Stabilization line. |
| 7.0.x 7.2.x | Best-effort security fixes only. Upgrade to 7.3.x recommended. |
| < 7.0 | End of life. No fixes. |
If you discover a security vulnerability in this plugin, please report it responsibly.
The project is in **stabilization mode** as of 2026-05-01. New features are
out of scope (see "Project scope" in [`README.md`](README.md)). Security and
correctness fixes continue.
## Reporting a vulnerability
If you discover a security vulnerability in this plugin, please report it
responsibly.
**Do NOT open a public issue.** Instead:
@ -17,28 +28,43 @@ If you discover a security vulnerability in this plugin, please report it respon
2. Include:
- Description of the vulnerability
- Steps to reproduce
- Affected component (scanner, hook, agent, etc.)
- Affected component (scanner, hook, agent, command, knowledge file)
- Potential impact
- Whether you have a proof-of-concept (encrypted attachment is fine)
**Response timeline:**
- Acknowledgment within 48 hours
- Assessment within 7 days
- Fix or mitigation within 30 days for confirmed vulnerabilities
**Response timeline (best-effort, solo project):**
- Acknowledgment within 7 days
- Triage and severity classification within 14 days
- Fix or documented mitigation within 30 days for confirmed High/Critical findings; Medium and Low scheduled into the next regular release
If the report touches a vulnerability the project explicitly cannot defend
against (see "Defense philosophy" and "What this plugin does NOT cover" in
the README — e.g., adaptive ML-based prompt injection bypass), the response
will explain why it is out of scope rather than leaving the report open.
## Scope
This policy covers:
- Hook scripts (`hooks/scripts/*.mjs`)
- Deterministic scanners (`scanners/*.mjs`)
- Scanner shared library (`scanners/lib/*.mjs`)
- Agent definitions (`agents/*.md`)
- Command definitions (`commands/*.md`)
- CLI entry point (`bin/llm-security.mjs`)
Out of scope:
- The malicious-skill-demo fixture (intentionally vulnerable for testing)
- Knowledge base content (derived from published OWASP standards)
- Template files (output formatting only)
- The malicious-skill-demo fixture (`examples/malicious-skill-demo/`) — intentionally vulnerable for testing
- Knowledge base content (derived from published OWASP standards and cited research)
- Template files (output formatting only, not part of the security boundary)
- Forks under other names — please report there, not here
## Disclosure
Confirmed vulnerabilities will be disclosed after a fix is available, with credit to the reporter unless anonymity is requested.
Confirmed vulnerabilities will be disclosed in the CHANGELOG after a fix is
available, with credit to the reporter unless anonymity is requested.
For coordinated disclosure with downstream forks: include the maintainer
email above and the maintainer of the fork in the same thread.

View file

@ -1,6 +1,6 @@
{
"name": "llm-security",
"version": "7.3.0",
"version": "7.3.1",
"description": "Security scanning, auditing, and threat modeling for Claude Code projects",
"type": "module",
"bin": {
@ -10,7 +10,10 @@
"bin/",
"scanners/",
"LICENSE",
"README.md"
"README.md",
"CONTRIBUTING.md",
"SECURITY.md",
"CHANGELOG.md"
],
"homepage": "https://git.fromaitochitta.com/open/claude-code-llm-security",
"engines": {
@ -31,6 +34,9 @@
"license": "MIT",
"repository": {
"type": "git",
"url": "https://git.fromaitochitta.com/fromaitochitta/claude-code-llm-security"
"url": "https://git.fromaitochitta.com/open/claude-code-llm-security"
},
"bugs": {
"url": "https://git.fromaitochitta.com/open/claude-code-llm-security/issues"
}
}

View file

@ -19,7 +19,7 @@ import { scan } from './posture-scanner.mjs';
// Constants
// ---------------------------------------------------------------------------
const VERSION = '6.0.0';
const VERSION = '7.3.1';
/** Cache location */
const CACHE_DIR = join(homedir(), '.cache', 'llm-security');

View file

@ -49,7 +49,7 @@ import { scan as scanTaint } from './taint-tracer.mjs';
import { scan as scanMemoryPoisoning } from './memory-poisoning-scanner.mjs';
import { scan as scanSupplyChain } from './supply-chain-recheck.mjs';
const VERSION = '7.3.0';
const VERSION = '7.3.1';
const SCANNER = 'IDE';
// ---------------------------------------------------------------------------

View file

@ -20,7 +20,7 @@ import { finding, scannerResult, resetCounter } from './lib/output.mjs';
// Constants
// ---------------------------------------------------------------------------
const VERSION = '6.0.0';
const VERSION = '7.3.1';
/** Minimum lines for a hook script to be considered non-stub */
const NON_STUB_THRESHOLD = 5;

View file

@ -98,12 +98,14 @@ describe('pre-compact-scan hook', () => {
assert.equal(parseOutput(r.stdout), null);
});
it('size-cap: ~1MB transcript completes under 500 ms', async () => {
it('size-cap: ~1MB transcript completes under 1000 ms', async () => {
const start = process.hrtime.bigint();
const r = await runHookWithEnv(SCRIPT, payload(LARGE), { LLM_SECURITY_PRECOMPACT_MODE: 'warn' });
const elapsedMs = Number(process.hrtime.bigint() - start) / 1e6;
assert.equal(r.code, 0, 'hook should not fail on large transcript');
assert.ok(elapsedMs < 500, `expected <500 ms, got ${elapsedMs.toFixed(1)} ms`);
// Design target is <500 ms (see CLAUDE.md). Test ceiling is 2x to absorb
// hardware/CI noise without going silent on order-of-magnitude regressions.
assert.ok(elapsedMs < 1000, `expected <1000 ms ceiling, got ${elapsedMs.toFixed(1)} ms`);
});
it('credential pattern in transcript is detected in warn mode', async () => {