google / google/tsunami-security-scanner
fix(full-image): make tsunami-linter usable under a non-root container user
- Dominant language
- Java
- Stars
- 8.6k
- Forks
- 925
- PR merge metrics
- No merged PRs in 30d
Description
## 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:
```sh
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:
1. `command -v tsunami-linter` succeeds.
2. The linter process starts without `Permission denied`.
## Actual behavior
The command is present and starts with the image's default root user:
```text
/usr/bin/tsunami-linter
status=0
```
With UID/GID 65534, shell lookup fails and direct execution returns status 126:
```text
uid=65534(nobody) gid=65534(nogroup) groups=65534(nogroup)
lookup_status=1
bash: line 1: /usr/bin/tsunami-linter: Permission denied
run_status=126
```
## Affected area
- The linter installation step in `full.Dockerfile`.
- Non-root use of the published `ghcr.io/google/tsunami-scanner-full` image.
## 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/amd64` platform support
- Reproducing user: UID/GID `65534:65534` (`nobody:nogroup` in the image)
## Evidence
The current [`full.Dockerfile`](https://github.com/google/tsunami-security-scanner/blob/363ba87b3543f8ae8e4304d3416818f03da7f262/full.Dockerfile#L37-L39) installs the linter with Go's root-default install path and then creates this global link:
```text
/usr/bin/tsunami-linter -> /root/go/bin/linter
```
The relevant runtime permissions are:
```text
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/linter
```
Although 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.
Contributor guide
Research direction
Start with the linter installation step in full.Dockerfile at the cited revision, then reproduce the issue using the published full image and UID/GID 65534:65534. Verify that /usr/bin/tsunami-linter is discoverable and executable as the non-root user, while preserving the existing root-user behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, dockerfile, go
- Domain
- devops, infrastructure
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 85/100