draugr

module
v0.50.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 31, 2026 License: Apache-2.0

README

Draugr

Developer-first, descriptor-driven security and compliance qualification.

CI OpenSSF Scorecard OpenSSF Best Practices Latest release License

Describe your app. Draugr figures out the rest.

You declare what you know about your software — where the repos are, what container images it builds, what endpoints it exposes, what infrastructure it runs on — in a single descriptor (draugr.saga.yaml). Draugr infers which checks apply, runs the right tool for each, and produces pass/fail evidence you can trust. Swap scanners freely — use the tools you already pay for, or Draugr's open-source defaults. Every finding is normalized to SARIF.

Both questions asked before a release ships, from the same descriptor and the same gate: the security one — SAST, SCA, secrets, IaC, DAST, TLS, headers — and the compliance one, starting with a Software Bill of Materials of everything you actually ship.

This is the open-source core engine.

See it in action

Draugr scanning a repository with zero config

draugr scan . on the demo sandbox — no descriptor, just a prioritized verdict:

Draugr — FAIL   (draugr-demo 0.0.0)

Priorities:  P1 21   P2 22   P3 13   P4 0

Controls:
  secrets  FAIL   1 high
  iac      FAIL   4 high  5 medium  12 low
  sast     FAIL   7 high  9 medium
  sca      FAIL   3 critical  6 high  8 medium  1 low

Fix first:
  Priority  Severity  Score  Rule            Control  Scanner  Location
  P1        critical  9.8    CVE-2019-20477  sca      Trivy    app/requirements.txt:4
            PyYAML: command execution through python/object/apply constructor in FullLoader
  P1        critical  9.8    CVE-2020-14343  sca      Trivy    app/requirements.txt:4
            PyYAML: incomplete fix for CVE-2020-1747
  P1        high      8.0    DS-0002         iac      Trivy    app/Dockerfile:1
            Image user should not be 'root'
  P1        high      8.0    KSV-0014        iac      Trivy    deploy/pod.yaml:8
            Root file system is not read-only
  …

… and 46 more finding(s). Use --format json for the full report, or -o <dir> for report.json + results.sarif.

On a terminal the verdict, priorities, and severities are color-coded (disable with NO_COLOR). Findings are ranked by priority (P1–P4) = severity × the component's exposure & criticality; severity (critical/high/medium/low) comes from the CVSS score when a scanner provides one, else from the finding's level. The gate and --format json/sarif still use SARIF levels.

draugr-dev/draugr-demo is an intentionally vulnerable sample app wired to Draugr. Every control lights up, the findings are prioritized P1–P4, and results land in the repo's Security → Code scanning tab — a safe sandbox to see exactly what Draugr delivers before pointing it at your own code. The example PRs there also show the new-vs-fixed PR diff and the sticky comment.

Status

🚧 Early, and moving fast. Working today:

  • Controls: images (Trivy), sca (Trivy fs), licenses (Trivy licence scanner), secrets (Gitleaks), sast (Semgrep, plus opt-in gosec for Go), iac (Trivy config), headers (native HTTP-header analyzer), dast (Nuclei), tls (native TLS/certificate probe), infrastructure (CIS Kubernetes Benchmark — read through the Kubernetes API by default, with kube-bench and an in-cluster Job available for the node sections). See the integrations catalog.
  • Pipeline: end-to-end scan (plan → scan → judge → report), content-hash caching, tunable parallelism (-j), results normalized to SARIF.
  • Prioritization: declare a component's exposure and criticality and Draugr ranks every finding P1–P4 (--min-priority to focus, --fail-on-priority to gate); optional KEV/EPSS enrichment for real-world exploitability.
  • Policy: config.gate.controls holds each control to its own threshold, and config.exclude suppresses a finding with a required reason — it stays in the report, marked, rather than disappearing.
  • Evidence: config.sbom emits an SBOM per repository and image (SPDX or CycloneDX, via Syft); reports render as console, Markdown, HTML, JUnit, JSON or SARIF. The HTML report is self-contained and carries its own SARIF and TSV downloads.
  • Discovery: survey for Kubernetes images, the cluster itself, and GitHub org repositories — and the descriptor it writes enables the controls for what it found.
  • Zero-config & scaffolding: scan . scans the current repo with no descriptor (sca/secrets/sast/iac); init scaffolds a stack-detected draugr.saga.yaml to customize.
  • Preflight & tooling: validate (schema-check a Saga), doctor (which scanner tools are present/missing), tools install (fetch pinned, checksum- and cosign-verified scanners — and cosign itself — into ~/.draugr/bin), and self-update (update draugr itself, verified).

threats (threat intelligence) is on the roadmap. See controls & scanners for what maps to what.

Quickstart

Requirements: the external scanners for the controls you use — Trivy (images, sca, iac, licenses), Gitleaks (secrets), Semgrep (sast), Nuclei (dast), kube-bench with kubectl (infrastructure); git for repo scans, and Syft for config.sbom. headers and tls need no external tool.

draugr doctor tells you which of these your Saga actually needs and whether they are present; draugr tools install fetches pinned, verified copies of the ones Draugr packages. Go 1.26+ only to build from source.

Install (recommended):

curl -fsSL https://draugr.dev/install.sh | sh

Detects your OS and architecture and installs to ~/.local/bin — no sudo. It verifies before it installs and says which checks ran: the archive's SHA-256 against the release's checksums.txt always, plus the cosign signature on checksums.txt when cosign is on your PATH. Nothing is installed if a check fails.

Piping a script into a shell means trusting the host that served it. The script is readable in the repo, and install & verifying downloads has the manual steps, the DRAUGR_* knobs, and Homebrew. Once installed, update in place with draugr self-update.

Or build from source:

git clone https://github.com/draugr-dev/draugr.git
cd draugr && make build      # produces ./bin/draugr
./bin/draugr version

Fastest path — zero config. Point Draugr at a repo and go; no descriptor needed:

draugr scan .        # scans the current repo: sca, secrets, sast, iac
draugr init          # or scaffold a draugr.saga.yaml (stack-detected) to customize

For full control, write a Saga — any *.saga.yaml file (see examples/):

release:
  name: my-app
  version: "1.0"
config:
  controllers:
    images:
      enabled: true
components:
  - name: web
    images:
      - image: alpine:3.19

Scan it:

draugr scan draugr.saga.yaml            # console summary; exits non-zero on fail
draugr scan draugr.saga.yaml -o out/    # also writes out/report.json + out/results.sarif
draugr scan draugr.saga.yaml --fail-on warning
draugr scan draugr.saga.yaml --format markdown   # or html, junit, json, sarif

Your editor already knows this file. Draugr's JSON Schema is registered with SchemaStore, which VS Code's YAML extension and JetBrains IDEs consult by default — so any *.saga.yaml gets completion, hover docs and typo warnings on open, with nothing to configure. For an editor that doesn't use the catalog, draugr init also writes:

# yaml-language-server: $schema=https://draugr.dev/schema/draugr.saga.schema.json

draugr schema -o .saga.schema.json writes the copy embedded in your binary instead, if you'd rather validate offline or pin to exactly the version you run. See editor support.

Compare two scans to see what a change introduced (and gate a PR on new findings only):

draugr diff base/results.sarif head/results.sarif                     # new / fixed / unchanged
draugr diff base/results.sarif head/results.sarif --fail-on-new-priority P1

Let discovery write the descriptor for you:

draugr survey github repos --org my-org -o draugr.saga.yaml
draugr survey k8s images --namespace prod --merge -o draugr.saga.yaml

Full walkthrough: docs/getting-started/quickstart.md.

Use in CI (GitHub Actions)

Add Draugr to a repository's CI and code scanning with the first-party action. It downloads a cosign-verified Draugr release, runs the scan, and hands the merged SARIF to GitHub code scanning — one clean Draugr tool in the Security tab:

permissions:
  contents: read
  security-events: write   # upload SARIF to code scanning

steps:
  - uses: actions/checkout@v4
  - id: draugr
    uses: draugr-dev/draugr@v0     # latest v0.x; pin @vX.Y.Z for reproducible CI (installs Draugr for you)
    with:
      saga: draugr.saga.yaml
      tools: true                       # provision the scanners the controls need
      fail-on: warning                  # optional gate (default: error)
  - if: always()                        # publish findings even when the gate fails
    uses: github/codeql-action/upload-sarif@v3
    with:
      sarif_file: ${{ steps.draugr.outputs.sarif }}

With tools: true the action provisions the scanners each control needs (Trivy, Gitleaks, Semgrep). See the GitHub Action guide for the full workflow and all inputs.

Use from an AI coding assistant

Ask an assistant to check a change for security problems and it will — by running whatever scanner it can find, over a scope it chose for itself, and reading the raw output. That answer has no relationship to the one your pipeline will give.

draugr mcp serves Draugr over the Model Context Protocol, so the assistant reads your committed Saga instead:

claude mcp add draugr -- draugr mcp

It can list the controls that exist, hand back the descriptor schema your build enforces, validate a Saga before you write it, and rank an existing report by priority. Every *.saga.yaml nearby is exposed as a resource, so the assistant reads the real scope rather than guessing at one.

Scanning is off by default — it clones repositories and runs external tools. Turn it on with --scan=ask to approve each call, or --scan=always for a sandbox. See use Draugr from an AI coding assistant.

Documentation

Full documentation index → (grouped by task, with a "building blocks" glossary of Saga / Norn / Skald).

What Draugr doesn't promise

A passing verdict means the controls you configured found nothing they were looking for. It is not a statement that your software is secure — it's silent about anything your descriptor doesn't declare, controls you didn't enable, and whatever the underlying scanners miss. Licence findings are information, not legal advice. Draugr is provided under Apache-2.0 without warranty.

The details, including whose terms the bundled scanners carry and your responsibility for authorisation when scanning live endpoints: scope and disclaimer.

Security & supply chain

A security tool should hold itself to what it checks. Draugr does:

  • Standard output — every finding is normalized to SARIF 2.1.0 (OASIS), so results flow into GitHub / GitLab / Azure DevOps code scanning and any SARIF-aware tool.
  • Signed releases + provenance — release archives' checksums.txt is keyless-signed with cosign (Sigstore) into a checksums.txt.sigstore.json bundle, and each release publishes SLSA build-provenance attestations (gh attestation verify …); verify before installing (recipe).
  • SBOMs — a Syft SBOM is published for every release archive.
  • Verified toolingdraugr tools install fetches scanners pinned by SHA-256 and, where the upstream signs them, verifies the cosign signature too — and cosign itself is installable, so verification is self-sufficient.
  • We scan ourselves — Draugr runs on its own repo every PR (dogfood self-scan), and we track our supply-chain posture with the OpenSSF Scorecard (badge above).
  • Report a vulnerability — see SECURITY.md.

Development

Requires Go 1.26+.

make build   # build ./bin/draugr
make gate    # full local gate: fmt, vet, golangci-lint, race tests + coverage, govulncheck
make test    # run tests
Observability

Draugr uses Cobra for the CLI, log/slog for logging (human-readable and colorized by default; --log-format json for structured logs in CI/observability pipelines), and OpenTelemetry for traces and metrics. Telemetry is opt-in via the standard OTEL_* environment variables (e.g. OTEL_EXPORTER_OTLP_ENDPOINT) — a no-op with zero overhead when unset. Logs and spans never carry secrets.

License

Draugr is licensed under the Apache License 2.0.

Directories

Path Synopsis
cmd
draugr command
Command draugr is the Draugr CLI: developer-first, descriptor-driven security and compliance qualification.
Command draugr is the Draugr CLI: developer-first, descriptor-driven security and compliance qualification.
internal
builtins
Package builtins assembles the default registry of controllers and scanners that ship with Draugr.
Package builtins assembles the default registry of controllers and scanners that ship with Draugr.
cli
Package cli assembles the Draugr command-line interface on top of Cobra.
Package cli assembles the Draugr command-line interface on top of Cobra.
controllers
Package controllers holds Draugr's built-in controllers (e.g.
Package controllers holds Draugr's built-in controllers (e.g.
git
Package git provides repository checkouts for scanners that operate on source trees.
Package git provides repository checkouts for scanners that operate on source trees.
mcp
Package mcp exposes Draugr to AI coding agents over the Model Context Protocol.
Package mcp exposes Draugr to AI coding agents over the Model Context Protocol.
observability
Package observability provides Draugr's logging and telemetry foundations: structured logging via log/slog and distributed tracing via OpenTelemetry.
Package observability provides Draugr's logging and telemetry foundations: structured logging via log/slog and distributed tracing via OpenTelemetry.
sbom
Package sbom generates Software Bills of Materials by shelling out to Syft.
Package sbom generates Software Bills of Materials by shelling out to Syft.
scanners
Package scanners holds Draugr's built-in scanners, which wrap individual security tools and normalize their output to SARIF.
Package scanners holds Draugr's built-in scanners, which wrap individual security tools and normalize their output to SARIF.
scanpolicy
Package scanpolicy holds the scoring choices a scan makes, so every entry point into Draugr makes the same ones.
Package scanpolicy holds the scoring choices a scan makes, so every entry point into Draugr makes the same ones.
selfupdate
Package selfupdate updates the running draugr binary to a released version.
Package selfupdate updates the running draugr binary to a released version.
surveyors
Package surveyors holds Draugr's built-in surveyors.
Package surveyors holds Draugr's built-in surveyors.
toolexec
Package toolexec runs the external tools Draugr orchestrates, and reports what it ran.
Package toolexec runs the external tools Draugr orchestrates, and reports what it ran.
tools
Package tools describes the external command-line scanners Draugr orchestrates and detects whether they are installed.
Package tools describes the external command-line scanners Draugr orchestrates and detects whether they are installed.
version
Package version carries build metadata, injected at link time via -ldflags.
Package version carries build metadata, injected at link time via -ldflags.
pkg
cache
Package cache stores scan results keyed by content hash so unchanged targets are not re-scanned.
Package cache stores scan results keyed by content hash so unchanged targets are not re-scanned.
diff
Package diff compares two Draugr scan results and classifies every finding as new, fixed, or unchanged — the security delta of a change (typically a PR's head vs the base branch).
Package diff compares two Draugr scan results and classifies every finding as new, fixed, or unchanged — the security delta of a change (typically a PR's head vs the base branch).
engine
Package engine orchestrates a run: it expands a Saga into scan jobs (controllers × components), executes them with bounded parallelism, and aggregates each control's results.
Package engine orchestrates a run: it expands a Saga into scan jobs (controllers × components), executes them with bounded parallelism, and aggregates each control's results.
exploit
Package exploit enriches a finding's severity with real-world exploitability signals: CISA KEV (Known Exploited Vulnerabilities — confirmed exploited in the wild) and FIRST EPSS (Exploit Prediction Scoring System — probability of exploitation).
Package exploit enriches a finding's severity with real-world exploitability signals: CISA KEV (Known Exploited Vulnerabilities — confirmed exploited in the wild) and FIRST EPSS (Exploit Prediction Scoring System — probability of exploitation).
norn
Package norn evaluates scan results against policy to produce a verdict (pass/fail) per control and overall.
Package norn evaluates scan results against policy to produce a verdict (pass/fail) per control and overall.
plugin
Package plugin is the Draugr plugin SDK.
Package plugin is the Draugr plugin SDK.
prioritization
Package prioritization turns a finding's severity and its component's risk classification (exposure × business criticality) into a single Priority band.
Package prioritization turns a finding's severity and its component's risk classification (exposure × business criticality) into a single Priority band.
publish
Package publish delivers rendered reports (report.Artifact) to destinations.
Package publish delivers rendered reports (report.Artifact) to destinations.
report
Package report renders a scan result in a chosen format.
Package report renders a scan result in a chosen format.
saga
Package saga defines the Draugr descriptor ("Saga") — the declarative account of an application's security surface (repositories, images, hosts, infrastructure) plus the controller configuration that drives a scan.
Package saga defines the Draugr descriptor ("Saga") — the declarative account of an application's security surface (repositories, images, hosts, infrastructure) plus the controller configuration that drives a scan.
sarif
Package sarif provides Draugr's result currency: a pragmatic model of SARIF 2.1.0 findings, plus merge and deduplication.
Package sarif provides Draugr's result currency: a pragmatic model of SARIF 2.1.0 findings, plus merge and deduplication.
sbom
Package sbom is the Software Bill of Materials surface: the document type a run produces and the contract for producing one.
Package sbom is the Software Bill of Materials surface: the document type a run produces and the contract for producing one.
skald
Package skald renders scan results and verdicts into evidence: a JSON summary and merged SARIF.
Package skald renders scan results and verdicts into evidence: a JSON summary and merged SARIF.
surveyor
Package surveyor is the discovery framework: plugins that inspect an environment and return Saga fragments, which are merged so the descriptor can write itself.
Package surveyor is the discovery framework: plugins that inspect an environment and return Saga fragments, which are merged so the descriptor can write itself.
tooladapter
Package tooladapter turns an external command-line security tool into a Draugr Scanner declaratively: describe how to build the command for a target, and the adapter runs it and parses its SARIF output.
Package tooladapter turns an external command-line security tool into a Draugr Scanner declaratively: describe how to build the command for a target, and the adapter runs it and parses its SARIF output.
tui
Package tui holds the terminal-presentation rules Draugr applies everywhere it writes for a person: when colour is allowed, what the colours mean, and how to link to more detail.
Package tui holds the terminal-presentation rules Draugr applies everywhere it writes for a person: when colour is allowed, what the colours mean, and how to link to more detail.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL