Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
df29db4
Add GitHub Actions workflow for Docker Scout security scanning
johlju Jul 19, 2025
acc6605
Add max-mode SBOM and provenance support for Docker Scout in build wo…
johlju Jul 19, 2025
7380dcb
Add 'sarif' and 'cves' to ignored words in cspell configuration
johlju Jul 19, 2025
c6da434
Fix typo in exit-on comment for vulnerability handling in Docker Scou…
johlju Jul 19, 2025
38bff18
Add section for testing max-mode attestations locally in CONTRIBUTING.md
johlju Jul 19, 2025
acd3692
Add Docker Scout security scanning workflow for pull requests
johlju Jul 19, 2025
0e19d5e
Restrict Docker build platforms to linux/amd64 for compatibility
johlju Jul 19, 2025
30b9bb8
Fix typos and improve clarity in Docker Scout workflow
johlju Jul 19, 2025
f0307ee
Fix typo in outputs key for Docker Scout image export
johlju Jul 19, 2025
95519d0
Update Docker Scout workflow to export OCI image and scan local archi…
johlju Jul 19, 2025
baebf4e
Refactor Docker Scout workflow to build and push images to a local re…
johlju Jul 19, 2025
3a6985c
Fix Docker registry startup command and adjust build settings for loc…
johlju Jul 19, 2025
6a6681f
Update Docker Scout workflow to use 127.0.0.1 for local registry and …
johlju Jul 19, 2025
1bc715c
Enhance Docker Scout workflow by adding explicit login step for Docke…
johlju Jul 19, 2025
3446c2a
Add organization parameter for baseline pull and refine Docker Hub lo…
johlju Jul 19, 2025
48ae3d7
Refactor Docker Scout workflow to use GitHub Container Registry for l…
johlju Jul 19, 2025
53c75c4
Add permission for package writing to allow pushing to GHCR
johlju Jul 19, 2025
d4fde12
Update Docker Scout workflow to use secrets for GHCR login credentials
johlju Jul 19, 2025
21e3204
Add Docker Hub authentication to Docker Scout step
johlju Jul 19, 2025
cd6ec5a
Refactor Buildx setup and environment variables in Docker Scout workflow
johlju Jul 19, 2025
d0a9bce
Update platforms in Docker build step to support multi-architecture
johlju Jul 19, 2025
df46682
Update Docker Scout action to use separate fields for Docker Hub cred…
johlju Jul 19, 2025
736a29a
Add Docker Hub and GHCR authentication to Docker Scout step
johlju Jul 19, 2025
1bccbbc
Update Docker build-push action to v6 and remove latest tag from image
johlju Jul 19, 2025
616e858
Update Docker Scout step to use secrets for GHCR user credentials
johlju Jul 19, 2025
0522bd4
Update Docker Scout step to fetch PR image from GHCR and compare agai…
johlju Jul 19, 2025
efb680e
Refactor Docker login step to separate Docker Hub authentication from…
johlju Jul 19, 2025
9fd84db
Remove commented-out Docker Hub and GHCR credentials from Docker Scou…
johlju Jul 19, 2025
662715c
Add checkout step for Docker Scout policies and update policy path
johlju Jul 19, 2025
60bae6f
Refactor secret injection for GH_READ_TOKEN in Docker build step
johlju Jul 19, 2025
24f3db0
Refactor secret injection for GH_READ_TOKEN in Docker workflows
johlju Jul 19, 2025
9c0066a
Update BuildKit instructions for Docker and Docker Compose in CONTRIB…
johlju Jul 19, 2025
562b8f2
Update Docker Scout action to include recommendations in CVE command
johlju Jul 19, 2025
5365050
Remove checkout step for Docker Scout policies from workflow
johlju Jul 19, 2025
33a5be7
Merge branch 'main' into f/scout-workflow
johlju Feb 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
tags: devshell-dsc:${{ github.sha }}
# Only inject the secret when it exists – empty values are ignored
secrets: | # inject read token
gh_read_token=${{ env.GH_READ_TOKEN }}
${{ env.GH_READ_TOKEN != '' && format('gh_read_token={0}', env.GH_READ_TOKEN) }}
sbom: mode=max # max-mode SBOM for Scout
provenance: mode=max # max-mode provenance for Scout
push: false
2 changes: 1 addition & 1 deletion .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ jobs:
builder: ${{ steps.buildx.outputs.name }}
context: .
secrets: | # inject read token
gh_read_token=${{ env.GH_READ_TOKEN }}
${{ env.GH_READ_TOKEN != '' && format('gh_read_token={0}', env.GH_READ_TOKEN) }}
# If we use build cache we might not be able bump to latest version installed by Dockerfile when pushing a new tag
# cache-from: "type=registry,ref=ghcr.io/viscalyx/devshell-dsc:buildcache"
# cache-to: "type=registry,ref=ghcr.io/viscalyx/devshell-dsc:buildcache,mode=max"
Expand Down
93 changes: 93 additions & 0 deletions .github/workflows/scout-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Container security (Docker Scout)

on:
pull_request:
branches: [ main ]
paths:
- '**/Dockerfile' # rebuild only when something container‑related changes
- '.github/workflows/**'

jobs:
scout:
runs-on: ubuntu-latest
permissions: # required for PR comments + Code‑scanning upload
contents: read
pull-requests: write
security-events: write
packages: write # allow pushing to GHCR

env:
IMAGE_NAME: ${{ github.repository }}
TAG: pr-${{ github.event.number }}

steps:
- uses: actions/checkout@v4

- name: Set up Buildx
id: buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker-container
driver-opts: |
network=host

- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
registry: docker.io
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USERNAME }} # GitHub username
password: ${{ secrets.GHCR_TOKEN }} # PAT with packages:write scope

- name: Build & push PR and baseline images to GHCR
uses: docker/build-push-action@v6
env:
GH_READ_TOKEN: ${{ secrets.GH_READ_TOKEN }} # provide token for provenance
with:
builder: ${{ steps.buildx.outputs.name }} # use configured Buildx builder
secrets: | # inject read token
${{ env.GH_READ_TOKEN != '' && format('gh_read_token={0}', env.GH_READ_TOKEN) }}
context: .
platforms: |
linux/amd64
linux/arm64
tags: |
ghcr.io/${{ github.repository }}:${{ env.TAG }}
sbom: mode=max # max-mode SBOM for Scout
provenance: mode=max # max-mode provenance for Scout
push: true # push both tags to GHCR

Comment on lines +60 to +65
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Comment/tag mismatch – clarify which tags are pushed.
The step comment says “push both tags to GHCR” but only one tag (pr-<nr>) is listed. Either add the second tag (e.g. :latest-pr) or update the comment to avoid confusion.

🤖 Prompt for AI Agents
In .github/workflows/scout-pr.yml around lines 60 to 65, the comment states that
both tags are pushed to GHCR, but only one tag is specified in the tags field.
To fix this, either add the second tag (such as :latest-pr) to the tags list so
both tags are pushed, or update the comment to accurately reflect that only one
tag is being pushed to avoid confusion.

- name: Scan image with Docker Scout
id: scout
uses: docker/scout-action@v1
with:
# dockerhub-user: ${{ secrets.DOCKERHUB_USERNAME }} # Docker Hub user for Scout auth
# dockerhub-password: ${{ secrets.DOCKERHUB_TOKEN }} # Docker Hub token for Scout auth
# registry-user: ${{ secrets.GHCR_USERNAME }} # GHCR user for fetching PR image
# registry-password: ${{ secrets.GHCR_TOKEN }} # GHCR token for fetching PR image
command: cves,recommendations,compare # list CVEs and compare to prod baseline
image: ghcr.io/${{ github.repository }}:${{ env.TAG }}
organization: ${{ github.repository_owner }} # namespace for baseline pull
# --- comparison baseline ---------------------------------------
to: docker.io/${{ github.repository }}:latest # pull baseline from Docker Hub
# --- what should make the step fail -----------------------------
only-severities: critical,high # we tolerate ≤ medium
exit-code: true # fail if *any* matching CVE left
exit-on: vulnerability # fail if comparison adds new vulnerabilities
only-fixed: true # ignore unfixed issues
# --- UX helpers --------------------------------------------------
sarif-file: scout-results.sarif # upload to Security tab
write-comment: true # nice PR comment
summary: true
github-token: ${{ secrets.GITHUB_TOKEN }} # token for PR comment

- name: Upload SARIF to GitHub code-scanning
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: scout-results.sarif
57 changes: 57 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,63 @@ docker compose build --no-cache dev

Max-mode attestations are automatically enabled in CI/CD workflows for production builds and security scanning. However, developers can test these locally to verify Docker Scout integration or troubleshoot attestation-related issues.

### Prerequisites for Local Attestation Testing

- Docker BuildKit enabled (automatically enabled in modern Docker versions)
- Docker Scout CLI (optional, for local scanning)

### Building with Max-Mode Attestations

To build locally with the same attestation settings used in production:

```sh
# Basic build with max-mode attestations
DOCKER_BUILDKIT=1 docker build \
--sbom=mode=max \
--provenance=mode=max \
-t devshell:dsc .
```

```sh
# No-cache build with max-mode attestations
DOCKER_BUILDKIT=1 docker build \
--no-cache \
--sbom=mode=max \
--provenance=mode=max \
-t devshell:dsc .
```

### Testing with Docker Scout Locally

If you have Docker Scout CLI installed, you can test the security scanning locally:

```sh
# Build with attestations
DOCKER_BUILDKIT=1 docker build \
--sbom=mode=max \
--provenance=mode=max \
-t devshell:dsc .

# Scan for vulnerabilities
docker scout cves devshell:dsc

# Compare with latest published image (requires Docker Hub access)
docker scout compare devshell:dsc --to viscalyx/devshell-dsc:latest
```

> [!NOTE]
> Max-mode attestations add additional build time and storage overhead. They are primarily useful for:
>
> - Testing the full CI/CD security pipeline locally
> - Debugging attestation-related issues
> - Verifying Docker Scout integration before pushing changes
>
> For regular development and testing, the standard build commands without attestations are sufficient.

## Publishing

Max-mode attestations are automatically enabled in CI/CD workflows for production builds and security scanning. However, developers can test these locally to verify Docker Scout integration or troubleshoot attestation-related issues.

Max-mode attestations add additional build time and storage overhead. They are primarily useful for:

- Testing the full CI/CD security pipeline locally
Expand Down
5 changes: 4 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
"sarif",
"shellcheck",
"viscalyx",
"viscalyxbot"
"viscalyxbot",
"sarif",
"cves",
"buildkit"
]
}