Docker images, GitHub Action, NIST CSF catalog, HTML reports — and what each actually enables.
Wardex v2.0 implemented a risk-based release gate with HMAC-signed CRA Article 14 artefact lifecycle. Running it required a Go toolchain or a precompiled binary. Integrating into CI/CD meant wrapping the binary in a custom container. Compliance reporting required piping JSON output into separate tools. Framework evaluation was limited to ISO 27001, NIS2, and DORA — which maps to part of the European regulatory landscape but omits the framework most organizations use as their base: NIST CSF.
v2.1 addresses these integration gaps. No new risk model, no new artefact types — the evaluation engine and Article 14 pipeline are unchanged. The work is in deployment surface and framework coverage.
Wardex v2.1 ships multi-architecture Docker images on GitHub Container Registry. Six targets: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64, windows/arm64. Entry point accepts all CLI subcommands. Exit codes preserved.
docker pull ghcr.io/had-nu/wardex:2.1.1
docker run ghcr.io/had-nu/wardex:2.1.1 wardex evaluate \
--config wardex-config.yaml \
--evidence vulns.yaml
The images are built by GoReleaser and pushed via the release workflow (.goreleaser.yaml, Docker section with extra_files for config templates). Each image contains the same single binary — no init process, no sidecars. Suitable for ephemeral CI runners.
The repository ships an action.yml that exposes Wardex as a composable GitHub Action. The action builds from Dockerfile in the repo — no external image dependency. Inputs: evidence, config, framework, output-format, output-file.
# .github/workflows/wardex-gate.yml
jobs:
security-gate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Wardex Release Gate
uses: had-nu/wardex@v2.1.1
with:
evidence: vulns.yaml
config: .wardex/config.yaml
framework: nist-csf
- name: Handle exit codes
if: failure()
run: |
case $? in
10) echo "BLOCK: Gate risk exceeded" ;;
11) echo "GAP: Compliance control missing" ;;
12) echo "EXPLOIT: Active vulnerability" ;;
esac
Exit code mapping in pkg/gate/gate.go:
| Code | Meaning | When |
|---|---|---|
| 0 | PASS | Risk within appetite |
| 10 | BLOCK | Gate risk exceeded threshold |
| 11 | GAP_WARN | Compliance control not evidenced |
| 12 | ACTIVE_EXPLOIT | Actively exploited CVE detected |
Code 12 triggers CRA Article 14 artefact generation (cmd/art14/art14.go). The artefact is HMAC-SHA256 signed with WARDEX_ACCEPT_SECRET and appended to the JSONL audit log. The pipeline must handle the routing — the action provides the exit code, not the notification infrastructure.
wardex assess --output html renders compliance gap analysis as a standalone HTML page. Dark/light mode, SVG risk bars, framework badge summary. Template at pkg/report/templates/report.html (213 lines, embedded via //go:embed).
wardex assess controls.yaml \
--framework iso27001 \
--output html \
--out-file compliance-posture.html
Generated page includes: control coverage table, Layer Delta (documented vs implemented), risk heatmap per asset, and Art14 artefact audit trail. No JavaScript runtime required.
31 controls mapped across Govern, Identify, Protect, Detect, Respond, Recover. File: pkg/catalog/nist_csf.yaml. Same input schema as ISO 27001, NIS2, and DORA — the assess command evaluates all four with a single control inventory:
wardex assess controls.yaml --framework iso27001 # Existing
wardex assess controls.yaml --framework nis2 # Existing
wardex assess controls.yaml --framework dora # Existing
wardex assess controls.yaml --framework nist-csf # v2.1
Framework-agnostic assessment means one YAML control file serves multiple regulatory regimes. The mapping from control to framework requirement is in the YAML — the engine reads the framework field on each control and filters accordingly (pkg/catalog/catalog.go:30).
Every v2.1 release includes:
.sig + .crt files per artifact, signed with cosign sign-blob using GitHub OIDC identitycosign verify-blob \
--signature wardex-2.1.1-linux-amd64.tar.gz.sig \
--certificate wardex-2.1.1-linux-amd64.tar.gz.crt \
--certificate-identity-regexp 'https://github.com/had-nu/wardex/.github/workflows/.*' \
wardex-2.1.1-linux-amd64.tar.gz
No SLSA attestation — deferred from the v2.0 hardening spec and not implemented in v2.1. The signing setup (.goreleaser.yaml) uses cosign v3 format with explicit --output-signature and --output-certificate flags.
The Docker image works with any orchestrator that supports OCI images. Entry point is the binary — no assumptions about storage, networking, or sidecars.
# Dockerfile for pipeline gate
FROM ghcr.io/had-nu/wardex:2.1.1 AS wardex
FROM alpine:3.20
COPY --from=wardex /wardex /usr/local/bin/wardex
COPY wardex-config.yaml controls.yaml /config/
ENTRYPOINT ["wardex", "evaluate", "--config", "/config/wardex-config.yaml", "--evidence"]
This pattern copies only the binary — 18 MB static Go binary, no runtime dependencies. Evidence files are provided at invoke time via volume mount or as subsequent arguments.
Wardex commands accept --output json. The JSON schemas are stable within a major version. Ingestion into Splunk, Elastic, or Datadog requires shipping the JSON output to their respective agents — no native connectors exist.
wardex evaluate --evidence vulns.yaml --config wardex-config.yaml --output json
wardex art14 list --output json
Exit code 12 events produce a JSON record with CVE, EPSS, CVSS, and Art14 artefact ID. The consuming pipeline decides what to do with it.
The artefact lifecycle is CLI-native. No web UI, no database, no ticket system integration.
# Detect active exploit → artefact created automatically
wardex evaluate --evidence vulns.yaml --config wardex-config.yaml
# Review pending notifications
wardex art14 list
# Acknowledge within 72h window
wardex art14 mark-dispatched wardex-art14-CVE-2024-3094-1718882320
# Confirm remediation
wardex art14 finalize wardex-art14-CVE-2024-3094-1718882320 \
--patch-date "$(date -Iseconds)"
The JSONL audit log (.wardex/audit.log) is the source of truth for the CRA compliance timeline. Each artefact includes cra_status with awareness_timestamp, early_warning_deadline, report_deadline, and correction_deadline. Deadlines are computed from detection timestamp, verified on mark-dispatched and finalize. Expiry detection is available via wardex art14 list --expired.
Action builds from source, not from GHCR. The action.yml uses image: Dockerfile rather than image: docker://ghcr.io/had-nu/wardex:2.1.1. This guarantees the action runs the exact code at the referenced commit — no skew between the action version and the image tag. Cold start is ~1-2 min for the first invocation; subsequent runs on the same runner cache the layer. For security gates that run in parallel with compilation jobs, this is negligible.
Wardex is a CLI that produces signed artifacts and exit codes. No daemon, no database, no webhook receiver. The audit log is a JSONL file on the filesystem. The HTML report is a static page. Integration with SIEMs, ticket systems, or notification channels is the consuming pipeline's responsibility — Wardex provides the data (JSON stdout, exit codes, signed artefacts) and the contract (stable schema within a major version). This keeps adoption immediate and troubleshooting trivial.
SBOM + signing enables, but doesn't enforce, supply-chain verification. Release artifacts include CycloneDX SBOM and cosign .sig + .crt per binary. Whether the consumer verifies before deployment is their process. The chain stops at "this binary was built by the GitHub Actions workflow at revision X." No SLSA attestation in v2.1 — deferred from the v2.0 hardening spec and not yet implemented.
Multi-framework support is a data design decision, not a modelling one. The risk formula (CVSS × EPSS × layer delta) is framework-agnostic. Each control in the YAML declares which frameworks it applies to (pkg/catalog/*.yaml). The assess command filters, not adapts. Adding a framework is a catalog maintenance task, not an engine change.
No persistent EPSS cache. Each wardex enrich invocation hits the FIRST.org API. In pipelines scanning hundreds of CVEs, this may cause throttling. File-based caching with TTL is planned for v2.2 and is the subject of an ongoing integration specification for ENISA EUVD data.
Audit log is ephemeral in CI. The JSONL artefact log lives in the runner filesystem. Persisting it across pipeline runs requires actions/upload-artifact or equivalent — not built into the tool. Same pattern as the EPSS cache: external state is the environment's concern.
CRA Article 14 enforcement begins September 2026. Wardex produces the signed, timestamped artefacts that constitute regulatory evidence. The tool's scope is the evidence — the pipeline and compliance workflow around it belong to the operator.