Commit graph

56 commits

Author SHA1 Message Date
c3852c9148 feat(signatures): add secret-egress.json from verified llm-security dump
The 18 fixed credential and token shapes a pre-write guard matches before
content is persisted: cloud keys, vendor tokens, PEM blocks, connection
strings, JWTs.

Proven, not transcribed: the table was rebuilt from the commons JSON alone
and diffed against the imported dump module — 18/18 identical on name, source
and flags, and all 18 byte-identical, so no normalisation was needed. All 18
compile in Node bare, Node under `u`, and Python `re`.

Array order is normative and is tested as such, not merely asserted: a Bearer
header containing a JWT must be labelled "Authorization header with token"
rather than "JWT (three-part token)", which is why the source puts the bare
JWT entry last. Reproduced from the commons order, and shown to change under a
reversed table. Every entry carries an explicit `order` field so a JSON
round-trip cannot reorder the contract silently.

Corrects the extraction plan's seed-source row in the same commit: it named
knowledge/secrets-patterns.md, but the dump named hooks/scripts/
pre-edit-secrets.mjs and stated the two are different tables. Recording a
source file that was never delivered is the defect class this repository
already caught once in finding.schema.json.

Neither severity nor disposition was supplied, so neither is invented — the
source table carries a name and a pattern and nothing else. Verification log
in docs/extraction-plan.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FaYqid3mejFmd9ZHsiHgp3
2026-08-09 21:10:01 +02:00
f4aa8b66f4 feat(codepoints): add carriers.json from verified llm-security dump
Six independent carrier tables: zero-width characters (5), the Unicode Tags
block with its subtraction decode rule, the two Supplementary Private Use
Areas, BIDI controls (9, the Trojan Source class CVE-2021-42574), the
Cyrillic presence set (13), and the fold-to-Latin homoglyph map (28).

Proven, not transcribed: five of the six tables were rebuilt from the commons
JSON alone and diffed against the imported dump module — every constant
identical, and the homoglyph map identical down to insertion order. Folding a
corpus through the rebuilt table and the source table gives identical results.

The tables overlap but are NOT merged, and cross_table_notes states each
divergence as fact: the zero-width carrier set includes U+00AD while the
lexicon's pattern class does not; the lexicon class holds U+0456 which
CYRILLIC_CONFUSABLES lacks, and CYRILLIC_CONFUSABLES holds U+0445 which the
class lacks. Reporting that to llm-security, not fixing it here.

Two honest limits, marked in the file rather than smoothed over: the private
use ranges arrived as a source comment with no constant behind them and carry
verified: false, and the dump's own "~25 entries" estimate for the homoglyph
map is wrong — counted mechanically it is 28.

Character names resolved through Python unicodedata against the Unicode
character database, not written from recollection. Verification log in
docs/extraction-plan.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FaYqid3mejFmd9ZHsiHgp3
2026-08-09 21:08:01 +02:00
23cf3e383a feat(lexicon): add injection-lexicon.json from verified llm-security dump
The four prompt-injection pattern families — 21 critical, 32 high, 22 medium,
8 hybrid — with per-pattern label, ECMAScript source and declared flags.

Data only. The dump names checkCognitiveLoadTrap and scanForInjection's
variant building (normalise → fold → rot13 → unicode-tag escalation) as
ENGINE logic that never moves here; they are absent by intent, not omission.

Proven, not transcribed: all four arrays were rebuilt from the commons JSON
alone and diffed against the imported dump module — 83/83 identical on label,
source and flags, 81 of them byte-identical. All 83 compile in Node bare, Node
under `u`, and Python `re`.

Two deliberate deviations from byte-identity, declared in the file: the
zero-width and Cyrillic character classes carried raw code points, four of
them invisible. Escaped to \uXXXX (the convention forbids raw invisible code
points outside conformance inputs — an unreviewable class is where a silent
false negative hides) and proven equivalent by differential match-set
comparison over 208 adversarial inputs, 832 comparisons, 0 differences.
Class membership was counted from the dump bytes: the zero-width class holds
4 code points and does NOT include U+00AD.

HYBRID_PATTERNS' severity was not supplied and is left null rather than
inferred from its siblings. Verification log in docs/extraction-plan.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FaYqid3mejFmd9ZHsiHgp3
2026-08-09 21:05:15 +02:00
0433240b14 feat(schema): add finding.schema.json with normative SARIF profile
The finding contract plus the SARIF 2.1.0 output profile, modelled on
llm-security's sarif-formatter.mjs (operator dump). Draft 2020-12, valid
against the metaschema.

The SARIF profile is proven, not transcribed: the mapping was re-implemented
from the commons JSON alone and diffed against the real toSARIF over 10
envelope shapes (all severities incl. unknown/undefined, slug edge cases,
rule-id collision, every optional-field combination, multi-scanner, explicit
version) — 0 differences.

Three things left honest rather than closed:
- additionalProperties stays open. The formatter CONSUMES findings, so fields
  it ignores are invisible in this evidence; the property list is a lower
  bound until the producer is supplied.
- The JSONL profile is status=unspecified with a TODO. "One finding per line"
  is inference, and a guessed normative contract is worse than a missing one.
- Node and the Python guard share only severity+owasp; the rest of the field
  names diverge (scanner/title vs detector/label). Recorded as an open
  question for v0.2.0, not settled silently here.

One published claim was wrong and is corrected: rule-id collision does NOT
cover punctuation, only case and whitespace runs. Caught by executing the
claim instead of asserting it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0191AKc2qW6tmXDFSx1xn53q
2026-08-09 14:52:53 +02:00
43f682bedd feat(signatures): add active-content.json from verified guard source
The EchoLeak class (CVE-2025-32711): markdown image/link/refdef/autolink,
data: URIs and active HTML, plus the URL-shape analysis that separates a URL
naming a remote document from one carrying bytes outward.

Seeded from llm-ingestion-pipeline-security v0.3.4 @ 0bf0729 (read-only) —
active_content.py's pattern table and calibration.py's severities/floors.
That module documents itself as the canonical home of this table, which is
why the guard is the source here rather than llm-security.

One deliberate deviation from byte-identity, recorded in the file: five
patterns carried `\"` from Python raw strings, which is a SyntaxError under
ECMAScript's u/v flags. Normalised to `"` and proven equivalent by
differential match-set comparison (5 patterns x 30 adversarial inputs, 0
differences). Verification log in docs/extraction-plan.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0191AKc2qW6tmXDFSx1xn53q
2026-08-09 14:37:48 +02:00
ef80288c57 feat: initialize llm-security-commons (charter, license, extraction plan)
Data+contract+fixtures repository for runtime-neutral LLM/agent security
detection. Charter is hard: no engine code, no dependencies, no runtime —
JSON data, normative specs and conformance fixtures only.

Scaffolding only; the seed data files land in follow-up commits from
verified source dumps (never from recollection).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0191AKc2qW6tmXDFSx1xn53q
2026-08-09 14:29:16 +02:00