Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: false positive AVD-DS-0011 #5392

Closed
vmarchese opened this issue Oct 12, 2023 · 16 comments
Closed

bug: false positive AVD-DS-0011 #5392

vmarchese opened this issue Oct 12, 2023 · 16 comments
Labels
kind/bug Categorizes issue or PR as related to a bug. scan/misconfiguration Issues relating to misconfiguration scanning

Comments

@vmarchese
Copy link

vmarchese commented Oct 12, 2023

Describe the bug
Scanning an image for Dockerfile misconfiguration with the command

trivy image --image-config-scanners config ...

with a layered Dockerfile containing a COPY command that copies a file from a builder layer as in:

COPY --from=builder somefile /somepath/somefile

fails with the message

CRITICAL: Slash is expected at the end of COPY command argument '/somepath/somefile'
══════════════════════════════════════════════════════════
When a COPY command has more than two arguments, the last one should end with a slash.

See https://avd.aquasec.com/misconfig/ds

It looks like the rego rule implemented in copy_with_more_than_two_arguments_not_ending_with_slash.rego does not take into account the COPY command flags

To Reproduce

Write a simple Dockerfile that copies a file from a builder image

@nikpivkin
Copy link
Contributor

Hi @vmarchese !

What are your versions of docker and Trivy?

@vmarchese
Copy link
Author

❯ trivy -v
Version: 0.45.1
Vulnerability DB:
  Version: 2
  UpdatedAt: 2023-10-12 12:16:39.10633075 +0000 UTC
  NextUpdate: 2023-10-12 18:16:39.10633025 +0000 UTC
  DownloadedAt: 2023-10-12 12:19:33.086508 +0000 UTC
Policy Bundle:
  Digest: sha256:1df8ade71efc830877ca3b1130f83e0c6368e3a45b0d4c0f0418955501644054
  DownloadedAt: 2023-10-12 12:22:50.276607 +0000 UTC

❯ docker -v
Docker version 24.0.6, build ed223bc820

@nikpivkin
Copy link
Contributor

@vmarchese Thanks! Can you show the output of the docker image history <your_image> command ?

@vmarchese
Copy link
Author

vmarchese commented Oct 12, 2023

> docker image history myimage
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
7f2f4d6c08b2   25 hours ago   /bin/sh -c #(nop)  ENTRYPOINT ["/app/server"]   0B
<missing>      25 hours ago   /bin/sh -c #(nop)  USER appuser                 0B
<missing>      25 hours ago   /bin/sh -c #(nop) COPY file:e62be48b501e30f7…   782B
<missing>      25 hours ago   /bin/sh -c #(nop) COPY file:dbf1ce21196d2f5a…   27.3MB
<missing>      25 hours ago   /bin/sh -c #(nop) COPY file:5bcbbabf74e2e1db…   1.22kB
<missing>      25 hours ago   /bin/sh -c #(nop) COPY file:cee95daa6036230f…   215kB
<missing>      25 hours ago   /bin/sh -c #(nop) COPY dir:78c3d824fe8276c61…   1.07MB
<missing>      25 hours ago   /bin/sh -c #(nop)  EXPOSE 2112 8080             0B
<missing>      25 hours ago   /bin/sh -c #(nop) WORKDIR /app                  0B

btw, this is a "from scratch" image with a go executable inside. The Dockerfile snippet in question is:

FROM scratch
WORKDIR /app
EXPOSE 8080 2112

# Import from builder.
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /workspace/bin/server /app/server
COPY banner.txt /app/banner.txt

# Use an unprivileged user.
USER appuser

ENTRYPOINT ["/app/server"]

I think the count of the COPY args could be fixed by filtering out the flags with something like:

count_args := [ x | x := copy.Value[_]; not startswith(x, "--")]
cnt := count(count_args) -1 

@vmarchese
Copy link
Author

vmarchese commented Oct 12, 2023

or better...

cnt := count([ x | x := copy.Value[_]; not startswith(x, "--")]) -1 

@nikpivkin
Copy link
Contributor

@vmarchese Strangely, I have not been able to reproduce the problem:

FROM alpine as builder

COPY test.txt /workspace/bin/test.txt

FROM scratch
WORKDIR /app

COPY --from=builder /workspace/bin/test.txt /app/test.txt
trivy image --image-config-scanners config test-img
2023-10-12T21:49:07.988+0700    INFO    Container image config scanners: ["config"]
2023-10-12T21:49:07.989+0700    INFO    Vulnerability scanning is enabled
2023-10-12T21:49:07.989+0700    INFO    Misconfiguration scanning is enabled
2023-10-12T21:49:07.989+0700    INFO    Secret scanning is enabled
2023-10-12T21:49:07.989+0700    INFO    If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2023-10-12T21:49:07.989+0700    INFO    Please see also https://aquasecurity.github.io/trivy/v0.45/docs/scanner/secret/#recommendation for faster secret detection
2023-10-12T21:49:08.100+0700    INFO    Number of language-specific files: 0

@vmarchese
Copy link
Author

I see a difference if I run trivy with -d. In the image built with your Dockerfile there is no config file detected.

With my image I have:

2023-10-12T16:56:25.569+0200	INFO	Detected config files: 1

@nikpivkin
Copy link
Contributor

@vmarchese
If I add the USER appuser command, Trivy detects the config:

trivy image --image-config-scanners config test-img
2023-10-12T22:03:47.237+0700    INFO    Container image config scanners: ["config"]
2023-10-12T22:03:47.237+0700    INFO    Vulnerability scanning is enabled
2023-10-12T22:03:47.237+0700    INFO    Misconfiguration scanning is enabled
2023-10-12T22:03:47.237+0700    INFO    Secret scanning is enabled
2023-10-12T22:03:47.237+0700    INFO    If your scanning is slow, please try '--scanners vuln' to disable secret scanning
2023-10-12T22:03:47.237+0700    INFO    Please see also https://aquasecurity.github.io/trivy/v0.45/docs/scanner/secret/#recommendation for faster secret detection
2023-10-12T22:03:47.826+0700    INFO    Number of language-specific files: 0
2023-10-12T22:03:47.826+0700    INFO    Detected config files: 1

test-img (dockerfile)

Tests: 26 (SUCCESSES: 25, FAILURES: 1, EXCEPTIONS: 0)
Failures: 1 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 0, CRITICAL: 0)

LOW: Add HEALTHCHECK instruction in your Dockerfile
═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
You should add HEALTHCHECK instruction in your docker container images to perform the health check on running containers.

See https://avd.aquasec.com/misconfig/ds026
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

I think it needs to be investigated.

Could you please share your full docker file?

@vmarchese
Copy link
Author

yes, sorry I had to hide some of the internal urls but it should not change anything. The build is done with Task and I have not included the relative task files...
There is also a Sonarqube step (but I skip it on my M1 )

FROM golang:1.21.1-alpine3.18 AS builder

ARG GOPRIVATE=REDACTED
ARG GOINSECURE
ARG GONOPROXY
ARG GOPROXY=REDACTED
ARG projectKey
ARG version

LABEL builder=$projectKey
ENV projectKey=$projectKey

RUN apk update && \
    apk add --no-cache git=2.40.1-r0 \
                       ca-certificates=20230506-r0 \
                       tzdata=2023c-r1 && \
    update-ca-certificates && \
    adduser -D -g '' appuser

WORKDIR /workspace/

ENV GOPRIVATE=$GOPRIVATE
ENV GOINSECURE=$GOINSECURE
ENV GONOPROXY=$GONOPROXY
ENV GOPROXY=$GOPROXY
ENV GO111MODULE=on

RUN go install github.com/go-task/task/v3/cmd/[email protected] &&\
    go install github.com/mikefarah/yq/[email protected] &&\
    go install github.com/deepmap/oapi-codegen/cmd/[email protected]


# Download dependencies
COPY app/go.mod app/go.mod
COPY app/go.sum app/go.sum
WORKDIR /workspace/app
RUN go mod download

WORKDIR /workspace/

# Copy git files
COPY .git .git


# Copy the build code
COPY pipeline.yaml pipeline.yaml
COPY Taskfile.yaml Taskfile.yaml
COPY .config .config


COPY app app

ENV VERSION=$version
# Build proto and source code
RUN CGO_ENABLED=0 GOOS=linux task src:build

FROM sonarsource/sonar-scanner-cli:4.7 AS sonarscanner

WORKDIR /check

COPY ./app ./code

ARG version
ARG projectKey
ARG qualityGates
ARG token
ARG server
ARG skipSonar

COPY . ./code
ENV SONAR_HOST_URL="$server"

RUN if [ "$skipSonar" = "" ]; \
  then  sonar-scanner \
  -Dsonar.projectKey=$projectKey \
  -Dsonar.projectVersion=$version \
  -Dsonar.sources=./code \
  -Dsonar.qualitygate.wait=$qualityGates \
  -Dsonar.exclusions=**/*_test.go,**/*.pb.go \
  -Dsonar.login=$token; \
  else \
    echo "-------------------------------"; \
    echo "SKIPPING SONARQUBE CHECKS"; \
    echo "-------------------------------"; \
  fi

FROM scratch
WORKDIR /app
EXPOSE 8080 2112

# Import from builder.
COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /workspace/bin/server /app/server
COPY banner.txt /app/banner.txt

# Use an unprivileged user.
USER appuser

ENTRYPOINT ["/app/server"]

@vmarchese
Copy link
Author

vmarchese commented Oct 12, 2023

uhm... I suspect it has something to do with our CI/CD environment
As a matter of fact if I rebuild the image on my Mac I do not get the misconfiguration errors.

Inspecting the images I get:

On my Mac:

┃ ● Layers ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Cmp   Size  Command                                                            
       0 B  FROM 6dc9925546b0573                                               
    1.1 MB  COPY /usr/share/zoneinfo /usr/share/zoneinfo # buildkit
    214 kB  COPY /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ # buildkit
    1.2 kB  COPY /etc/passwd /etc/passwd # buildkit
     26 MB  COPY /workspace/bin/server /app/server # buildkit
     782 B  COPY banner.txt /app/banner.txt # buildkit

The image built in docker (the one that has the errors)

┃ ● Layers ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Cmp   Size  Command                                                                                                 
       0 B  FROM 3fd69bc430c06ea                                                                                    
    1.1 MB  #(nop) COPY dir:78c3d824fe8276c613fe2d144127ffca86629a3c767df24e80ea2313542b0671 in /usr/share/zoneinfo 
    214 kB  #(nop) COPY file:cee95daa6036230fcbf45d10edbd5f2df75ec449e633dfcfa3951819c01dec8b in /etc/ssl/certs/    
    1.2 kB  #(nop) COPY file:5bcbbabf74e2e1db7d06af9ed221579031de263472cefe2d4064ed5eb7bb19d1 in /etc/passwd        
     27 MB  #(nop) COPY file:dbf1ce21196d2f5a7fd9eeac1426fd3201de8a593e7563d9ec253085fd208731 in /app/server           
     782 B  #(nop) COPY file:e62be48b501e30f7b698566a4b7ae4bbbe422636e3dff56a7dd0b9e45008cf90 in /app/banner.txt 

Nevertheless, I guess the rego rule should be fixed

@vmarchese
Copy link
Author

❯ docker -v
Docker version 24.0.6, build ed223bc820

Our CI/CD system has docker 20.10.17 and I see in the layers that the COPY command is

COPY file:dbf1ce21196d2f5a7fd9eeac1426fd3201de8a593e7563d9ec253085fd208731 in /app/server

maybe is that ?

@vmarchese
Copy link
Author

vmarchese commented Oct 13, 2023

As a matter of fact this is the complete message:

CRITICAL: Slash is expected at the end of COPY command argument '/app/banner.txt'
════════════════════════════════════════════════════════════════════════════
When a COPY command has more than two arguments, the last one should end with a slash.

See https://avd.aquasec.com/misconfig/ds011
──────────────────────────────────────────────────────
myregistry/my-image:1.1.0-SNAPSHOT:7
──────────────────────────────────────────────────────
   7 [ COPY file:e62be48b501e30f7b698566a4b7ae4bbbe422636e3dff56a7dd0b9e45008cf90 in /app/banner.txt
──────────────────────────────────────────────────────
```

@nikpivkin
Copy link
Contributor

@vmarchese I reproduced this with 20.10.17 docker.

@nikpivkin nikpivkin transferred this issue from aquasecurity/defsec Oct 17, 2023
@github-actions
Copy link

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Oct 17, 2023
@nikpivkin nikpivkin reopened this Oct 17, 2023
@nikpivkin nikpivkin changed the title bug: bug: false positive AVD-DS-0011 Oct 17, 2023
@nikpivkin nikpivkin added kind/bug Categorizes issue or PR as related to a bug. scan/misconfiguration Issues relating to misconfiguration scanning and removed bug needs-triage labels Oct 17, 2023
@nikpivkin
Copy link
Contributor

This is easily reproduced by disabling the BuildKit:

DOCKER_BUILDKIT=0 docker build . -t test-img --no-cache

docker history test-img
IMAGE          CREATED          CREATED BY                                      SIZE      COMMENT
4a7104cf6b42   14 seconds ago   /bin/sh -c #(nop)  USER appuser                 0B
541a645d2e47   14 seconds ago   /bin/sh -c #(nop) COPY file:7e46c04ff62f9f5d…   4B
83f0e82295c3   14 seconds ago   /bin/sh -c #(nop) WORKDIR /app                  0B

@nikpivkin
Copy link
Contributor

@simar7 This has been fixed in aquasecurity/trivy-checks#56

@simar7 simar7 closed this as completed Mar 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Categorizes issue or PR as related to a bug. scan/misconfiguration Issues relating to misconfiguration scanning
Projects
None yet
Development

No branches or pull requests

3 participants