Skip to content

security: Harden Docker image and CI pipeline (OWASP Docker Security compliance)#1060

Merged
BenjaminMichaelis merged 1 commit intomainfrom
agents/docker-security-compliance-review
May 6, 2026
Merged

security: Harden Docker image and CI pipeline (OWASP Docker Security compliance)#1060
BenjaminMichaelis merged 1 commit intomainfrom
agents/docker-security-compliance-review

Conversation

@BenjaminMichaelis
Copy link
Copy Markdown
Member

@BenjaminMichaelis BenjaminMichaelis commented May 6, 2026

Increase docker security

Addresses multiple items from the OWASP Docker Security Cheat Sheet:

- Switch base image to mcr.microsoft.com/dotnet/aspnet:10.0-noble-chiseled
  (smaller attack surface, no shell, fewer CVEs, non-root by default)
- Add USER app directive so container runs as non-root (OWASP Rule 2)
- Remove curl|sh pattern for Azure Artifact Credential Provider
- Replace raw PAT secret with BuildKit --mount=type=secret file (nugetconfig)
  so credentials are never written to any image layer or build cache
- Generate NuGet auth config in CI via heredoc; clean up with if: always()
- Fix PR docker build step: add context and ACCESS_TO_NUGET_FEED=false
- Downgrade Node from non-LTS v25 to Active LTS v24 (Krypton)
@BenjaminMichaelis BenjaminMichaelis marked this pull request as ready for review May 6, 2026 21:47
Copilot AI review requested due to automatic review settings May 6, 2026 21:47
@BenjaminMichaelis BenjaminMichaelis merged commit 1a28ef6 into main May 6, 2026
7 checks passed
@BenjaminMichaelis BenjaminMichaelis deleted the agents/docker-security-compliance-review branch May 6, 2026 21:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR aims to harden the container build and CI pipeline by switching to a more minimal ASP.NET runtime image, running the app as a non-root user, and changing how private NuGet feed credentials are provided during Docker builds.

Changes:

  • Switch runtime base image to a chiseled .NET runtime image and run the container as a non-root user.
  • Update frontend build image version (Node 24).
  • Replace credential provider + PAT env approach with a BuildKit secret-mounted NuGet config generated in CI.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
EssentialCSharp.Web/Dockerfile Moves to chiseled runtime, uses Node 24 for frontend build, and restores via a secret-mounted NuGet config; runs as non-root user.
.github/workflows/Build-Test-And-Deploy.yml Generates a NuGet auth config file for Docker build and passes it as a Buildx secret; adds cleanup.

if [ "$ACCESS_TO_NUGET_FEED" = "true" ]; then \
auth_token=$(cat /run/secrets/nuget_auth_token) && \
export VSS_NUGET_EXTERNAL_FEED_ENDPOINTS="{\"endpointCredentials\": [{\"endpoint\":\"https://pkgs.dev.azure.com/intelliTect/_packaging/EssentialCSharp/nuget/v3/index.json\", \"password\":\"$auth_token\"}]}"; \
RUN --mount=type=secret,id=nugetconfig \
Comment on lines +22 to +23
if [ "$ACCESS_TO_NUGET_FEED" = "true" ] && [ -f /run/secrets/nugetconfig ]; then \
dotnet restore "EssentialCSharp.Web.slnx" --configfile /run/secrets/nugetconfig -p:AccessToNugetFeed=$ACCESS_TO_NUGET_FEED; \
Comment on lines +71 to +87
cat > /tmp/nuget-auth.config << EOF
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="nuget" value="https://api.nuget.org/v3/index.json" />
<add key="EssentialCSharp" value="https://pkgs.dev.azure.com/intelliTect/_packaging/EssentialCSharp/nuget/v3/index.json" />
</packageSources>
<packageSourceCredentials>
<EssentialCSharp>
<add key="Username" value="docker" />
<add key="ClearTextPassword" value="${NUGET_AUTH_TOKEN}" />
</EssentialCSharp>
</packageSourceCredentials>
</configuration>
EOF

Copilot AI mentioned this pull request May 6, 2026
4 tasks
BenjaminMichaelis added a commit that referenced this pull request May 6, 2026
…1062)

## Problem

PR #1060 merged with the `--configfile` approach for Docker NuGet auth.
This approach:
- Discards the repo's `nuget.config` entirely (including
`packageSourceMapping`)
- Caused 401 Unauthorized on the Azure DevOps private feed

The fixup commit from the original PR branch was never applied to main.

## Fix

Switch to **NuGet config layering** (NuGet 5.7+):
- CI generates a **credentials-only** config (no `<packageSources>`)
- Dockerfile copies it to `~/.nuget/config/credentials.config`
- NuGet merges it with the repo's `nuget.config` automatically
- `nuget.config` remains the single source of truth for feeds +
`packageSourceMapping`

### Changes
- **`Dockerfile`**: `cp /run/secrets/nugetconfig
~/.nuget/config/credentials.config` instead of `--configfile`; add
`required=false` on secret mount
- **`Build-Test-And-Deploy.yml`**: credentials-only generated config (no
`<packageSources>` section)

## Testing
- PR build: uses `ACCESS_TO_NUGET_FEED=false` (no auth needed, verifies
image builds)
- Main build: full auth path with layered config

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants