feat(signatures): add the malware identity table, drawn from source not memory

The last missing data file. Seven known-bad-identity signatures over four
families - webshell, reverse_shell, cryptominer, hacktool - reproduced
verbatim from llm-security/knowledge/signatures.json at b0de0ca, key order
included. The file was generated from the parsed source rather than typed,
and provenance pins the source's byte length (2494) and SHA-256 so the
claim is checkable rather than asserted.

Note the family spellings: reverse_shell with an underscore, and
cryptominer rather than miner. The working note this file was planned from
had both wrong. They are policy keys - the engine filters on them and
interpolates them into every finding title - so a rename is a breaking
change, which is exactly why the table was read instead of recalled.

The rules were the easy half. The substance is engine_behaviour_not_data,
which draws the line between the table and the runtime around it. No rule
carries a flags field, because the engine compiles every pattern with `i`
unconditionally at signature-scanner.mjs:48 - so a consumer compiling these
case-sensitively silently under-matches all seven, and the dialect block
records that where a reader will hit it. Also engine, not data: matching
against five decode variants rather than raw bytes, the enabled-families
policy filter, per-file rule dedup, custom-rule merging, and a loader that
defaults four missing fields instead of rejecting a rule.

Two limits are stated as evidence limits rather than left implied. Seven
signatures are not malware coverage; a clean SIG result is not "no
malware", and the seed runtime's own header calls the table deliberately
tight. And three of the seven match on names - xmrig, mimikatz,
meterpreter - so a document discussing those tools matches. The seed
runtime hides that by excluding knowledge/, tests/, docs/ and
node_modules/, which is scan scoping and does not travel with the table.

Verified: 7/7 rule objects field-identical to source including key order,
no non-ASCII bytes, all seven compile in Node bare, i and iu (21/21) and in
Python re (7/7). Charter guard clean - no executable code in the repository.

README and CHANGELOG updated: the file moves out of "planned, not in
v0.1.0" and out of "not included".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SNMcqrfNyoLRQ7qXUFZnb9
This commit is contained in:
Kjell Tore Guttormsen 2026-08-09 22:49:21 +02:00
commit 47760d2264
3 changed files with 204 additions and 3 deletions

View file

@ -32,6 +32,31 @@ change. **Not yet tagged** — see *Not included* below.
16-prefix key set.
- `calibration/calibration.json` — risk-score tier constants, verdict thresholds, risk-band
cutoffs, posture grade thresholds.
- `signatures/malware-signatures.json` — the known-bad-identity table for the `SIG` class:
seven signatures over four families (`webshell`, `reverse_shell`, `cryptominer`,
`hacktool`), reproduced verbatim from `knowledge/signatures.json` at `b0de0ca`, key order
included, with the source file's byte length and SHA-256 pinned in `provenance`.
The rules were the easy half. The file's substance is the line between the table and the
engine, drawn in `engine_behaviour_not_data`: **no rule carries a `flags` field**, because
the engine compiles every pattern with `i` unconditionally — so a consumer that compiles
these case-sensitively silently under-matches all seven. Each pattern is also run against
five decode variants, not just raw bytes; rules are filtered by an enabled-families policy;
a rule fires once per file; operator rules are merged at scan time; and the loader defaults
four missing fields rather than rejecting a rule. None of that travels with the data, and
all of it changes what a consumer sees.
Two honesty notes are in `evidence_limits` rather than in prose. Seven signatures are not
malware coverage — a clean `SIG` result is not "no malware", and the seed runtime's own
header calls the table "deliberately tight". And three of the seven match on **names**
(`xmrig`, `mimikatz`, `meterpreter`), so a document *discussing* those tools matches; the
seed runtime papers over this by excluding `knowledge/`, `tests/`, `docs/` and
`node_modules/` from the scan, which is engine behaviour and does not come with the table.
Verified: 7/7 rule objects field-identical to source including key order, no non-ASCII
bytes, and all seven compile in Node bare, `i` and `iu` (21/21) and in Python `re` (7/7).
Note the exact family spellings — `reverse_shell`, not `reverse-shell`, and `cryptominer`,
not `miner`; they are policy keys, and the working note that seeded this file had both wrong.
### Verification
@ -186,7 +211,6 @@ checks that were not run instead of attaching a caveat to a pass.
### Not included
- `signatures/malware-signatures.json` — seed data not yet delivered.
- `spec/decode-pipeline.md` — needs the decode implementation. A normative spec inferred
from a data dump would be worse than an absent one.
- `conformance/` — still absent, with half the blocker cleared. 105 of the guard's 134