fix(full-image): make tsunami-linter usable under a non-root container user
Summary
The full image exposes /usr/bin/tsunami-linter, but that path is a symbolic link into /root/go/bin. Because /root is mode 0700, the globally named command cannot be resolved or executed when the container is run with a non-root user.
Target repository: google/tsunami-security-scanner.
Steps to reproduce
Use the currently published amd64 image by digest:
image='ghcr.io/google/tsunami-scanner-full@sha256:26973ab2614c7e7280d3b757aa24faf63b20b1a871832b54d75df8f5064b32e2'
# The installed entry point starts as root.
docker run --rm --platform linux/amd64 "$image" \
bash -lc 'command -v tsunami-linter; tsunami-linter --help; printf "status=%s\n" "$?"'
# The same global entry point is inaccessible to a non-root user.
docker run --rm --platform linux/amd64 --user 65534:65534 "$image" \
bash -lc '
id
command -v tsunami-linter
printf "lookup_status=%s\n" "$?"
/usr/bin/tsunami-linter
printf "run_status=%s\n" "$?"
'Expected behavior
An executable deliberately exposed at /usr/bin/tsunami-linter should be invokable when the container runs with a non-root user, just like the image's other global wrapper commands.
A direct closure check is to run the second command under --user 65534:65534 and confirm that:
command -v tsunami-lintersucceeds.- The linter process starts without
Permission denied.
Actual behavior
The command is present and starts with the image's default root user:
/usr/bin/tsunami-linter
status=0With UID/GID 65534, shell lookup fails and direct execution returns status 126:
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
lookup_status=1
bash: line 1: /usr/bin/tsunami-linter: Permission denied
run_status=126Affected area
- The linter installation step in
full.Dockerfile. - Non-root use of the published
ghcr.io/google/tsunami-scanner-fullimage.
Runtime or environment
- Image:
ghcr.io/google/tsunami-scanner-full@sha256:26973ab2614c7e7280d3b757aa24faf63b20b1a871832b54d75df8f5064b32e2 - OCI source revision:
363ba87b3543f8ae8e4304d3416818f03da7f262 - OCI version:
nightly - Image platform:
linux/amd64 - Host: Docker Desktop on macOS arm64, using Docker's
linux/amd64platform support - Reproducing user: UID/GID
65534:65534(nobody:nogroupin the image)
Evidence
The current full.Dockerfile installs the linter with Go's root-default install path and then creates this global link:
/usr/bin/tsunami-linter -> /root/go/bin/linterThe relevant runtime permissions are:
drwx------ 1 root root 4096 /root
drwxr-xr-x 4 root root 4096 /root/go
drwxr-xr-x 2 root root 4096 /root/go/bin
-rwxr-xr-x 1 root root 8233436 /root/go/bin/linter
lrwxrwxrwx 1 root root 19 /usr/bin/tsunami-linter -> /root/go/bin/linterAlthough the binary and link are executable, a non-root process cannot traverse /root to reach the link target. The tested image's org.opencontainers.image.revision label exactly matches the cited source revision.
The live open-issue searches for tsunami-linter and /root/go/bin/linter returned no matching report in google/tsunami-security-scanner on 2026-08-08.
Impact
Container platforms and local workflows that enforce a non-root UID cannot use the linter shipped by the full image. The failure is misleading because the public /usr/bin entry point exists, yet normal command lookup treats it as unavailable and direct execution only reports a permissions error.
Source: google/tsunami-security-scanner