wwwdsawr# One offline container archive per tool

Each archive below is a complete Docker-format image, loadable by Docker or
Podman without pulling another image. All are Linux x86_64/amd64.

| Tool | Archive under `images/` | Image tag |
|---|---|---|
| Gitleaks 8.30.1 | `gitleaks-8.30.1-linux-amd64.tar` | `localhost/devsecops/gitleaks:8.30.1` |
| Syft 1.51.1 | `syft-1.51.1-linux-amd64.tar` | `localhost/devsecops/syft:1.51.1` |
| Grype 0.118.0 | `grype-0.118.0-linux-amd64.tar` | `localhost/devsecops/grype:0.118.0` |
| Trivy 0.74.0 | `trivy-0.74.0-linux-amd64.tar` | `localhost/devsecops/trivy:0.74.0` |
| OWASP ZAP 2.17.0 | `zap-stable-amd64.tar` | `localhost/devsecops/zap:20260909` |

The four new images each contain only their named scanner. Grype carries its
own vulnerability database; Trivy carries its database, Java index and checks.
Gitleaks and Syft contain neither database. ZAP remains its original standalone
image. The previous combined scanner archive is retained for compatibility;
the default Drone examples now use the separate tool images.

## Load the tools

From this directory, verify your independently authenticated transfer manifest:

```bash
sha256sum --check --quiet SHA256SUMS
podman load -i images/gitleaks-8.30.1-linux-amd64.tar
podman load -i images/syft-1.51.1-linux-amd64.tar
podman load -i images/grype-0.118.0-linux-amd64.tar
podman load -i images/trivy-0.74.0-linux-amd64.tar
podman load -i images/zap-stable-amd64.tar
bash containers/test-tools-offline.sh
```

On a Drone Docker runner host, use `docker load` and run the test as
`CONTAINER_ENGINE=docker bash containers/test-tools-offline.sh`. Docker and
Podman use separate stores. Load as the account that will run the containers.
The fixture test needs host Bash, Git and Python 3, uses new temporary files,
and runs containers with `--network=none --pull=never`. It publishes no ports.

## Run scans independently

Use absolute paths to your source directory, application image archive and a
report directory outside the source tree. Example inputs below are placeholders.
Create the report directory before running containers. Use `:Z` for a private
SELinux bind mount, or an appropriately managed shared label for concurrent jobs.

```bash
podman run --rm --pull=never --network=none \
  -v /srv/source/app:/input:ro,Z -v /srv/reports/build-001:/reports:Z \
  localhost/devsecops/gitleaks:8.30.1 tool-security source /input /reports/gitleaks

podman run --rm --pull=never --network=none \
  -v /srv/source/app:/input:ro,Z -v /srv/reports/build-001:/reports:Z \
  localhost/devsecops/trivy:0.74.0 tool-security source /input /reports/trivy

podman run --rm --pull=never --network=none \
  -v /srv/source/app:/input:ro,Z -v /srv/reports/build-001:/reports:Z \
  localhost/devsecops/syft:1.51.1 tool-security source /input /reports/sbom

podman run --rm --pull=never --network=none \
  -v /srv/reports/build-001:/reports:Z \
  localhost/devsecops/grype:0.118.0 tool-security sbom /reports/sbom/sbom.syft.json /reports/grype
```

Require every command to succeed before promotion. Syft writes `sbom.syft.json`
and `sbom.cdx.json`; Grype reads the first file from the shared report volume.
Grype returns 2 for findings at High/Critical severity. Any scanner/database
error also blocks promotion. Gitleaks rejects shallow Git histories. Trivy's
source gate covers vulnerability and misconfiguration findings.

For application container archives, mount your actual Docker archive at
`/input/app.tar` and use `tool-security image /input/app.tar REPORT_DIR` in
both the Trivy and Syft containers; pass Syft's resulting SBOM to Grype as above.
An image archive is an input file, so no Docker/Podman socket is required.

For ZAP, use the existing baseline against your authorized staging HTTP service:

```bash
podman run --rm --pull=never --user 0 \
  -v /srv/reports/zap:/zap/wrk:Z \
  localhost/devsecops/zap:20260909 \
  zap-baseline.py -t https://staging.example.internal -r zap.html -J zap.json \
  -z '-dir /tmp/zap-ci -config autoupdate.checkOnStart=false -config autoupdate.checkAddonUpdates=false'
```

Use your internal staging network and CA configuration. ZAP needs connectivity
to the target; the loopback fixture is the network-disabled acceptance test.
The baseline crawls and performs passive analysis. Authenticated/active testing
requires application-specific context and test credentials.

## Drone and release utilities

For a complete push → image build → Syft/Grype/Trivy example, start with
[my-app/README.md](my-app/README.md). It includes a ready `.drone.yml`, a real
Dockerfile, one combined security gate and a webhook acceptance test.

`drone/source.yml` separates Gitleaks, Trivy, Syft and Grype into individual
steps. `drone/release.yml` also separates artifact scans and uses the standalone
ZAP image. Syft precedes Grype, and shared evidence volumes carry the SBOMs.
`drone/selftest.yml` checks tool startup and absence of the other scanners.
The full fixture acceptance test is the shell harness above.

`evidence-tools package|verify|archive|upload` is a small utility command in the
four new scanner images. It preserves the existing checksum/release and HTTPS
evidence-upload behavior without requiring the combined scanner. Pipeline
utility steps use the Gitleaks image. No release signing tool is included.
See [Drone integration](DRONE-CONTAINERS.md) for the required application hooks.

## Offline build provenance and maintenance

`containers/prepare-tool-runtime.py` constructs a runtime from the first two
verified layers of the existing pinned ZAP Docker archive: Debian Bookworm and
its OS dependencies. It omits all subsequent application layers, including ZAP.
It retains package metadata and licenses. This runtime includes Git, Python,
Bash, Java and browser/OS dependencies from the upstream layer; it is not a
minimal or RHEL userspace image. Full standalone archives repeat these shared
base layers; a container store deduplicates them after loading.

Each `containers/Containerfile.TOOL` then adds only that scanner, its license,
configuration and required database. No packages or databases are downloaded.
To rebuild all four images and refresh their exports:

```bash
bash containers/build-tools-offline.sh
bash containers/test-tools-offline.sh
python3 scripts/make-manifest.py
sha256sum --check --quiet SHA256SUMS
```

Authenticate your updated transfer manifest. Refresh Grype and Trivy snapshots
before their seven-day limit and rebuild their images; do not disable freshness
gates. Approve the runtime's vulnerabilities separately from these functional
tests. See [per-tool validation](metadata/PER-TOOL-VALIDATION.md).
