dsh-defend red-team benchmark results

August 26, 2026 ยท View on GitHub

Deterministic scanner benchmark. Regenerate with node --experimental-strip-types benchmark/run.mjs (zero new dependencies; the scanner is the shipped src/detect source).

Method

  • Detector: buildScanner() โ€” NFKC normalization, the Aho-Corasick automaton over all needles, per-rule tolerant regexes, and the Shannon-entropy gate on secret matches (default minSecretEntropy: 3.0). Each category is scanned with only that category's family enabled, so a match is a per-category detection.
  • Detection = at least one match in the category's family.
  • Labels: label: true = an attack/secret of that category; label: false = benign or near-miss text (including low-entropy secret lookalikes for the entropy gate).

Per-category metrics

CategoryTPFPFNTNPrecisionRecallF1FPR
injection2500101.0001.0001.0000.000
jailbreak2500101.0001.0001.0000.000
secret221390.9570.8800.9170.100

Overall

AggregatePrecisionRecallF1
Macro (mean of the three categories)0.9860.9600.972
Micro (pooled TP/FP/FN across categories)0.9860.9600.973
  • Samples: 105 total (75 positive, 30 negative).
  • Micro false-positive rate: 0.033.

Per-sample notes

  • Missed positives (false negatives): secret/sec-pos-23, secret/sec-pos-24, secret/sec-pos-25.
  • Flagged negatives (false positives): secret/sec-neg-04.

Comparison with the documented floor (27/28)

The repository pins a detection-rate floor on the upstream Prompt-Attack-Dataset fixture (fixtures/attacks.json): 27 of 28 attacks detected (see README Known limitations and tests/detect.spec.ts). Re-running that fixture with this same scanner reproduces:

  • Detected: 27/28 (0.964).
  • Missed: en_004.

The one documented miss (en_004's lookalike Unicode) normalizes to "how to hack a system", which the rule library still has no needle/regex for. This benchmark's category split is stricter than the fixture: it adds per-category negatives (benign + low-entropy secret lookalikes) and evaluates F1, not just recall, so a high detection rate here is a stronger claim than the flat 27/28 recall.

Known limitations (honest)

  • Vocabulary-bound. Injection/jailbreak detection is only as broad as the ported rule library; novel phrasing and multi-step attacks can evade it.
  • Secret matching is structural. Regex + entropy gate; no checksum/liveness validation and no issuer round-trip, so a well-formed synthetic credential is flagged by design.
  • GitHub token subtypes. The secret vocabulary covers ghp_ and gho_ (plus github_pat_), not the ghs_/ghr_/ghu_ GitHub App/refresh/user tokens, so those positives are reported as false negatives.
  • aws-secret-key grammar not in the committed dataset. Its 40-character value is AWS-secret-shaped and GitHub push protection rejects committing such a literal, so that single grammar is exercised by a runtime test (tests/benchmark.spec.ts) instead of a dataset row. Every other secret grammar is measured here.
  • Entropy gate scores the whole regex match. found[0] includes the key name and separator, so password: <low-diversity-value> can clear the gate when the key name itself adds enough entropy (see sec-neg-04).
  • No model verdicts. The scanner is deterministic; it never judges intent.