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

Cycle during symlink resolution prevents syft/grype scans from enumerating vulnerabilities #206

Open
mathrock opened this issue Oct 30, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@mathrock
Copy link

What happened:
We recently came across an image where a user had accidentally created a symlink loop within their container image. This resulted in the image failing both syft and grype scans.

This could be used by an attacker or developer who wants to hide vulnerabilities through malicious compliance. By generating a symlink loop, syft/grype will error and fail to output results. If scan errors are not closely monitored the image could avoid detection.

What you expected to happen:
Malformed symlinks should be logged, but allow the rest of the syft or grype scans to complete.

How to reproduce it (as minimally and precisely as possible):
Using old, known vulnerable image from webgoat/webgoat-8.0:latest grype shows a bunch of vulns:

% grype webgoat/webgoat-8.0:latest
 ✔ Vulnerability DB                [no update available]
 ✔ Pulled image
 ✔ Loaded image                                                                                                                                                             webgoat/webgoat-8.0:latest
 ✔ Parsed image                                                                                                                sha256:6664051b8808540cf920e5802e7eb025f9cb19346dcb0fc2be137a26979bb111
 ✔ Cataloged packages              [315 packages]
 ✔ Scanned for vulnerabilities     [581 vulnerability matches]
   ├── by severity: 73 critical, 185 high, 152 medium, 60 low, 111 negligible
   └── by status:   304 fixed, 277 not-fixed, 0 ignored

Build a downstream image and create a symlink loop in a cataloged binary, /usr/bin/xz for example:

echo "FROM webgoat/webgoat-8.0:latest
USER root
RUN yes | ln -sfi /usr/bin/xzcat /usr/bin/xz
USER webgoat" | docker build -t symlink-loop:latest .

Syft error:

% syft symlink-loop:latest
 ✔ Loaded image                                                                                                                                                                    symlink-loop:latest
 ✔ Parsed image                                                                                                                sha256:108309a3bb9c201ffe0f2c4fc1300f434485e5216d6edad8c76d6d2ec8d3e7de
 ✔ Cataloged packages              [315 packages]
[0003]  WARN unable to create any package-file relationships cataloger=dpkgdb-cataloger error=unable to find path for path="/usr/bin/xz": cycle during symlink resolution package=xz-utils
[0003]  WARN unable to process mimetypes=[application/x-executable application/x-mach-binary application/x-elf application/x-sharedlib application/vnd.microsoft.portable-executable]: unable to get ref
[0005]  WARN error while cataloging cataloger=graalvm-native-image-cataloger
1 error occurred:
        * failed to find binaries by mime types: unable to get ref for path="/usr/bin/xz": cycle during symlink resolution

Grype error:

% grype symlink-loop:latest
 ✔ Vulnerability DB                [no update available]
 ✔ Loaded image                                                                                                                                                                    symlink-loop:latest
 ✔ Parsed image                                                                                                                sha256:108309a3bb9c201ffe0f2c4fc1300f434485e5216d6edad8c76d6d2ec8d3e7de
 ✔ Cataloged packages              [315 packages]
[0003]  WARN unable to create any package-file relationships cataloger=dpkgdb-cataloger error=unable to find path for path="/usr/bin/xz": cycle during symlink resolution package=xz-utils
[0003]  WARN unable to process mimetypes=[application/vnd.microsoft.portable-executable application/x-executable application/x-mach-binary application/x-elf application/x-sharedlib]: unable to get ref
[0004]  WARN error while cataloging cataloger=graalvm-native-image-cataloger
1 error occurred:
        * failed to catalog: 1 error occurred:
        * failed to find binaries by mime types: unable to get ref for path="/usr/bin/xz": cycle during symlink resolution

Anything else we need to know?:

This issue was validated on latest syft/grype versions:

% syft version
Application: syft
Version:    0.94.0
BuildDate:  2023-10-20T17:21:07Z
GitCommit:  8f6bdde6662aa8050a71eadbdb7bd5a3b079a56d
GitDescription: v0.94.0
Platform:   linux/amd64
GoVersion:  go1.21.3
Compiler:   gc

% grype version
Application:         grype
Version:             0.72.0
BuildDate:           2023-10-20T18:17:05Z
GitCommit:           04df28051b7694a5e4a28fc5b2ea2068f24ef213
GitDescription:      v0.72.0
Platform:            linux/amd64
GoVersion:           go1.21.3
Compiler:            gc
Syft Version:        v0.94.0
Supported DB Schema: 5

Environment:

  • OS (e.g: cat /etc/os-release or similar):
$ cat /etc/os-release
NAME="Red Hat Enterprise Linux Server"
VERSION="7.9 (Maipo)"
ID="rhel"
ID_LIKE="fedora"
VARIANT="Server"
VARIANT_ID="server"
VERSION_ID="7.9"
PRETTY_NAME="Red Hat Enterprise Linux Server 7.9 (Maipo)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:redhat:enterprise_linux:7.9:GA:server"
HOME_URL="https://www.redhat.com/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"

REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 7"
REDHAT_BUGZILLA_PRODUCT_VERSION=7.9
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="7.9"
@mathrock mathrock added the bug Something isn't working label Oct 30, 2023
@wagoodman wagoodman moved this to Ready in OSS Aug 7, 2024
@wagoodman
Copy link
Contributor

If I'm understanding correctly, if there is an infinite symlink within a dir, and it's half way through the entires in a directory, then we're not reading the remaining entires in the directory. There may be more cases here I haven't considered. This is the part of the code we should scrutinize further

// prevent infinite loop
if strings.Count(string(currentPath.Normalize()), file.DirSeparator) >= maxDirDepth {
return currentPath, currentNode.FileNode, ErrMaxTraversalDepth
}

@wagoodman
Copy link
Contributor

@kzantow you pointed out this might play into the known-unknowns work in syft anchore/syft#518 -- specifically noting that there could be symlink loops that is occluding catalogable part of the filetree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Status: Ready
Development

No branches or pull requests

2 participants