I ran kics (through gitlab) on the following Dockerfile:
# escape=`
FROM <our registry>/<repository path>/dotnet10-ltsc2022:latest
RUN New-Item -ItemType Directory -Path C:\install -Force | Out-Null
ARG VS_VERSION=17
ARG VS_MARKETING=2022
ADD https://aka.ms/vs/$VS_VERSION/release/vs_buildtools.exe C:/install/vs_buildtools.exe
RUN choco install -y visualstudio${Env:VS_MARKETING}buildtools
RUN Start-Process -FilePath C:\install\vs_buildtools.exe -ArgumentList '--quiet --norestart --wait --nocache --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended' -Wait
COPY profile.ps1 C:\Users\ContainerAdministrator\Documents\PowerShell\Microsoft.PowerShell_profile.ps1
RUN Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
RUN Install-Module VSSetup -Force
RUN git clone https://github.com/Microsoft/vcpkg.git C:\install\vcpkg
RUN C:\install\vcpkg\bootstrap-vcpkg.bat
RUN ["pwsh.exe", "-NoLogo", "-Command", "vcpkg integrate install"]
ARG CYCLONEDX_VERSION=0.32.0
ADD https://github.com/CycloneDX/cyclonedx-cli/releases/download/v${CYCLONEDX_VERSION}/cyclonedx-win-x64.exe C:/install/cyclonedx.exe
Expected Behavior
Security findings that are relevant for a Windows container and don't make recommendations against Docker best practices.
Actual Behavior
I received the following findings:
Critical: Missing User instruction
Medium: Gem Install Without Version
Medium: Add Instead of Copy
Medium: Image Version Using 'latest'
Medium: Apt Get Install Pin Version Not Defined
Medium: Yum Install Without Version
Medium: Add Instead of Copy
Info: Zypper Install Without Version
Info: Curl or Wget Instead of Add
Info: Multiple RUN, ADD, COPY Instructions Listed
Info: Curl or Wget Instead of Add
Info: Yum Install Allows Manual Input
Info: Healthcheck Instruction Missing
Info: APT-GET Missing Flags To Avoid Manual Input
The "Missing User Instruction" and "Image Version Using 'latest'" findings are accurate, although the image that we base ourselves off of is maintained by us too and only provides a :latest tag; it also includes a "USER" statement that passes through.
All the findings about gem, zypper, apt and yum are false positives. They trigger on the line where we run "vcpkg integrate install". This is how you run that; there is no further argument. Having to dismiss 6 false positives for one line of code is a bit much.
I question the wisdom of encouraging people to use curl or wget. By using those instead of ADD, you require that to be living inside the image, which increases the attack surface of the resulting image. An image that does not have curl installed is more secure than an image that does. Yes, it is possible to install curl, do a bunch of things, and remove it again, but that's more work than just an ADD command. And yes, it is also possible to have a multi-stage image thing (with multiple FROM lines), but that's more complicated and less accessible. And what attack can be leveraged against ADD that can't be leveraged against curl or wget? The recommendation should be to not download, rather than to download in a particular way. In fact, if you check the "best practices" document that the "Curl or wget" finding links to, it contains this statement:
The ADD instruction is best for when you need to download a remote artifact as part of your build. ADD is better than manually adding files using something like wget and tar, because it ensures a more precise build cache.
(from https://docs.docker.com/build/building/best-practices/#add-or-copy)
In this case, if either aka.ms or github.com is compromised we have a bigger problem, so I didn't bother to update it and dismissed both of those too.
That only leaves the "Multiple RUN, ADD, COPY Instructions Listed" recommendation listed. While the finding is correct, the extra RUN statements were done on purpose, as a way to improve cachability of the image: all the run statements are listed, as much as possible, in order of how likely they are to change: the first ones are least likely to change, the last ones are most likely to change (or depend on other steps that are done before them). By ordering things this way, we avoid having to recreate a Windows image that is larger than 25G in its entirety just because a small application at the end of an install script has changed.
I ran kics (through gitlab) on the following Dockerfile:
Expected Behavior
Security findings that are relevant for a Windows container and don't make recommendations against Docker best practices.
Actual Behavior
I received the following findings:
Critical: Missing User instruction
Medium: Gem Install Without Version
Medium: Add Instead of Copy
Medium: Image Version Using 'latest'
Medium: Apt Get Install Pin Version Not Defined
Medium: Yum Install Without Version
Medium: Add Instead of Copy
Info: Zypper Install Without Version
Info: Curl or Wget Instead of Add
Info: Multiple RUN, ADD, COPY Instructions Listed
Info: Curl or Wget Instead of Add
Info: Yum Install Allows Manual Input
Info: Healthcheck Instruction Missing
Info: APT-GET Missing Flags To Avoid Manual Input
The "Missing User Instruction" and "Image Version Using 'latest'" findings are accurate, although the image that we base ourselves off of is maintained by us too and only provides a
:latesttag; it also includes a "USER" statement that passes through.All the findings about gem, zypper, apt and yum are false positives. They trigger on the line where we run "vcpkg integrate install". This is how you run that; there is no further argument. Having to dismiss 6 false positives for one line of code is a bit much.
I question the wisdom of encouraging people to use curl or wget. By using those instead of ADD, you require that to be living inside the image, which increases the attack surface of the resulting image. An image that does not have curl installed is more secure than an image that does. Yes, it is possible to install curl, do a bunch of things, and remove it again, but that's more work than just an ADD command. And yes, it is also possible to have a multi-stage image thing (with multiple FROM lines), but that's more complicated and less accessible. And what attack can be leveraged against ADD that can't be leveraged against curl or wget? The recommendation should be to not download, rather than to download in a particular way. In fact, if you check the "best practices" document that the "Curl or wget" finding links to, it contains this statement:
(from https://docs.docker.com/build/building/best-practices/#add-or-copy)
In this case, if either aka.ms or github.com is compromised we have a bigger problem, so I didn't bother to update it and dismissed both of those too.
That only leaves the "Multiple RUN, ADD, COPY Instructions Listed" recommendation listed. While the finding is correct, the extra RUN statements were done on purpose, as a way to improve cachability of the image: all the run statements are listed, as much as possible, in order of how likely they are to change: the first ones are least likely to change, the last ones are most likely to change (or depend on other steps that are done before them). By ordering things this way, we avoid having to recreate a Windows image that is larger than 25G in its entirety just because a small application at the end of an install script has changed.