diff --git a/dsgai_scanner_tool/README.md b/dsgai_scanner_tool/README.md
index cbe4ca6..239ce78 100644
--- a/dsgai_scanner_tool/README.md
+++ b/dsgai_scanner_tool/README.md
@@ -1,455 +1,340 @@
-# GenAI Data Security Risks (DSGAI) Tool โ OWASP GenAI Data Security Compliance Report
+
-[](https://genai.owasp.org/initiative/data-security/)
-[](https://genai.owasp.org/resource/owasp-genai-data-security-risks-mitigations-2026/)
-[](./CHANGES_v0.3.md)
-[](https://creativecommons.org/licenses/by-sa/4.0/)
+# ๐ก๏ธ DSGAI Scanner
-Scans GenAI and agentic codebases against the **OWASP GenAI Data Security Risks and Mitigations 2026 (v1.0)** โ all 21 DSGAI risk controls across the GenAI data lifecycle. A **deterministic CLI** (`cli/dsgai_scan.py`) owns pattern matching so results are reproducible; the **Claude Code skill** orchestrates and writes the report. The report is **strict-by-default redacted** (file IDs + line numbers only, value-bearing matches never shown) โ designed to minimize disclosure. It is not automatically public-safe: the existence and location of failing controls is itself information, so handle it like any security assessment.
+**OWASP GenAI Data Security compliance scanning for AI & agentic codebases**
-Part of the [OWASP GenAI Data Security Initiative](https://genai.owasp.org/initiative/data-security/).
+Audits your GenAI app against all **21 controls** of the [OWASP GenAI Data Security Risks & Mitigations 2026](https://genai.owasp.org/resource/owasp-genai-data-security-risks-mitigations-2026/) framework. A **deterministic engine** owns the pattern matching, so results are reproducible and secrets never leave your machine โ the LLM only orchestrates and writes prose.
----
-
-## How It Works
-
-```mermaid
-flowchart LR
- Dev([Developer]) -->|/dsgai_scanner_tool| Skill[DSGAI Skill]
- Repo[(Your GenAI Repo)] --> Skill
+[](https://genai.owasp.org/initiative/data-security/)
+[](https://genai.owasp.org/resource/owasp-genai-data-security-risks-mitigations-2026/)
+[](./CHANGES_v0.3.md)
+[](../.github/workflows/scanner-selftest.yml)
+[](#cicd-and-code-scanning)
+[](#license)
- Skill --> Detect{Step 0
GenAI signals?}
- Detect -->|No| Minimal[Minimal report
21 ร NOT APPLICABLE]
- Detect -->|Yes| CVE[Step 0.5
Live CVE enrichment]
+[Quick start](#quick-start) ยท [How it works](#how-it-works) ยท [Features](#features) ยท [Usage](#usage) ยท [CI/CD](#cicd-and-code-scanning) ยท [The report](#the-report) ยท [Contributing](#contributing)
- CVE -.->|package + version
only| Sources((OSV ยท NVD
GitHub Advisory
AVID))
-
- CVE --> Scan[Step 2
21 parallel scans]
- Scan --> Class{Step 3
Classify}
- Class --> Report[DSGAI-report.html
self-contained
STRICT-redacted by default]
-
- Report --> Auditor([Auditor / GRC])
- Report --> Ticket([Jira / Backlog])
- Report --> CICD([CI/CD artifact])
-
- style Skill fill:#7c3aed,color:#fff
- style Report fill:#16a34a,color:#fff
- style Minimal fill:#6b7280,color:#fff
- style Sources fill:#e0e7ff,color:#1e1b4b
-```
-
-The whole thing runs on your local machine. Source code never leaves it โ only public package names + pinned versions go to public CVE databases (and only if you haven't passed `--no-cve`).
+
---
-## Quick Start (60 seconds)
+Most scanners either miss GenAI-specific risk (generic SAST) or hand the judgment to an LLM that produces a different answer every run. **DSGAI Scanner splits the job:** a single-file, dependency-free Python CLI (`cli/dsgai_scan.py`) runs 107 PCRE rules over your code via [ripgrep](https://github.com/BurntSushi/ripgrep) and emits identical findings every time; the [Claude Code](https://www.anthropic.com/claude-code) skill orchestrates the run, classifies ambiguous cases, and renders the report. You get a **reproducible compliance artifact** โ and, if you want it, a $0 LLM-free path that drops straight into CI as SARIF.
-```bash
-# 1. Install the skill into Claude Code
-curl -fsSL https://raw.githubusercontent.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/main/dsgai_scanner_tool/dsgai_scanner_tool.md \
- -o ~/.claude/commands/dsgai_scanner_tool.md # macOS/Linux
+
+Table of contents
-# 2. cd into your GenAI repo and launch Claude Code
-cd ~/my-genai-app
-claude
+- [Quick start](#quick-start)
+- [How it works](#how-it-works)
+- [Features](#features)
+- [The 21 DSGAI controls](#the-21-dsgai-controls)
+- [Usage](#usage)
+- [CI/CD & Code Scanning](#cicd-and-code-scanning)
+- [The report](#the-report)
+- [How redaction works](#how-redaction-works)
+- [Reference](#reference) โ checkpoint file ยท PDF export ยท scope annotation ยท remediation tiers
+- [Cost & runtime](#cost-and-runtime)
+- [Contributing](#contributing) ยท [Non-goals](#non-goals)
+- [License & attribution](#license)
-# 3. Run the scan (the skill prefers the deterministic CLI if bundled)
-/dsgai_scanner_tool
+
-# 4. Open the timestamped report from dsgai-reports/
-open dsgai-reports/DSGAI-report-*.html # macOS
-xdg-open dsgai-reports/DSGAI-report-*.html # Linux
-start dsgai-reports\DSGAI-report-.html # Windows
-```
+## Quick start
-**Deterministic, LLM-free option ($0):** run the CLI directly for reproducible findings + SARIF, no API cost:
+**Deterministic CLI โ $0, no LLM, no account.** Reproducible findings + SARIF in seconds. Needs only Python 3.10+ and ripgrep with PCRE2.
```bash
-python dsgai_scanner_tool/cli/dsgai_scan.py scan . --sarif DSGAI-scan.sarif
+git clone --depth 1 https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative
+python GenAI-Data-Security-Initiative/dsgai_scanner_tool/cli/dsgai_scan.py scan . \
+ --sarif DSGAI-scan.sarif --json-out DSGAI-scan.json
```
-That's it. Full installation, flags, and CI integration are documented below.
-
----
-
-## What It Does
-
-When you run `/dsgai_scanner_tool` inside a repository, the skill:
-
-1. **Detects** whether the repo contains GenAI/agentic patterns (LangChain, LlamaIndex, OpenAI SDK, vector stores, MCP servers, etc.) โ bails out gracefully if none are found.
-2. **Enriches live CVEs** by querying OSV, NVD, GitHub Advisory Database, and AVID against the exact package versions pinned in the repo (Python, JS/TS, Java, **Go**).
-3. **Scans source code** for all 21 DSGAI risk indicators across all 21 controls โ credentials, SQL injection via LLM output, vector store auth, telemetry logging, RAG access controls, MCP transport security, resilience, multimodal handling, synthetic data, labeling pipelines, IDE plugin scoping, and more.
-4. **Generates a timestamped `dsgai-reports/DSGAI-report-.html`** โ a self-contained, print-ready HTML report with findings, file locations, line numbers, remediation steps, MITRE ATLAS technique mapping, and a CVE advisory panel โ **strict-by-default obfuscation designed to minimize disclosure** (share under security-assessment handling; see *Residual risk*).
-
-**Performance:** All 21 control scans and all CVE source queries run as parallel tool calls โ the skill fires multiple grep scans and API requests simultaneously rather than sequentially. Typical scan time: 2โ5 minutes (in Claude Code; other AI tools may run sequentially and take longer).
-
----
-
-## Privacy, Obfuscation & Data Handling
-
-The skill runs **entirely on your local machine**. Your source code is never uploaded.
-
-### What stays local
-- All source code files scanned for security patterns
-- Configuration files, secrets, environment variables
-- Dependency manifests and build files
-
-### What is sent to the internet (optional, CVE lookups only)
-- Package names and version numbers (e.g. `langchain==0.1.0`) sent to public vulnerability databases
-- Only these public databases: [OSV](https://osv.dev), [NVD](https://nvd.nist.gov), [GitHub Advisory Database](https://github.com/advisories), [AVID](https://avidml.org)
-- No actual code, secrets, file contents, or identifying information leaves your machine
-- Pass `--no-cve` to skip all network traffic โ the scan falls back to the embedded CVE database
+**Claude Code skill โ full report with narrative + remediation.**
-### Report obfuscation โ strict by default
-
-The report **defaults to strict mode**. The default exists because OWASP-aligned compliance reports are routinely shared with auditors, attached to tickets, and stored in public repos โ and a leaked secret in a "compliance report" is worse than no report at all.
-
-| Mode | How to invoke | What evidence shows | When to use |
-|---|---|---|---|
-| **๐ก๏ธ STRICT** (default) | `/dsgai_scanner_tool` | Filename + line only (`config.py:12`). Intermediate directories dropped. Value-bearing matches (credentials, tokens, PII in logs) NEVER displayed, even with `--internal`. | Sharing with auditors, attaching to a Jira ticket, committing the report to git, posting in Slack, archiving as compliance evidence. |
-| **๐ INTERNAL** | `/dsgai_scanner_tool --internal` | Full relative path (`app/services/agent/config.py:12`). Value-bearing matches still NEVER displayed. | Your team's working copy on a private dev machine when you want to click straight to the file. |
-
-Value-bearing scans (DSGAI02 credentials, DSGAI13 vector store tokens, DSGAI14 telemetry PII, DSGAI15 system prompt secrets) use a six-step protocol that **never lets the matched secret value enter the report, the on-disk checkpoint, or any persistent tool call** โ regardless of mode.
-
----
-
-## Prerequisites
-
-- A repository containing GenAI or agentic code (Python, TypeScript, Java, Go)
-- An AI coding tool with **file reading access** to your codebase
-- **Web access** for live CVE lookups (optional โ pass `--no-cve` for fully offline operation)
-
-No Python packages or external tools required to generate the HTML report.
-
----
-
-## Running with Claude Code (Native)
-
-Claude Code has first-class support for this skill via its slash command system.
-
-**Install โ macOS / Linux:**
```bash
-cp dsgai_scanner_tool.md ~/.claude/commands/
-```
-
-**Install โ Windows (PowerShell):**
-```powershell
-Copy-Item dsgai_scanner_tool.md $env:USERPROFILE\.claude\commands\
-```
-
-**Install โ Windows (cmd):**
-```
-copy dsgai_scanner_tool.md %USERPROFILE%\.claude\commands\
-```
-
-**Usage โ all flags combinable:**
-
-| Command | What it does |
-|---|---|
-| `/dsgai_scanner_tool` | Default scan. STRICT obfuscation. Live CVE enrichment. Full repo. |
-| `/dsgai_scanner_tool --internal` | Full file paths (team-internal report) |
-| `/dsgai_scanner_tool --no-cve` | Skip live CVE lookups (air-gapped / offline) |
-| `/dsgai_scanner_tool --scope app/agents/` | Only scan this sub-directory (large monorepos) |
-| `/dsgai_scanner_tool --internal --no-cve --scope services/` | All three combined |
+# 1. Install the skill
+curl -fsSL https://raw.githubusercontent.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/main/dsgai_scanner_tool/dsgai_scanner_tool.md \
+ -o ~/.claude/commands/dsgai_scanner_tool.md
-Claude scans the codebase โ typically 2โ5 minutes depending on repo size. A `DSGAI-report.html` file is saved at the repository root.
+# 2. Scan your repo
+cd ~/my-genai-app && claude
+/dsgai_scanner_tool
-**Open the report:**
-```bash
-# macOS
-open DSGAI-report.html
-# Linux
-xdg-open DSGAI-report.html
-# Windows
-start DSGAI-report.html
+# 3. Open the timestamped report
+open dsgai-reports/DSGAI-report-*.html # macOS (xdg-open on Linux, start on Windows)
```
----
+> [!TIP]
+> Check your environment first with `python cli/dsgai_scan.py doctor` โ it verifies Python, ripgrep + PCRE2, and that the ruleset loads.
-## Running with Other AI Coding Tools
+## How it works
-The skill file is plain Markdown. Any AI tool with file reading access to your codebase can run it โ paste the contents as your prompt.
+The deterministic CLI does all pattern matching and CVE lookups; the skill (or the CI's report renderer) turns the checkpoint into a report. Nothing but package names + versions ever leaves your machine.
-| Tool | How to run |
-|---|---|
-| **Cursor** | Open `dsgai_scanner_prompt.md` (the plain-prompt variant), copy contents, paste into Cursor's AI chat |
-| **GitHub Copilot Chat** | Open `dsgai_scanner_prompt.md`, copy contents, paste into Copilot Chat in VS Code with repo files as context |
-| **ChatGPT / GPT-5** | Paste `dsgai_scanner_prompt.md` as the system prompt, then upload or paste the relevant source files |
-| **Google Gemini** | Paste `dsgai_scanner_prompt.md` as instructions, attach source files for analysis |
-
-> **Why a separate `dsgai_scanner_prompt.md`?** The Claude Code skill assumes specific tools (Grep with output modes, parallel tool calls, Write/Edit). The plain-prompt variant strips those assumptions so it works in tools that just ingest text + files.
-
-These tools generally cannot run scans in parallel, so total runtime can be 10โ20 minutes for large repos.
-
----
-
-## CI/CD Integrations
-
-### GitHub Action
-
-A drop-in workflow that runs the scan on every PR, posts a summary comment, and uploads the report as a build artifact:
-
-- Triggers on PRs, pushes to `main`/`master`, and manual dispatch
-- Installs Claude Code via `npm install -g @anthropic-ai/claude-code`
-- Runs the scan in STRICT mode (artifacts can end up in build logs visible to anyone with repo read access)
-- Posts a PR comment with FAIL / WARN / PASS / Vendor Attestation / Exploitable CVE counts
-- Optionally fails the build on any FAIL-class finding
+```mermaid
+flowchart TD
+ Repo[(Your GenAI repo)] --> Detect{"GenAI / agentic
code detected?"}
+ Detect -->|No| NA["Minimal report
21 ร NOT APPLICABLE"]
+
+ Detect -->|Yes| Engine
+ subgraph Engine["Deterministic CLI โ cli/dsgai_scan.py ยท stdlib + ripgrep ยท no LLM"]
+ direction TB
+ Scan[Scan 21 DSGAI controls
107 PCRE rules]
+ CVE[CVE enrichment
6 ecosystems ยท cached]
+ Scan --> Out[DSGAI-scan.json
+ SARIF 2.1.0]
+ CVE --> Out
+ end
+ CVE -. package + version only .-> Sources((OSV ยท NVD))
+
+ Out --> Skill[Claude Code skill
classify ยท judge ยท prose]
+ Skill --> Report[Timestamped HTML report
STRICT-redacted]
+ Out --> Renderer[cli/dsgai_report.py
deterministic HTML]
+ Renderer --> Report
+ Out --> CodeScan[GitHub Code Scanning]
-Required repo secret: `ANTHROPIC_API_KEY`. Optional: `NVD_API_KEY` (raises rate limit). `GITHUB_TOKEN` is auto-provided by Actions.
+ Report --> Auditor([Auditor / GRC])
+ Report --> Ticket([Jira / backlog])
+ CodeScan --> PR([PR annotations])
-```yaml
-# .github/workflows/dsgai-scan.yml
-name: OWASP DSGAI Compliance Scan
-on:
- pull_request: { branches: [main] }
- workflow_dispatch:
-# ... full workflow body in ./integrations/dsgai-scan.yml
+ style Engine fill:#0f172a,color:#fff
+ style Skill fill:#7c3aed,color:#fff
+ style Report fill:#16a34a,color:#fff
+ style CodeScan fill:#0b7285,color:#fff
+ style NA fill:#6b7280,color:#fff
+ style Sources fill:#e0e7ff,color:#1e1b4b
```
-See [`integrations/dsgai-scan.yml`](integrations/dsgai-scan.yml) for the complete workflow.
-
-### Pre-commit Hook (fast secret scan only)
+**Value-bearing rules never surface the secret.** Credential/PII patterns run through ripgrep in erase-the-match mode (`rg -o --replace ''`), so the matched value is destroyed *inside ripgrep* before anything is emitted โ it cannot reach the report, the checkpoint, or a tool call. See [How redaction works](#how-redaction-works).
-A pre-commit hook that runs a fast subset (DSGAI02 hardcoded LLM API key scan) to block secrets before commit. See [`integrations/pre-commit-hook.md`](integrations/pre-commit-hook.md) for the recipe.
+## Features
----
-
-## What Gets Scanned
-
-All 21 DSGAI risks from the OWASP GenAI Data Security framework:
-
-| Risk | Control Area | Scope |
+| | |
+|---|---|
+| ๐ฏ **Deterministic engine** | 107 PCRE rules, run via `rg --pcre2`. Identical findings on identical input โ a compliance report you can diff, not an LLM opinion. |
+| ๐ **Redaction by construction** | Value-bearing matches are erased inside ripgrep; the checkpoint schema *forbids* content fields (machine-checked). |
+| ๐งพ **SARIF 2.1.0 โ Code Scanning** | Native GitHub Code Scanning annotations on changed lines, plus a portable artifact. |
+| ๐ **CVE enrichment, no hallucination** | The CLI queries OSV (+ NVD for CVSS) per pinned version across **6 ecosystems**; the LLM never transcribes CVE data. Cached, offline-capable. |
+| ๐ **Multi-language** | Python, JS/TS, Java, Kotlin, Go, and credential coverage for **C#, Rust, Ruby**. |
+| ๐งฐ **Ships with the ecosystem** | A [gitleaks](integrations/gitleaks/dsgai.toml) rule pack and a [Semgrep](dist/dsgai.semgrep.yaml) export so incumbent toolchains carry the framework. |
+| ๐๏ธ **Team-scale controls** | Inline `# dsgai-ignore` suppressions (with reasons), a **baseline** so CI gates only on new findings, and incremental `--diff` scans. |
+| โ
**Tested & gated** | A public [vulnerable fixture app](tests/fixtures/vulnerable-app/) with a line-pinned answer sheet and a CI self-test that makes external rule PRs safe to merge. |
+| ๐ฃ๏ธ **Honest reporting** | STRICT mode renders stable file IDs, never the secret; the report declares its own residual risk instead of implying it can be published as-is. |
+
+### The 21 DSGAI controls
+
+
+Every control is rated PASS / WARN / FAIL / NOT VALIDATED / NOT APPLICABLE / VENDOR ATTESTATION REQUIRED โ click to expand the full list.
+
+| Risk | Control | Responsibility |
|---|---|---|
| DSGAI01 | Training Data Privacy | BOTH |
-| DSGAI02 | Agentic Identity & Credential Management | BUILD |
-| DSGAI03 | Shadow AI & Unauthorized Data Flows | BOTH |
+| DSGAI02 | Agentic Identity & Credential Management | BUILD |
+| DSGAI03 | Shadow AI & Unauthorized Data Flows | BOTH |
| DSGAI04 | AI Supply Chain Security | BUILD |
| DSGAI05 | RAG Data Security | BUILD |
-| DSGAI06 | MCP & Plugin Security | BUILD |
+| DSGAI06 | MCP & Plugin Security | BUILD |
| DSGAI07 | Data Lifecycle Management | BUILD |
-| DSGAI08 | Regulatory & Privacy Compliance | BOTH |
+| DSGAI08 | Regulatory & Privacy Compliance | BOTH |
| DSGAI09 | Multimodal AI Data Security | BOTH |
| DSGAI10 | Synthetic Data Security | BUILD |
| DSGAI11 | Multi-Tenant Data Isolation | BUILD |
| DSGAI12 | Database Agent Security | BUILD |
| DSGAI13 | Vector Store Security | BUILD |
-| DSGAI14 | AI Telemetry & Observability Security | BUILD |
+| DSGAI14 | AI Telemetry & Observability Security | BUILD |
| DSGAI15 | Context Window Data Security | BUILD |
-| DSGAI16 | AI IDE Plugin & Extension Security | BUILD |
-| DSGAI17 | AI System Resilience & Availability | BUILD |
+| DSGAI16 | AI IDE Plugin & Extension Security | BUILD |
+| DSGAI17 | AI System Resilience & Availability | BUILD |
| DSGAI18 | Model Output Data Security | BUILD |
| DSGAI19 | AI Data Labeling Security | BUILD |
| DSGAI20 | Inference API Security | BOTH |
| DSGAI21 | Knowledge Store Security | BUILD |
-Each control is rated: **PASS** / **WARN** / **FAIL** / **NOT VALIDATED** / **NOT APPLICABLE** / **VENDOR ATTESTATION REQUIRED**.
-
-> **VENDOR ATTESTATION REQUIRED** is new in v0.2. For BUY-tagged controls and the BUY portions of BOTH-tagged controls, the code scan cannot determine compliance โ the report lists exactly which vendor attestations to request (e.g. SOC 2 report, training data retention policy, rate-limit documentation).
-
-### Remediation Tiers
+**[BUILD]** you implement (scanned mechanically) ยท **[BUY]** the vendor is responsible (emits a *Vendor Attestation Required* callout) ยท **[BOTH]** shared. See the **Reference โ Scope annotation** section below.
-Each finding in the Recommendations section is tagged with one of three tiers so teams can sequence work:
+
-| Tier | Colour | Meaning | Example |
-|---|---|---|---|
-| **Tier 1** | ๐ด Red | Fix today. FAIL items + exploitable CVEs affecting your repo. | Hardcoded `sk-` API key; unauthenticated vector store; `torch.load()` unsafe pickle. |
-| **Tier 2** | ๐ก Yellow | Architecture backlog. WARN items + structural improvements. | Add circuit breaker; centralize PII redaction middleware; replace third-party LLM call with internal gateway. |
-| **Tier 3** | ๐ต Blue | Maturity program. NOT VALIDATED items needing process evidence. | Run quarterly red-team exercise; complete DPIA; commission AppSec architecture review. |
+## Usage
-Vendor attestations to request from BUY/BOTH controls render as a separate ๐ฃ purple card.
+### Deterministic CLI
----
+`cli/dsgai_scan.py` is a single stdlib-only file that shells out to ripgrep. Subcommands:
-## Evidence Safety โ Structural vs Value-Bearing Patterns
+| Command | What it does |
+|---|---|
+| `scan [path]` | Run the ruleset; emit `DSGAI-scan.json`, SARIF, and/or a table. |
+| `detect [path]` | Exit 0 if the repo contains GenAI/agentic signals, 1 otherwise. |
+| `doctor` | Check Python, ripgrep + PCRE2, and that the ruleset loads. |
+| `baseline [path]` | Snapshot current findings to a baseline file. |
+| `cve [path]` | CVE enrichment only, from dependency manifests. |
-When the skill scans your codebase and finds a match, it needs to include that evidence in the report. Not all matches are equal โ some show *architectural gaps* (safe to display), others target *credential and PII-bearing lines* (must never appear in a shareable report).
+Key `scan` flags (all combinable):
-### Structural Patterns [STRUCTURAL]
+| Flag | Effect |
+|---|---|
+| `--sarif FILE` | Write SARIF 2.1.0 for GitHub Code Scanning. |
+| `--json-out FILE` | Write the `DSGAI-scan.json` checkpoint. |
+| `--internal` | Render full paths (default STRICT renders file IDs). |
+| `--scope PATH` | Restrict the scan to a sub-directory. |
+| `--exclude PATH` | Exclude a path/glob (repeatable). |
+| `--diff REF` | Incremental: only files changed vs `REF`. |
+| `--baseline FILE` | Gate only on findings **not** in the baseline. |
+| `--no-cve` / `--offline` / `--refresh-cve` | Control CVE enrichment & caching. |
+| `--fail-on {fail,warn}` | Exit non-zero at this threshold (CI gating). |
+
+Suppress a finding inline (a reason is required, and it stays visible in a *Suppressed* section):
+
+```python
+db.execute(query) # dsgai-ignore: P12.1 reason="reviewed 2026-07 โ ORM param binding"
+```
-The match shows a code *pattern* โ a missing import, an absent decorator, a function call without a required argument. The matched line contains no runtime secret or PII. It is reproduced in the evidence block because it proves the finding without exposing anything sensitive.
+### Claude Code skill
-**Examples (safe to show):**
-```
-# DSGAI04 โ torch.load() without weights_only=True
-loader.py:22 โ model = torch.load(model_path)
+The skill prefers the bundled CLI and falls back to an in-context scan if it isn't present; the report header names which engine ran.
-# DSGAI06 โ MCP server binding all interfaces with no auth middleware
-server.py:42 โ uvicorn.run(app, host="0.0.0.0", port=8001)
+| Command | What it does |
+|---|---|
+| `/dsgai_scanner_tool` | Full scan. STRICT redaction, CVE enrichment, whole repo. |
+| `/dsgai_scanner_tool --internal` | Full file paths (team-internal report). |
+| `/dsgai_scanner_tool --no-cve` | Skip CVE lookups (air-gapped / offline). |
+| `/dsgai_scanner_tool --scope app/agents/` | Scan one sub-directory (monorepos). |
+| `/dsgai_scanner_tool --diff main --baseline dsgai-baseline.json` | Incremental, gated on new findings. |
-# DSGAI20 โ FastAPI endpoint missing rate-limiting decorator
-main.py:55 โ @app.post("/chat") # no @limiter.limit decorator
+### Other AI coding tools
-# DSGAI05 โ similarity_search() missing access-control filter
-retriever.py:41 โ results = vectorstore.similarity_search(query, k=5)
-```
+The tool-neutral variant [`dsgai_scanner_prompt.md`](dsgai_scanner_prompt.md) is generated from the skill (so the two never drift) and works with any assistant that can run shell commands โ Cursor, Copilot Chat, ChatGPT, Gemini. Paste it as instructions and give the model access to your files and a shell.
-### Value-Bearing Patterns [VALUE-BEARING โ ๏ธ]
+## CI/CD and Code Scanning
-The match specifically targets lines where the *content IS the sensitive value* โ a credential assignment, a secret key, a connection string, or a log statement that may contain PII. Reproducing this in a shareable report would leak the actual value.
+### GitHub Action โ [`integrations/dsgai-scan.yml`](integrations/dsgai-scan.yml)
-The skill applies a **six-step protocol** (V1โV6, defined in the skill file) that guarantees the matched value never enters the report, the on-disk checkpoint file, or any persistent tool call. Additionally, every STRUCTURAL match is swept for accidental secret patterns before display.
+A hardened, **two-job** workflow. The design keeps secrets away from any job that reads untrusted code:
-**What the report shows for value-bearing findings:**
-```
-config.py:12 โ hardcoded OpenAI API key pattern detected (value redacted โ review file directly)
-config.py:18 โ hardcoded vector store auth token pattern detected (value redacted โ review file directly)
-logging.py:28 โ prompt logging statement detected (content redacted โ review file directly)
-```
+- **`scan`** โ runs the **deterministic CLI only**: no LLM, no API key, no network egress with a secret. Safe on fork PRs. Uploads **SARIF to Code Scanning** (same-repo) and the checkpoint as an artifact.
+- **`narrate`** โ renders the HTML report **deterministically** (`cli/dsgai_report.py`); no LLM, no secret either.
-The four DSGAI controls whose scans are classified VALUE-BEARING:
+All third-party actions are **pinned by commit SHA**. Gating is **report-only by default** โ set the repo variable `DSGAI_FAIL_ON` to `fail` or `warn` to break the build. No `ANTHROPIC_API_KEY` is required.
-| Control | Why value-bearing |
-|---|---|
-| **DSGAI02** โ Agentic Credential Management | Matches lines containing actual API keys, database passwords, JWT secrets, cloud credentials |
-| **DSGAI13** โ Vector Store Security | May match lines where vector store auth tokens are hardcoded as literal values |
-| **DSGAI14** โ AI Telemetry Security | Matches log statements whose format strings reference PII fields or contain inline test data |
-| **DSGAI15** โ Context Window Security | Matches system prompt construction that may embed credential strings or sensitive config |
+> [!IMPORTANT]
+> CI always scans in STRICT mode (file IDs, never full paths or values). Don't pass `--internal` in a workflow whose artifacts or logs are visible beyond your team.
-All 17 remaining controls (DSGAI01, 03โ12, 16โ21) are **STRUCTURAL** โ matched content is always safe to show (after defense-in-depth secret sweep).
+### Pre-commit โ gitleaks pack + portable fallback
----
+Block hardcoded credentials before they land. Recommended path is the [gitleaks rule pack](integrations/gitleaks/dsgai.toml) (entropy-aware, cross-platform); a zero-dependency [ripgrep script](integrations/dsgai-secret-scan.sh) is provided as a bash-3.2-safe fallback. See [`integrations/pre-commit-hook.md`](integrations/pre-commit-hook.md).
-## Report Output
+### Semgrep pack
-
-
-
- DSGAI report rendered deterministically (cli/dsgai_report.py) from a scan of the public fixture app โ STRICT mode, file IDs + line numbers only, zero real-repo disclosure. Fully reproducible.
-
+[`dist/dsgai.semgrep.yaml`](dist/dsgai.semgrep.yaml) exports the STRUCTURAL rules as a Semgrep pack โ run the DSGAI framework inside a toolchain you already have.
-The generated `DSGAI-report.html` contains:
+## Why this scanner
-- **Executive Summary** โ overall posture and key FAIL findings
-- **Obfuscation Mode badge** โ STRICT ๐ก๏ธ or INTERNAL ๐
-- **Dashboard** โ counts of PASS / WARN / FAIL / NOT VALIDATED / NOT APPLICABLE / VENDOR ATTESTATION across all 21 controls
-- **AI Component Inventory** โ detected frameworks, vector stores, LLM providers, MCP servers
-- **MITRE ATLAS Techniques** โ AI attack techniques relevant to the detected stack
-- **Summary Table** โ all 21 risks at a glance with status and key evidence
-- **Detailed Findings** โ one card per risk with file locations, line numbers, remediation steps
-- **Recommendations** โ tiered action plan (fix today / architecture backlog / maturity / vendor attestations)
-- **CVE Advisory Panel** โ live CVEs for your exact dependency versions, grouped by DSGAI risk
-- **Compliance Artifacts Checklist** โ 15-item checklist mappable to GDPR, EU AI Act, SOC 2, ISO 42001
+It's built to *complement* the tools you already run, not replace them โ it even ships packs for them.
-The report is fully self-contained (no CDN, no external fonts) and renders correctly when saved as PDF.
+- **Framework-native.** The reference implementation of the OWASP GenAI Data Security 2026 framework, maintained inside the initiative that authors it. Findings map 1:1 to the 21 controls, so the report reads as compliance evidence, not generic lint output.
+- **Deterministic where it matters.** Pattern matching, CVE lookup, and report structure are code (stdlib CLI + ripgrep) โ not model output. Identical input yields byte-identical findings, and every rule is data pinned to a known-answer fixture corpus. The optional LLM layer only adds prose; it never decides what was found.
+- **Redaction by construction, not by policy.** Value-bearing rules erase the match inside ripgrep, and the checkpoint schema formally forbids content fields โ so the guarantee is machine-checked in CI, not left to discipline.
+- **GenAI-specific depth, not SAST breadth.** Vector-store auth, RAG access control, MCP transport, prompt-logging PII, unsafe model deserialization, agentic credential handling โ patterns general rulesets don't carry.
+- **Feeds your toolchain.** SARIF into GitHub Code Scanning; exported Semgrep and gitleaks packs so the framework rides tools you already operate.
----
+## The report
-## Scan Checkpoint File (`DSGAI-scan.json`)
+
+
+
+ Rendered deterministically by cli/dsgai_report.py from a scan of the public fixture app โ STRICT mode, file IDs + line numbers only, zero real-repo disclosure. Fully reproducible.
+
-When the skill runs, it writes a local checkpoint file called `DSGAI-scan.json` to the repository root after each major scan phase.
+The self-contained HTML report (no CDN, no external fonts; prints cleanly to PDF) contains:
-### Why it exists
+- **Executive summary** & an **obfuscation-mode badge** (๐ก๏ธ STRICT / ๐ INTERNAL)
+- **Compliance dashboard** โ counts across all 21 controls; every status carries a symbol + text label, not colour alone
+- **AI component inventory** โ detected frameworks, vector stores, LLM providers, MCP servers
+- **MITRE ATLAS techniques** relevant to the detected stack (from a versioned [static map](rules/atlas-map.yaml))
+- **Findings** โ one card per risk with locations, line numbers, and tiered remediation
+- **CVE advisory panel** โ advisories for your exact dependency versions, grouped by DSGAI risk
+- **Compliance checklist** mappable to GDPR, EU AI Act, SOC 2, ISO 42001
-The scan involves three time-consuming phases: repository detection, live CVE enrichment, and 21-control grep scanning. If the session times out before the HTML report is written, everything is lost and the scan restarts from zero. The checkpoint prevents this โ on the next run the skill skips already-completed phases.
+> [!WARNING]
+> **Residual risk.** STRICT mode is designed to *minimize* disclosure โ file IDs + line numbers only, value-bearing matches never shown. It does **not** make the report public-safe: the existence and location of failing controls is itself information. Handle it like any security assessment.
-### What it stores โ and what it doesn't
+## How redaction works
-The file contains only **structural scan metadata**: detected framework versions, DSGAI control findings (status, rendered file paths, line numbers, pattern IDs), and CVE query results.
+The redaction guarantee is **structural**, not a matter of remembering to be careful:
-The same redaction rules that apply to the HTML report apply here:
-- VALUE-BEARING findings store only `{control, path_rendered, line, pattern_id, status}` โ never `match_text`, `raw_grep_output`, or `value`
-- In STRICT mode, the `path_internal` field is omitted entirely โ keeping full paths out of the checkpoint, which minimizes disclosure without making the checkpoint public-safe
-- In INTERNAL mode, both `path_rendered` and `path_internal` are present for team convenience
+1. **Location-only matching.** Value-bearing rules (DSGAI02/13/14/15 โ credentials, vector-store tokens, telemetry PII, system-prompt secrets) run `rg -o --replace ''`. Ripgrep erases the matched text *before it emits anything*, so the output is `path:line:` โ the secret never leaves the ripgrep process.
+2. **Stable file IDs in STRICT mode.** Findings render as `F07:12`; the `F## โ path` map is written to a **gitignored** `DSGAI-filemap.json` that is never embedded in the report.
+3. **A schema that forbids leakage.** [`schemas/dsgai-scan.schema.json`](schemas/dsgai-scan.schema.json) rejects any finding carrying `match_text`, `content`, `value`, or `raw_grep_output`, and the CLI self-validates before writing. The guarantee is machine-checked by CI.
-### Lifecycle
+## Reference
-In STRICT mode it contains no secrets and no full paths, but it still records which controls fail and where โ treat it as a security artifact (commit only if your repo's threat model allows, or `.gitignore` it). Regenerated on each full scan.
+
+Checkpoint file โ DSGAI-scan.json
----
+The CLI writes a schema-validated checkpoint alongside the report: framework/ruleset versions, per-control statuses, findings (control, rule ID, rendered path, line, status), suppressed findings, and CVEs. It carries **no** match content by construction. In STRICT mode it holds file IDs, not full paths โ but it still records which controls fail and where, so treat it as a security artifact (commit only if your threat model allows, or `.gitignore` it).
-## Exporting to PDF
+
-**Option 1 โ Browser print (simplest):**
-Open `DSGAI-report.html` in Chrome or Edge โ `Ctrl+P` / `Cmd+P` โ Save as PDF. All cards expand automatically for print.
+
+Export to PDF
-**Option 2 โ Chrome headless (scriptable):**
+**Browser:** open the report in Chrome/Edge โ `Ctrl/Cmd+P` โ Save as PDF (cards expand for print).
+**Headless:**
```bash
-# macOS
-"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
- --headless=new --print-to-pdf=DSGAI-report.pdf \
- --print-to-pdf-no-header "file://$(pwd)/DSGAI-report.html"
-
-# Linux
google-chrome --headless=new --print-to-pdf=DSGAI-report.pdf \
- --print-to-pdf-no-header "file://$(pwd)/DSGAI-report.html"
-```
-
-```powershell
-# Windows (PowerShell)
-& "C:\Program Files\Google\Chrome\Application\chrome.exe" `
- --headless=new --print-to-pdf=DSGAI-report.pdf `
- --print-to-pdf-no-header "file:///$((Get-Location).Path)/DSGAI-report.html"
+ --print-to-pdf-no-header "file://$(pwd)/dsgai-reports/DSGAI-report-.html"
```
----
-
-## Scope Annotation
-
-Each DSGAI control is tagged by responsibility:
-
-- **[BUILD]** โ your team implements this in the codebase. Scanned mechanically.
-- **[BUY]** โ the LLM provider / SaaS vendor is responsible. Emits a `VENDOR ATTESTATION REQUIRED` callout listing what to request.
-- **[BOTH]** โ shared responsibility. The BUILD portion is scanned; the BUY portion emits a vendor attestation callout.
+
-Controls with BUY-side aspects (DSGAI01, 08, 09, 20) generate a consolidated "Vendor Attestations to Request" recommendation card.
+
+Scope annotation โ BUILD / BUY / BOTH
----
+Each control is tagged by responsibility. **[BUILD]** controls are scanned mechanically. **[BUY]** controls (the vendor's responsibility) emit a `VENDOR ATTESTATION REQUIRED` callout listing exactly what to request (e.g. SOC 2 report, data-retention policy, rate-limit documentation). **[BOTH]** controls scan the BUILD portion and emit an attestation callout for the BUY portion. Controls with BUY aspects (DSGAI01, 08, 09, 20) consolidate into one *Vendor Attestations to Request* card.
-## Based On
+
-**OWASP GenAI Data Security Risks and Mitigations 2026 (v1.0, March 2026)**
-[https://genai.owasp.org/resource/owasp-genai-data-security-risks-mitigations-2026/](https://genai.owasp.org/resource/owasp-genai-data-security-risks-mitigations-2026/)
+
+Remediation tiers
-[OWASP GenAI Data Security Initiative](https://genai.owasp.org/initiative/data-security/) โ led by [Emmanuel Guilherme Junior](https://www.linkedin.com/in/emmanuelgjr/).
+| Tier | Meaning | Example |
+|---|---|---|
+| ๐ด **Tier 1** โ fix today | FAIL items + exploitable CVEs | Hardcoded `sk-` key; unauthenticated vector store; unsafe `torch.load()` |
+| ๐ก **Tier 2** โ architecture backlog | WARN + structural gaps | Add a circuit breaker; centralize PII redaction; route via an internal LLM gateway |
+| ๐ต **Tier 3** โ maturity program | NOT VALIDATED (process evidence) | Quarterly red-team; complete a DPIA; commission an AppSec review |
----
+
-## Cost & runtime
+## Cost and runtime
-- **CLI-only mode: $0.** `python cli/dsgai_scan.py scan .` uses no LLM โ just ripgrep. Reproducible findings + SARIF in seconds. This is what the hardened GitHub Action runs on every PR (including fork PRs, since it needs no secrets).
-- **Skill mode (LLM orchestration):** a full scan of the public fixture app renders in roughly **1โ3 minutes** in Claude Code; token cost depends on repo size and the report prose. The deterministic engine does the matching; the model only classifies, writes remediation prose, and renders the report โ so cost scales with findings, not lines of code.
-- **Fork PRs:** the Action's scan job runs on forks and uploads the SARIF as an artifact (Code Scanning upload is skipped โ fork tokens can't write security events); the LLM narration job is skipped on forks by design.
-- Incremental `--diff` scans (seconds, near-zero cost) are planned for **v0.4**.
+- **CLI-only mode: $0.** `python cli/dsgai_scan.py scan .` uses no LLM โ just ripgrep. Reproducible findings + SARIF in seconds. This is what the Action runs on every PR (including forks, since it needs no secrets).
+- **Skill mode:** a full scan of the fixture app renders in ~1โ3 minutes in Claude Code; token cost scales with findings and report prose, not lines of code โ the deterministic engine does the matching.
+- Everything runs **locally**. Only package names + pinned versions go to public CVE databases, and only if you don't pass `--no-cve`.
## Contributing
+> [!TIP]
> **Found a wrong result? That's a contribution.** Run the scan on your repo and file a
-> [false-positive](../.github/ISSUE_TEMPLATE/scanner-false-positive.yml) or
-> [false-negative](../.github/ISSUE_TEMPLATE/scanner-false-negative.yml) issue โ every
-> accepted report becomes a permanent, credited test case. No code required.
-
-This is an OWASP project. Contributions welcome โ open an issue or PR against [GenAI-Security-Project/GenAI-Data-Security-Initiative](https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative).
+> [false-positive](https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/issues/new?template=scanner-false-positive.yml) or
+> [false-negative](https://github.com/GenAI-Security-Project/GenAI-Data-Security-Initiative/issues/new?template=scanner-false-negative.yml) issue โ every accepted
+> report becomes a permanent, credited test case in the fixture corpus. No code required.
-When proposing new scan patterns:
-1. Classify them as STRUCTURAL or VALUE-BEARING (use the table in the skill's Step 2)
-2. Validate the PCRE pattern with `rg --pcre2 'pattern' .` against a real repo
-3. For VALUE-BEARING patterns, prove the value never escapes by inspecting `DSGAI-scan.json` after a test run
+Detection rules live as data in [`rules/dsgai-rules.yaml`](rules/dsgai-rules.yaml) (schema-validated, compiled to JSON). To add or fix a rule, see [`rules/README.md`](rules/README.md) and the full guide in [`CONTRIBUTING.md`](CONTRIBUTING.md); the [`ROADMAP.md`](ROADMAP.md) tracks what's planned. Every rule ships with positive **and** negative fixture cases โ the CI self-test is the gate.
-See [`CONTRIBUTING.md`](CONTRIBUTING.md) for the full contributor guide and the
-[`ROADMAP.md`](ROADMAP.md) for what's planned.
+### Non-goals
-## Non-goals
+To stay maintainable and trustworthy, some things are deliberately out of scope:
-To keep the scanner maintainable and trustworthy, some things are deliberately out of scope:
-
-- **We will not reimplement general-purpose secret scanning.** We ship a gitleaks rule
- pack instead (see `integrations/gitleaks/`) and lean on battle-tested tooling for
- entropy-based detection.
-- **We will not become a general-purpose SAST tool.** Scope is the 21 DSGAI controls and
- the GenAI-specific patterns behind them โ not every code smell in a repo.
-- **We will not add rules without fixture test cases.** A rule with no positive *and*
- negative test has no defined precision, so it doesn't merge.
-- **We will not accept changes that weaken the redaction guarantees.** Value-bearing
- matches never enter a report, checkpoint, or persisted tool call โ that property is
- non-negotiable.
-
----
+- **No general-purpose secret scanning** โ we ship a gitleaks pack and lean on battle-tested tooling instead.
+- **No general SAST** โ scope is the 21 DSGAI controls, not every code smell.
+- **No rules without fixture tests** โ a rule with no positive *and* negative case has no defined precision.
+- **No changes that weaken the redaction guarantee** โ that property is non-negotiable.
## License
-This skill is based on materials licensed under [Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)](https://creativecommons.org/licenses/by-sa/4.0/legalcode).
+Based on the **OWASP GenAI Data Security Risks and Mitigations 2026 (v1.0, March 2026)**, licensed under [Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)](https://creativecommons.org/licenses/by-sa/4.0/legalcode). *(A split that keeps framework text under CC BY-SA 4.0 while re-licensing the executable code under Apache-2.0 is under review with OWASP leadership.)*
-**Original work:** OWASP GenAI Data Security Risks and Mitigations 2026 (v1.0, March 2026) by the [OWASP GenAI Data Security Initiative](https://genai.owasp.org/initiative/data-security/), led by [Emmanuel Guilherme Junior](https://www.linkedin.com/in/emmanuelgjr/).
+**Framework & scanner** by the [OWASP GenAI Data Security Initiative](https://genai.owasp.org/initiative/data-security/), led by [Emmanuel Guilherme Junior](https://www.linkedin.com/in/emmanuelgjr/). v0.1 groundwork by Harish Ramachandran.
-**This adaptation:** Created by [Harish Ramachandran](https://www.linkedin.com/in/harish-ramachandran-a8026443/). You are free to share and adapt this skill for any purpose, including commercial use, under the same CC BY-SA 4.0 terms.
+