Project: FOSSA (Provisioning / Security & Compliance)
File: scanner.md

- - - - - - - - FOSSA's new container scanner adds support for compliance and vulnerability checks for application dependencies inside of containers. The performance of analysis and support for container image sources is improved, and is more robust for future enhancement. FOSSA's new container scanner brings support for standard FOSSA CLI features into containers: Support for configuration via `.fossa.yml`. Support for path filtering (exclusion and inclusion). Finally, FOSSA's new container scanner improves the user experience and reports more information to FOSSA servers, improving both the information available to users and the ability for FOSSA to debug questions or issues. For example, images scanned with the container scanner show the origin path for each dependency discovered inside the image, just like analysis of a local project. Like the legacy container scanner, the container scanner fully supports the detection of OS dependencies (`apk`, `deb`, etc). Refer to following guides for integrating container scanning in your CI, FOSSA's new container scanner scans the base layer of the image, squashes all other layers, and scans those as well. Scans report compliance and security issues for operating system dependencies and application dependencies. To scan a container image with `fossa-cli`, use the `container analyze` command: ```bash fossa container analyze <IMAGE> fossa container analyze <IMAGE> -o ``` Once the container image has been scanned and the results uploaded to FOSSA, security and compliance issues are reported via the `fossa container test` command. ```bash fossa container test <IMAGE> ``` FOSSA can analyze container images from multiple sources: Exported archive Docker engine Podman OCI container registry (public and private) Docker Hub By default `fossa-cli` attempts to identify `<IMAGE>` source in the following order: ```bash docker save redis:alpine > redis_alpine.tar fossa container analyze redis_alpine.tar ``` ```bash fossa container analyze redis:alpine ``` For this image source to work, `fossa-cli` requires docker to be running and accessible. Specifically, `fossa-cli` uses the Unix socket at `/var/lib/docker.sock`, with `http://localhost/v1.28/` as a base API endpoint. 1) `/_ping`: check connection to docker 2) `images/<IMAGE>/json`: retrieve image manifest 3) `images/<IMAGE>/get`: retrieve image archive In summary, `fossa-cli` performs the equivalent of: ```bash curl --unix-socket /var/run/docker.sock -X GET "http://localhost/v1.28/_ping" curl --unix-socket /var/run/docker.sock -X GET "http://localhost/v1.28/images/redis:alpine/json" curl --unix-socket /var/run/docker.sock -X GET "http://localhost/v1.28/images/redis:alpine/get" > tmp/fossa-cli-docker-engine-artifact-<random-number>/img.tar ``` `fossa-cli` stores this archive in a temporary location and analyzes that archive. ```bash fossa container analyze ghcr.io/fossas/haskell-dev-tools:9.0.2 ``` This step works even if you do not have docker installed or have docker engine accessible. If `<IMAGE>` is not a docker image archive and is not accessible via the docker engine API, `fossa-cli` attempts to retrieve the image via registries based on the content of `<IMAGE>`. `<IMAGE>` is parsed in a similar fashion to `docker pull <ARG>`: | `<IMAGE>` | Registry | Repository | Manifest Reference | | - | | -- | | | `redis` | None (defaults to `index.docker.io`) | `library/redis` | None (defaults to `latest`) | | `redis:alpine` | None (defaults to `index.docker.io`) | `library/redis` | `alpine` (as tag) | | `bitnami/wordpress:6.0.1-debian-11-r14` | None (defaults to `index.docker.io`) | `bitnami/wordpress` | `6.0.1-debian-11-r14` (as tag) | | `ghcr.io/fossas/haskell-dev-tools:9.0.2` | `ghcr.io` | `fossas/haskell-dev-tools` | `9.0.2` (as tag) | | `ghcr.io/fossas/haskell-dev-tools@sha256:e83e...` | `ghcr.io` | `fossas/haskell-dev-tools` | `sha256:e83e...` (as digest) | | `quay.io/org/image:tag` | `quay.io` | `org/image` | `tag` | Note: When the domain is not present, `fossa-cli` defaults to the registry `index.docker.io`. When digest or tag is not present, `fossa-cli` defaults to the tag `latest`. When the registry is `index.docker.io`, and repository does not contain the literal `/`, `fossa-cli` infers that this is official image stored under

When a multi-platform image is provided (e.g. `ghcr.io/graalvm/graalvm-ce:ol7-java11-21.3.3`), `fossa-cli` defaults to selecting image artifacts for current runtime platform. Analyzing the container image for a platform other than the one currently running is possible by specifying the digest for the image on a different platform. For example, the following command analyzes the `arm64` platform image of `ghcr.io/graalvm/graalvm-ce@sha256` regardless of the platform running `fossa container analyze`: ```bash fossa container analyze ghcr.io/graalvm/graalvm-ce@sha256:bdcba07acb11053fea0026b807ecf94550ace7df27b10596ca4c765165243cef ``` Private registries `fossa-cli` automatically infers credentials based on the host name and Docker credential store. This is done in following steps: 1) Identify the host of image source (e.g. `quay.io` for `quay.io/org/image:tag`) 2) Parse Docker config file: `$HOME/.docker/config.json` or `%USERPROFILE%/.docker/config.json` 3) If there is an associated credential helper specified in `credHelpers` it is used. Otherwise, the default helper `credsStore` is used. 4) `fossa-cli` executes `docker-credential-<store>`, similar to following command to retrieve credentials: ```bash > echo "index.docker.io" | docker-credential-desktop get { "ServerURL": "https://index.docker.io", "Username": "username", "Secret": "secret" } ``` If any of the steps above fail, `fossa-cli` defaults to connecting without user credentials. To explicitly provide a username and password, use HTTP-style authentication in the image URL. For this to work the host value must be present in the image URL: ```bash fossa container analyze user:secret@quay.io/org/image:tag ``` Retrieving image from registry `fossa-cli` uses `/v2/` registry api (per OCI distribution spec) for retrieving image manifests, and image artifacts from registry. It does so in following manner: 1) `HEAD <repository>/manifests/<tag-or-digest>` (to see if the manifests exists) 1) If 401 status code is provided, and auth challenge is presented, `fossa-cli` will make request to token provider with mentioned scope and service (if username and password were provided for registry, HTTP auth will be used) to retrieve token. 2) Use token from step (1) to make `GET /v2/<repository>/manifests/<tag-or-digest>` to retrieve manifest 1) If multi-platform image is detected (content-type indicating manifest index, or manifest list), manifest for current runtime's digest will be identified 2) Using (2.a)'s digest value, `GET /v2/<repository>/manifests/<digest>` will be used to infer platform specific manifest 3) Identify configuration blob and layer blobs digests from (2) 4) Download all blobs using `GET /v2/<repository>/blobs/<digest>` (if blobs are tar.gzip, they will be gzip extracted) 5) From artifacts downloaded representative image tarball will be created. All `GET` request from step 2 to step 5, will make `HEAD` call prior to confirm existence of resource. If 401 status is received new access token will be generated using auth flow mentioned in step (1). The new container scanner scans in two steps: The base layer. The rest of the layers, squashed. The following package managers are supported in container scanning: | Analysis | Supported? | Docs | | | | - | | Alpine (APK) | :whitecheckmark: | | | Debian (DPKG) | :whitecheckmark: | | | RedHat (RPM) | :whitecheckmark: | | | Python (setuptools, poetry, etc.) | :whitecheckmark: | | | Javascript (npm, yarn, pnpm, etc.) | :whitecheckmark: | | | Ruby (bundler) | :whitecheckmark: | | | .Net (paket, projectjson,

| :whitecheckmark: | | | Perl | :whitecheckmark: | | | Swift (xcode, swift package manager) | :whitecheckmark: | | | Carthage | :whitecheckmark: | | | Fortran (fpm) | :whitecheckmark: | | | R (renv) | :whitecheckmark: | | | Cocoapods | :warning: | | | Nim (nimble) | :warning: | | | Dart (pub) | :warning: | | | Maven | :warning: | | | Golang (gomod) | :x: | N/A | | Rust (cargo) | :x: | N/A | | Haskell (cabal, stack) | :x: | N/A | | Gradle | :x: | N/A | | Clojure (lein) | :x: | N/A | | Scala (sbt) | :x: | N/A | | Elixir | :x: | N/A | | Erlang | :x: | N/A | Where: :whitecheckmark: - analysis is supported :warning: - partial analysis is supported. Refer to the linked strategy documentation for more details. :x: - analysis is not supported in container scanning. To view the list of projects detected within the container by the above strategies run `fossa container list-targets <ARG> `. `ARG` must be the same value as provided to `fossa container analyze <ARG> ` or `fossa container test <ARG>`. This output can be useful to understand what is going to be analyzed via `fossa container analyze <ARG> `, and if desired can inform . Example output: ```bash ; fossa container list-targets ghcr.io/tcort/markdown-link-check:stable [ INFO] Discovered image for: ghcr.io/tcort/markdown-link-check:stable (of 137610196 bytes) via docker engine api. [ INFO] Exporting docker image to temp file: /private/var/folders/hb/pg5d0r196kq1qdswr6_79hzh0000gn/T/fossa-docker-engine-tmp-f7af2b5d1ec5173d/image.tar! This may take a while! [ INFO] Listing targets exported docker archive: /private/var/folders/hb/pg5d0r196kq1qdswr6_79hzh0000gn/T/fossa-docker-engine-tmp-f7af2b5d1ec5173d/image.tar [ WARN] fossa container list-targets does not apply any filtering, you may see projects which are not present in the final analysis. [ WARN] fossa container list-targets only lists targets for experimental-scanner (when analyzed with flag). [ INFO] Found project: apkdb@lib/apk/db/ (Base Layer) [ INFO] Found target: apkdb@lib/apk/db/ (Base Layer) [ INFO] Found project: setuptools@usr/local/lib/nodemodules/npm/nodemodules/node-gyp/gyp/ (Other Layers) [ INFO] Found target: setuptools@usr/local/lib/nodemodules/npm/nodemodules/node-gyp/gyp/ (Other Layers) [ INFO] Found project: npm@src/ (Other Layers) [ INFO] Found project: npm@opt/yarn-v1.22.5/ (Other Layers) [ INFO] Found target: npm@src/ (Other Layers) [ INFO] Found target: npm@opt/yarn-v1.22.5/ (Other Layers) [ INFO] Found project: apkdb@lib/apk/db/ (Other Layers) [ INFO] Found target: apkdb@lib/apk/db/ (Other Layers) ``` The new container scanner supports configuring analysis targets via `.fossa.yml`, as with a standard `fossa analyze` command. For more information on configuring analysis targets, see . For example, the following `fossa.yml` excludes all `setuptools` targets: ```yaml exclude: type: setuptools ``` `fossa-cli` supports the `--debug` flag and debug bundle generation with the container scanner. ```bash fossa container analyze redis:alpine --debug ``` For best performance prefer analyzing exported docker archive file instead of downloading image from registry. When building in CI, consider saving the image as an artifact and using that for analysis. This improves performance by being able to skip downloading and extracting the image from a registry. Images can be exported to archives using Docker: ```bash docker pull <IMAGE>:<TAG> # or docker pull <IMAGE>@<DIGEST> docker save <IMAGE>:<TAG> > image.tar fossa container analyze image.tar --container scanner rm image.tar ``` By default when `fossa-cli` is analyzing multi-platform image it prefers using the same runtime architecture as the host. If a specific platform is desired, use the digest for that platform: ```bash fossa container analyze ghcr.io/graalvm/graalvm-ce@sha256:bdcba07acb11053fea0026b807ecf94550ace7df27b10596ca4c765165243cef ``` Use the `--only-system-deps` option: ```bash fossa container analyze <IMAGE> --only-system-deps ``` Use a FOSSA configuration file to perform exclusion of projects or paths. Refer to the documentation for more details. As an example, the following configuration file only analyzes `setuptools`, and `alpine` packages: ```yml version: 3 targets: only: type: setuptools type: apkdb ``` ```bash