English | Türkçe
DevGuard AI is a local-first developer quality platform that collects security
and code-quality findings from real static-analysis tools, normalizes them into
a shared contract, and produces a deterministic pass / warn / fail policy
decision.
The LLM is never the scanner. It cannot create findings, change severity, or influence the build decision. Optional LLM support is limited to explaining already verified tool findings.
- Findings originate only from real, version-pinned analysis tools.
- Scanning, normalization, policy evaluation, SARIF, and GitHub Actions summaries work with the LLM completely disabled.
- Severity, confidence, baseline state, and policy decisions come only from tool output, versioned mappings, and policy rules.
- Source code stays inside the repository or CI runner by default.
- Automatic code modification, commits, and merges are outside the MVP scope.
| Area | Support |
|---|---|
| Languages | Python, JavaScript, and TypeScript |
| Static analysis | Ruff, Bandit, ESLint + typescript-eslint, Semgrep CE |
| Dependencies and secrets | OSV-Scanner v2, Gitleaks |
| Configuration | Hadolint, actionlint |
| Quality metrics | coverage.py JSON/LCOV, Radon, jscpd |
| Outputs | DevGuard Report JSON v1, SARIF 2.1.0, GitHub Actions summary, GitHub Check payload |
Tool responsibilities and execution boundaries are documented in ADR-0001.
apps/dashboard is a React/TypeScript interface that validates and displays a
DevGuard Report v1 entirely inside the browser. Open a report with the file
picker or drag and drop it into the page; the file is not uploaded to a server.
The dashboard cannot generate findings, recalculate policy, change severity, or store source snippets. It ships with a real end-to-end sample report.
Set-Location apps\dashboard
npm ci
npm run devThe Sites preview is owner-only and requires access: DevGuard AI Dashboard
| Overview | Findings |
|---|---|
![]() |
![]() |
| Policy decision | Tool health |
|---|---|
![]() |
![]() |
See UI architecture and the dashboard README for its contract, privacy boundary, and validation details.
DevGuard discovers applicable files without running project scripts or tests, executes the required pinned tools, removes sensitive raw fields, and maps every finding to the common Report v1 schema. It then applies suppressions, compares a repository-bound baseline, calculates aggregate quality metrics, and evaluates the versioned policy.
The implementation includes:
- parallel scanner execution with timeouts and fail-closed required-tool checks;
- packaged Semgrep, ESLint, Hadolint, actionlint, and jscpd configurations;
- offline-only OSV matching with no online vulnerability query during scans;
- fully redacted, temporary Gitleaks output;
- removal of source snippets, fixes, suggestions, metavariables, secret values, commit identities, absolute paths, and other raw sensitive fields before normalization;
- aggregate-only coverage, complexity, and duplication metrics;
- trusted unified-diff or hardened
git diffchange maps for changed-code policy gates; - repository-bound baselines and fingerprint-based, time-limited suppressions;
- snippet-free SARIF 2.1.0 and bounded GitHub Actions summaries;
- exact executable version and SHA-256 toolchain snapshots;
- deterministic policy decisions and schema-validated reports;
- complete operation with LLM functionality disabled.
Windows PowerShell:
py -3.11 -m venv .venv
.\.venv\Scripts\python.exe -m pip install -e ".[security-scanners]"Gitleaks, OSV-Scanner v2, Hadolint, actionlint, and jscpd v5 must also be
installed as verified, pinned native binaries. The production CI image verifies
them against ci/native-tools.lock.json.
Python transitive dependencies are locked by exact version and hash in
requirements/security-scanners.lock.txt. ESLint and jscpd dependencies are
locked with npm integrity values in rules/eslint/package-lock.json.
.\.venv\Scripts\devguard.exe scan `
--target . `
--output devguard-report.json `
--sarif-output devguard-results.sarif `
--github-summary-output devguard-summary.mdDevGuard automatically discovers coverage.json, coverage.lcov, or
lcov.info in the target root. A trusted CI artifact can also be provided
explicitly:
.\.venv\Scripts\devguard.exe scan `
--target . `
--coverage-file artifacts\coverage.json `
--toolchain-lock .devguard\toolchain.lock.json `
--output devguard-report.json `
--sarif-output devguard-results.sarif `
--github-summary-output $env:GITHUB_STEP_SUMMARYDevGuard never runs a test command or coverage producer. A missing coverage
artifact produces warn under the default policy; a malformed artifact fails
through an adapter error.
The first scan has no baseline, so existing non-secret findings are unknown
and normally produce warn. A later pull-request scan can compare a previous
report:
.\.venv\Scripts\devguard.exe scan `
--target . `
--mode pull_request `
--baseline previous-devguard-report.json `
--output devguard-report.jsonA valid baseline must belong to the same pseudonymous repository identity. A trusted unified diff can be supplied when the checkout does not contain the base commit:
.\.venv\Scripts\devguard.exe scan `
--target . `
--mode pull_request `
--diff-file artifacts\pull-request.diffIf a required change map cannot be produced, DevGuard fails closed instead of silently skipping changed-code gates.
Dockerfile.ci pins Python and Node base images by immutable digest. Locked
packages and verified native scanner assets are installed at build time, and the
offline OSV database is embedded in the image.
With Docker Desktop running:
.\scripts\build-ci-image.ps1The script builds the image, generates an exact executable toolchain snapshot, runs all real scanners against the vulnerable fixture without network access, and records the immutable local image ID. Runtime scanning uses no network, a read-only root filesystem, dropped capabilities, and disabled LLM functionality.
The default lock outputs are .devguard/ci-image.lock.json and
.devguard/toolchain.lock.json. Existing locks change only during an intentional
upgrade with -Force.
Inside a trusted environment with all scanners installed:
.\.venv\Scripts\devguard.exe lock-toolchain `
--output .devguard\toolchain.lock.jsonThis command does not install tools or use the network. It records the exact version and SHA-256 digest of every scanner and Git executable. Run it only while building a trusted image, never against binaries supplied by a pull request.
Generate an inspectable completed check-run payload without network access:
.\.venv\Scripts\devguard.exe github-check-payload `
--report devguard-report.json `
--head-sha $env:GITHUB_SHA `
--output devguard-check.jsonhead_sha must exactly match the full commit scanned in the report. The payload
contains at most 50 open tool findings and excludes source snippets, raw details,
diff content, and secret titles.
Publishing is a separate, explicitly invoked network action:
$env:DEVGUARD_GITHUB_TOKEN = $env:GITHUB_TOKEN
.\.venv\Scripts\devguard.exe publish-github-check `
--report devguard-report.json `
--repository $env:GITHUB_REPOSITORY `
--head-sha $env:GITHUB_SHA
Remove-Item Env:\DEVGUARD_GITHUB_TOKENProduction should use a GitHub App installation token with Checks: write.
Never expose this token to a job that executes untrusted fork pull-request code.
Exit codes:
0: policypassorwarn;1: policyfail;2: CLI or configuration contract error.
- Scans use local rules and offline vulnerability data.
- Source code and raw tool output remain inside the repository or CI runner.
- Symlinks resolving outside the repository cause the scan to stop.
- Scanner snippets, secret values, commit identities, raw diffs, and absolute paths are discarded before normalized output is produced.
- LLM use is optional, disabled by default, and restricted to explaining existing verified findings.
- The LLM cannot edit finding fields, severity, confidence, baseline state, or policy decisions.
- Publishing a GitHub Check requires an explicit command and a token supplied only through the environment.
The complete boundary is defined in ADR-0004.
.\.venv\Scripts\python.exe -m unittest discover -s tests -v
.\.venv\Scripts\ruff.exe check src tests
.\.venv\Scripts\bandit.exe -r src -qFixture-based adapter tests run offline. Inside the trusted image, execute the real scanner end-to-end smoke test with:
.\scripts\e2e-smoke.ps1 `
-Python .\.venv\Scripts\python.exe `
-ToolchainLock .devguard\toolchain.lock.json- Normalized finding contract
- Severity and policy model
- Privacy and LLM boundary
- Toolchain lock and offline E2E
- GitHub Checks publication boundary
- Report JSON Schema
- Policy JSON Schema
- Suppression JSON Schema
- Toolchain lock JSON Schema
- GitHub Check payload JSON Schema
- Example report
- Example policy
- Example suppressions
- Ruff configuration and machine-readable output
- Bandit JSON format
- Semgrep CLI reference
- ESLint JSON formatter
- typescript-eslint flat config
- OSV-Scanner v2 offline scanning
- Gitleaks reporting and redaction
- Hadolint
- actionlint usage and JSON output
- coverage.py JSON reports
- Radon command-line output
- jscpd JSON reporter
- GitHub SARIF support
- GitHub Actions job summaries
- GitHub Checks REST API
Released under the MIT License.




