Skip to content

Vulnerability management

This page explains how vulnerabilities are managed in the Security Shepherd platform and its Docker images, and how to check an image yourself. It's about the platform: the login, the admin pages, Tomcat, the operating system and the libraries. The lessons and challenges are vulnerable by design, and scanners don't report on them.

Keeping the images up to date

  • Operating system. The Tomcat image is built on the official tomcat image for Tomcat 11 and Java 17, which runs Ubuntu. The build runs apt-get upgrade, so each image includes the Ubuntu security updates released since its base image was published (#1038).
  • Rebuilds. Every push to dev publishes a new dev image, and every release publishes a new release image, so both pick up the latest updates. A release image never changes once it's published. To get later fixes, move to a newer release.
  • Dependencies. Dependabot checks the Maven dependencies, the base images, the GitHub Actions and the documentation tooling every week. Every Maven dependency's PGP signature is checked on every build.
  • Before each release, the maintainers scan the dev image with Docker Scout, Trivy and Grype, as described in Releasing.

If you build the images yourself, see Building an up-to-date image: Docker caches the base image and the upgrade step, so a plain rebuild can miss updates.

How a finding is handled

Each finding is checked to see whether it affects Security Shepherd:

  • It affects Security Shepherd: it's fixed in the image, by updating the package or library.
  • It doesn't: for example, a vulnerable binary that comes with the base image but never runs. It gets a not_affected statement, with the reason, in .vex/security-shepherd.openvex.json, an OpenVEX document. Findings that do affect Security Shepherd are never listed there.

Each statement names the vulnerable package and version it covers, such as pkg:golang/stdlib@1.27.1. A newer vulnerability in the same binary, or the same vulnerability in another version, is still reported.

Scan an image yourself

The commands use the TAG variable from Verifying the images, for example TAG=4.0.0.

# Scan the image with Docker Scout
docker scout cves "owasp/security-shepherd:$TAG"

# Or scan the SBOM saved in Verifying the images with Grype (https://github.com/anchore/grype)
grype "sbom:./shepherd-$TAG.spdx.json"

Scanners only apply a VEX document when you pass it to them:

curl -sSfLO https://raw.githubusercontent.com/OWASP/SecurityShepherd/dev/.vex/security-shepherd.openvex.json

# Docker Scout trusts only VEX written by Docker unless --vex-author names the author
docker scout cves "owasp/security-shepherd:$TAG" \
  --vex-location security-shepherd.openvex.json \
  --vex-author 'OWASP Security Shepherd maintainers'

# Grype, scanning the image itself so that the VEX document's product matches it
grype "owasp/security-shepherd:$TAG" --vex security-shepherd.openvex.json

# Trivy (https://trivy.dev/). --show-suppressed lists what the VEX document covers.
trivy image --vex security-shepherd.openvex.json --show-suppressed "owasp/security-shepherd:$TAG"

Use the VEX signed for the image

Each image is also published with a signed copy of the VEX document as it was when the image was built. It's signed by the same release workflow as the image's provenance and stored next to the image on Docker Hub. Trivy can read it from there, with no download. These commands also need the REF variable from Verifying the images.

# Proves the VEX document attached to the image came from this repository's release workflow
gh attestation verify "oci://docker.io/owasp/security-shepherd:$TAG" \
  --repo OWASP/SecurityShepherd \
  --signer-workflow OWASP/SecurityShepherd/.github/workflows/release-build.yml \
  --source-ref "$REF" \
  --predicate-type https://openvex.dev/ns/v0.2.0

# Trivy, applying the VEX document attached to the image
trivy image --vex oci --show-suppressed "owasp/security-shepherd:$TAG"

# Or save the image's own signed copy to use with Docker Scout or Grype, in place of the curl
# download above. It's the version signed for this image, rather than the latest file on dev.
gh attestation verify "oci://docker.io/owasp/security-shepherd:$TAG" \
  --repo OWASP/SecurityShepherd \
  --signer-workflow OWASP/SecurityShepherd/.github/workflows/release-build.yml \
  --source-ref "$REF" \
  --predicate-type https://openvex.dev/ns/v0.2.0 \
  --format json --jq '.[0].verificationResult.statement.predicate' > security-shepherd.openvex.json

An image's attached VEX never changes after it's published. Statements added to the file later, for vulnerabilities found since, apply only when you pass the file from dev. Docker Scout and Grype don't read the attached copy, so pass them a file: the signed copy above, or the latest from dev. Older images, including the 3.x releases, have no attached VEX.

If Trivy finds no VEX attached to an image that should have one, you may have an older copy of that tag pulled locally, which Trivy scans in preference. Run docker pull "owasp/security-shepherd:$TAG" first, or add --image-src remote.

Report a vulnerability

If you find a vulnerability in the platform itself, rather than in a lesson or challenge, report it privately through GitHub's private vulnerability reporting. Please don't open a public issue for it.

A vulnerability in a lesson or challenge that lets a player affect the server, other players or the platform is a platform vulnerability too: report it the same way.