Skip to content
Open
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions migrate/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
FROM debian:bookworm-slim@sha256:0104b334637a5f19aa9c983a91b54c89887c0984081f2068983107a6f6c21eeb
FROM docker.io/library/debian:bookworm-slim@sha256:0104b334637a5f19aa9c983a91b54c89887c0984081f2068983107a6f6c21eeb

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Run the container as a non-root user.

The image currently runs as root (no USER set), which unnecessarily increases blast radius for a migrations container.

Suggested hardening
 FROM docker.io/library/debian:bookworm-slim@sha256:0104b334637a5f19aa9c983a91b54c89887c0984081f2068983107a6f6c21eeb
 ARG TARGETARCH
@@
 COPY ./migrations /migrations
+RUN useradd --system --no-create-home --uid 10001 migrator && \
+    chown -R 10001:10001 /migrations /usr/local/bin
+USER 10001:10001
 
 ENV MYSQL_DB=""

Also applies to: 16-16

🧰 Tools
🪛 Trivy (0.69.3)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)


[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@migrate/Dockerfile` at line 1, The Dockerfile currently runs as root (only a
FROM line); add a non-root user and switch to it: create a user/group (eg.
migration:migration or uid/gid 1000), chown any migration artifacts/directories
the container needs (e.g., /app, /migrations, or whatever paths are created
later in this Dockerfile or referenced by the migration process), and set USER
to that non-root user before the container starts the migration command. Ensure
any files created during build that must be writable are owned by that user and
that no privileged operations require root at runtime.

ARG TARGETARCH

RUN apt-get update -y && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/* && \
curl -L https://github.com/golang-migrate/migrate/releases/download/v4.17.1/migrate.linux-amd64.tar.gz | tar xvz && \
curl -L https://github.com/golang-migrate/migrate/releases/download/v4.17.1/migrate.linux-${TARGETARCH}.tar.gz | tar xvz && \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the Dockerfile and related workflow files mentioned in the comment
ls -R

echo "---- migrate/Dockerfile ----"
sed -n '1,200p' migrate/Dockerfile | nl -ba

echo "---- .github/workflows/build.yml (relevant range) ----"
if [ -f .github/workflows/build.yml ]; then
  sed -n '150,260p' .github/workflows/build.yml | nl -ba
else
  echo "Missing .github/workflows/build.yml"
fi

echo "---- .github/workflows/push.yml (relevant range) ----"
if [ -f .github/workflows/push.yml ]; then
  sed -n '140,240p' .github/workflows/push.yml | nl -ba
else
  echo "Missing .github/workflows/push.yml"
fi

Repository: TryGhost/ActivityPub

Length of output: 18034


🌐 Web query:

golang-migrate v4.17.1 migrate.linux-amd64.tar.gz sha256

💡 Result:

The official SHA256 checksum for the golang-migrate v4.17.1 linux-amd64 binary artifact is provided within the sha256sum.txt file located in the official GitHub release [1]. To verify the integrity of the file, you can download the checksum file directly from the release page: https://github.com/golang-migrate/migrate/releases/download/v4.17.1/sha256sum.txt You can verify the downloaded file using the following command: curl -sSLO https://github.com/golang-migrate/migrate/releases/download/v4.17.1/migrate.linux-amd64.tar.gz curl -sSLO https://github.com/golang-migrate/migrate/releases/download/v4.17.1/sha256sum.txt grep "migrate.linux-amd64.tar.gz" sha256sum.txt | sha256sum -c If the file is valid, the command will output "migrate.linux-amd64.tar.gz: OK". [1][2]

Citations:


🌐 Web query:

golang-migrate release signature verification tar.gz gpg

💡 Result:

The golang-migrate project does not provide detached GPG signatures for individual release tar.gz files on its GitHub releases page [1][2]. Instead, the project distributes binary packages (such as.deb and.rpm) via Packagecloud, which provides a GPG key for verifying the integrity of the repository metadata and packages [3]. If you are using the official Linux installation instructions for.deb packages, you should import the project's GPG key from Packagecloud to verify the repository [3][4][5]: curl -fsSL https://packagecloud.io/golang-migrate/migrate/gpgkey | sudo gpg --dearmor -o /etc/apt/keyrings/migrate.gpg After importing the key, you configure your source list to use the verified GPG key for package operations [4][6]: deb [signed-by=/etc/apt/keyrings/migrate.gpg] https://packagecloud.io/golang-migrate/migrate/ubuntu/ $(lsb_release -sc) main While GitHub releases themselves are marked with verified signatures for individual commits [2], this refers to the developer's commit signing on GitHub rather than a GPG-signed checksum file or detached signature for the downloadable build artifacts (tar.gz files). If you are downloading source code or binaries directly from the GitHub releases page, there is no GPG signature provided for those specific files to verify against [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- migrate/Dockerfile ----"
sed -n '1,160p' migrate/Dockerfile | cat -n

echo "---- migrate/Dockerfile USER occurrences ----"
rg -n "^\s*USER\s+|USER\s+" migrate/Dockerfile || true

echo "---- Search workflows for TARGETARCH / platforms / manifest ----"
rg -n "TARGETARCH|matrix\.platform|platforms:|\bmanifest\b|buildx|docker/build-push-action" .github/workflows || true

echo "---- Show relevant workflow sections ----"
ls .github/workflows | head
sed -n '1,260p' .github/workflows/build.yml | cat -n 2>/dev/null || true
sed -n '1,260p' .github/workflows/push.yml | cat -n 2>/dev/null || true

Repository: TryGhost/ActivityPub

Length of output: 27247


Verify the downloaded golang-migrate artifact checksum and run as non-root.

  • migrate/Dockerfile downloads migrate.linux-${TARGETARCH}.tar.gz via curl and extracts it without any integrity check; golang-migrate publishes a sha256sum.txt for the release, so use that (and curl -fsSL to fail fast).
  • migrate/Dockerfile has no USER directive, so the container defaults to running as root at runtime.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@migrate/Dockerfile` at line 7, Replace the unverified curl/extract step that
fetches "migrate.linux-${TARGETARCH}.tar.gz" with a fail-fast download (use curl
-fsSL) and verify the artifact against the release's sha256sum.txt (download the
corresponding sha256 file, check the archive with sha256sum -c, and abort on
mismatch), then extract only after verification and clean up checksums/archives;
additionally, create a non-root user/group in the Dockerfile and add a USER
directive so the resulting image does not run as root by default (ensure the
migrate binary is owned/executable by that user).

mv migrate /usr/bin/

COPY bin /usr/local/bin
Expand Down
Loading