Skip to content

Commit 012062e

Browse files
authored
PR-16 (hand-off): Benchmark methodology + announcement drafts (#45)
* docs(scanner): benchmark methodology + announcement drafts (PR-16 hand-off) Prepares the agent-authored parts of PR-16; benchmark execution/labeling and the scanner-v0.4.0 release remain maintainer tasks (hard gate). - docs/BENCHMARK.md: corpus selection, deterministic run steps, a labeling-sheet template, a per-rule precision snippet, and the responsible-disclosure rule (never publish an unresolved live finding — follow SECURITY.md first). - docs/ANNOUNCEMENT-DRAFTS.md: Slack, mailing-list, call-for-scan-reports, lightning-talk abstract. - ROADMAP: Phases 1-3 complete (scanner-v0.3.0 shipped); Phase 4 gated items flagged. * fix(scanner): use a real path for the issue-templates link (PR-16)
1 parent de81958 commit 012062e

4 files changed

Lines changed: 167 additions & 14 deletions

File tree

dsgai_scanner_tool/CHANGES_v0.3.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ dates are ISO-8601. The previous line is recorded in [`CHANGES_v0.2.md`](CHANGES
99
## [Unreleased]
1010

1111
### Added
12+
- **Benchmark methodology + announcement drafts** (PR-16 hand-off). `docs/BENCHMARK.md`
13+
(corpus selection, deterministic run steps, a labeling-sheet template, a per-rule
14+
precision snippet, and the responsible-disclosure rule for live findings) and
15+
`docs/ANNOUNCEMENT-DRAFTS.md` (Slack / mailing-list / call-for-reports / lightning-talk).
16+
The benchmark **execution + labeling** and the `scanner-v0.4.0` release remain
17+
maintainer tasks.
1218
- **Ecosystem expansion + rule-pack export** (PR-15).
1319
- **C# / Rust / Ruby**: detection signals (Semantic Kernel/Azure.AI.OpenAI, async-openai,
1420
ruby-openai); CVE manifest parsing for **NuGet** (`*.csproj`), **crates.io**

dsgai_scanner_tool/ROADMAP.md

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
This is the public roadmap for the DSGAI scanner. It turns the internal improvement
44
plan into work anyone can pick up.
55

6+
> **Status (v0.3 shipped):** Phases 1–3 are complete and released as `scanner-v0.3.0`. Phase 4 is in progress — templating, ecosystems, and the Semgrep export have landed; the **license split** (needs OWASP leadership sign-off) and the **precision benchmark** (needs maintainer labeling) are the remaining gated items.
7+
68
> **Want one of these? Comment on the tracking issue and claim it.** Each unstarted
79
> item below links to a GitHub issue. Rule and precision work is labelled
810
> `blocked-on-phase-1` until the test corpus and self-test CI land — you can draft it
@@ -16,49 +18,49 @@ A compliance report that changes run-to-run on identical input is an opinion, no
1618
evidence. This phase makes pattern matching deterministic and testable, so everything
1719
after it is verifiable.
1820

19-
- **Rules as data** — extract every detection pattern into `rules/dsgai-rules.yaml`
21+
- **Rules as data** — extract every detection pattern into `rules/dsgai-rules.yaml`
2022
with a JSON Schema, so rules are reviewable data instead of prose.
21-
- **Fixture app + known-answer sheet** — a small, intentionally vulnerable
23+
- **Fixture app + known-answer sheet** — a small, intentionally vulnerable
2224
multi-language GenAI app that is the test corpus, the demo, and the contributor
2325
on-ramp.
24-
- **Deterministic runner** — a stdlib Python CLI that runs the rules via ripgrep and
26+
- **Deterministic runner** — a stdlib Python CLI that runs the rules via ripgrep and
2527
emits findings JSON + SARIF, identically every run.
26-
- **Checkpoint schema + self-test CI** — a formal, redaction-checkable output schema
28+
- **Checkpoint schema + self-test CI** — a formal, redaction-checkable output schema
2729
and the CI gate that makes external rule PRs safe to merge.
2830

2931
## Phase 2 — Secure the pipeline itself
3032

3133
A security scanner that is itself a prompt-injection vector or a secret-leak channel is
3234
a liability. This phase closes those.
3335

34-
- **Skill rewrite** — the LLM becomes the orchestrator; the deterministic engine owns
36+
- **Skill rewrite** — the LLM becomes the orchestrator; the deterministic engine owns
3537
pattern matching. Adds an untrusted-content trust preamble, structural secret
3638
redaction, stable file IDs, and honest language about what the report guarantees.
37-
- **Harden the GitHub Action** — split scanning (no secrets, runs on forks) from
39+
- **Harden the GitHub Action** — split scanning (no secrets, runs on forks) from
3840
narration (restricted tools), pin actions by SHA, and fix the push-gate behaviour.
39-
- **README truth pass + lighter sample image** — every claim matches reality; the
41+
- **README truth pass + lighter sample image** — every claim matches reality; the
4042
~5 MB sample screenshot is replaced with a small one from the public fixture app.
41-
- **Pre-commit: gitleaks rule pack** — ship a battle-tested gitleaks pack, keep a
43+
- **Pre-commit: gitleaks rule pack** — ship a battle-tested gitleaks pack, keep a
4244
portable no-dependency fallback script.
4345

4446
## Phase 3 — Precision
4547

46-
- **Pattern precision wave 1** — fix confirmed false positives/negatives (unquoted
48+
- **Pattern precision wave 1** — fix confirmed false positives/negatives (unquoted
4749
`.env` keys, the innocent-webhook SQL false positive), add per-rule confidence levels.
48-
- **CVE pipeline rework** — move CVE fetching into the CLI (no hallucinated CVEs),
50+
- **CVE pipeline rework** — move CVE fetching into the CLI (no hallucinated CVEs),
4951
add caching, inline suppressions with reasons, a baseline for CI gating, and
5052
incremental `--diff` scans.
5153

5254
## Phase 4 — Professional polish
5355

54-
- **License split + SPDX headers** — content stays CC BY-SA 4.0; executable code
56+
- 🚧 **License split + SPDX headers** — content stays CC BY-SA 4.0; executable code
5557
moves to Apache-2.0 (pending OWASP leadership sign-off).
56-
- **Single-source variants + templated report + static ATLAS map** — generate the
58+
- **Single-source variants + templated report + static ATLAS map** — generate the
5759
tool-neutral prompt variant from the skill, render reports deterministically from a
5860
template, and ship a static MITRE ATLAS technique map.
59-
- **Ecosystem expansion** — C#/NuGet, Rust, Ruby coverage, plus Semgrep and gitleaks
61+
- **Ecosystem expansion** — C#/NuGet, Rust, Ruby coverage, plus Semgrep and gitleaks
6062
rule-pack exports so incumbent toolchains carry the DSGAI framework.
61-
- **Benchmark + published precision report** — run against public GenAI repos,
63+
- 🚧 **Benchmark + published precision report** — run against public GenAI repos,
6264
hand-label, and publish per-rule precision. This is what separates "interesting
6365
project" from "tool AppSec teams adopt".
6466

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# DSGAI Scanner v0.3 — announcement drafts
2+
3+
> **Hand-off: the agent drafts, the maintainer posts.** Review, adjust the links
4+
> (fill the `<...>` placeholders), and post. All four items are optional but the
5+
> "call for scan reports" doubles as contributor recruitment + the benchmark
6+
> dataset.
7+
8+
## 1. OWASP GenAI Slack post
9+
10+
> 🛡️ **DSGAI Scanner v0.3 is out.** The OWASP DSGAI compliance scanner now has a
11+
> **deterministic engine** — a stdlib Python CLI runs the 21-control ruleset via
12+
> ripgrep and emits reproducible findings + SARIF (GitHub Code Scanning), while
13+
> the Claude Code skill orchestrates and writes the report. Highlights: rules as
14+
> data (107 patterns), a public vulnerable-fixture test corpus with CI, secrets
15+
> that never leave ripgrep (structural redaction), a hardened two-job Action
16+
> (safe on fork PRs), a gitleaks pre-commit pack, and a Semgrep export so your
17+
> existing toolchain can carry the framework. **Found a wrong result? That's a
18+
> contribution** — file an FP/FN issue and it becomes a permanent test case.
19+
> Repo: <link to dsgai_scanner_tool/> · Release: <scanner-v0.3.0 link>
20+
21+
## 2. Initiative mailing list
22+
23+
> Subject: DSGAI Scanner v0.3 — deterministic engine, CI-gated, ecosystem support
24+
>
25+
> The DSGAI scanner reached v0.3. The headline change is architectural: pattern
26+
> matching is now deterministic and reproducible (a compliance report that
27+
> changes run-to-run is an opinion, not evidence), owned by a single-file
28+
> stdlib CLI; the LLM's job is orchestration, judgment, and prose. We added a
29+
> public test corpus + self-test CI (so external rule PRs are safe to merge),
30+
> structural secret redaction, a hardened GitHub Action, a gitleaks pack, CVE
31+
> enrichment with no hallucination risk, and C#/Rust/Ruby coverage plus a Semgrep
32+
> export. Full changelog: <CHANGES_v0.3 link>. We'd love scan reports (below).
33+
34+
## 3. Call for scan reports (recruits contributors + builds the benchmark)
35+
36+
> **Run the DSGAI scanner on your GenAI repo and tell us what it got wrong.**
37+
> `python cli/dsgai_scan.py scan .` ($0, no LLM) or the Claude Code skill. Every
38+
> false-positive / false-negative you file with the
39+
> [issue templates](../../.github/ISSUE_TEMPLATE/) becomes a permanent, credited test case —
40+
> and feeds the precision benchmark. Recurring contributors are invited as
41+
> co-maintainers. No code required to help.
42+
43+
## 4. Lightning-talk abstract (AppSec Global / regional CFP, ~10 min)
44+
45+
> **Title:** A deterministic compliance scanner for GenAI apps — and why the LLM
46+
> shouldn't do the matching
47+
>
48+
> **Abstract:** GenAI apps leak secrets, execute model-generated SQL, and skip
49+
> tenant isolation in ways generic SAST misses. We built an OWASP DSGAI 2026
50+
> compliance scanner and learned the hard way that letting an LLM do the pattern
51+
> matching produces reports that change run-to-run. v0.3 splits the concern: a
52+
> tiny deterministic engine owns matching (reproducible, redaction-guaranteed by
53+
> construction — secrets never leave ripgrep); the model orchestrates and writes
54+
> prose, always citing evidence. Live demo: we scan an intentionally-vulnerable
55+
> fixture app, show the SARIF land in Code Scanning, and watch a prompt-injection
56+
> file in the repo have exactly zero effect on the result. 10 minutes, one scan,
57+
> a lot of opinions about trusting AI with security evidence.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# DSGAI Scanner — Precision Benchmark (methodology + labeling kit)
2+
3+
> **Status: HAND-OFF.** The finding sheets are prepared by tooling; the
4+
> **hand-labeling and the per-rule precision numbers are a maintainer task**
5+
> (they require human judgment and a responsible-disclosure decision). This file
6+
> is the methodology and the template — fill the `label:` and `notes:` columns,
7+
> then compute precision with the snippet below. **This document is what
8+
> separates "interesting project" from "tool AppSec teams adopt."**
9+
10+
## Responsible-handling rule (read first)
11+
12+
If the benchmark surfaces a **real, live vulnerability in a public repo**, do
13+
**not** publish that finding here. Follow the monorepo's
14+
[`SECURITY.md`](../../SECURITY.md) disclosure process first, and exclude the
15+
finding from the public sheet until it is resolved. The benchmark measures the
16+
*scanner's precision*, not a list of who is vulnerable.
17+
18+
## Candidate corpus (record exact commit SHAs)
19+
20+
Pick 5–10 public GenAI repos spanning frameworks and maturity. Suggested mix
21+
(confirm each is still representative before running):
22+
23+
- 2–3 popular **LangChain** example/starter apps.
24+
- 1–2 **LlamaIndex** example apps.
25+
- 1–2 production-grade OSS **agents** (e.g. an MCP server, a RAG service).
26+
- 1 **non-Python** GenAI service (JS/Go/C#) to exercise the ecosystem work.
27+
28+
For each: record `repo`, `commit_sha`, `scanned_at`, and the `ruleset_version`
29+
(from `DSGAI-scan.json`) so the run is reproducible.
30+
31+
## How to run (deterministic, $0)
32+
33+
```bash
34+
for repo in <list>; do
35+
git -C "$repo" rev-parse HEAD # record the SHA
36+
python cli/dsgai_scan.py scan "$repo" --no-cve \
37+
--json-out "bench/$(basename "$repo").json" --format none
38+
done
39+
```
40+
41+
Use `--no-cve` for the precision benchmark (CVE precision is measured separately
42+
against OSV ground truth). Merge the `findings` arrays into the labeling sheet.
43+
44+
## Labeling sheet template
45+
46+
One row per finding. Fill `label` (TP / FP) and `notes` by inspecting the file.
47+
48+
```yaml
49+
# bench/labels.yaml
50+
- repo: owner/name
51+
commit: <sha>
52+
rule_id: P02.1
53+
control: DSGAI02
54+
path: <path>
55+
line: <n>
56+
status: fail
57+
label: TP # TP (true positive) | FP (false positive)
58+
notes: "" # why; for value-bearing, DO NOT paste the secret
59+
```
60+
61+
## Per-rule precision (run after labeling)
62+
63+
```python
64+
import yaml, collections
65+
rows = yaml.safe_load(open("bench/labels.yaml"))
66+
by_rule = collections.defaultdict(lambda: [0, 0]) # rule -> [TP, FP]
67+
for r in rows:
68+
by_rule[r["rule_id"]][0 if r["label"] == "TP" else 1] += 1
69+
print(f"{'rule':8} {'TP':>4} {'FP':>4} {'precision':>10}")
70+
for rule, (tp, fp) in sorted(by_rule.items()):
71+
prec = tp / (tp + fp) if (tp + fp) else float("nan")
72+
print(f"{rule:8} {tp:>4} {fp:>4} {prec:>10.2f}")
73+
```
74+
75+
## Feeding results back
76+
77+
- For rules with low precision, **lower `confidence`** (or tighten the PCRE with a
78+
fixture case) in `rules/dsgai-rules.yaml` and note the change here.
79+
- Publish the aggregate table (per-rule TP/FP/precision) and the methodology.
80+
**Never** publish an unresolved live finding (see the responsible-handling rule).
81+
82+
## Results
83+
84+
_To be filled after labeling._
85+
86+
| Rule | TP | FP | Precision |
87+
|---|---|---|---|
88+
| _pending_ | | | |

0 commit comments

Comments
 (0)