Skip to content

Fix container running as root in Dockerfile#1717

Merged
StuartFerguson merged 5 commits intomasterfrom
copilot/fix-dockerfile-user-permission
Apr 7, 2026
Merged

Fix container running as root in Dockerfile#1717
StuartFerguson merged 5 commits intomasterfrom
copilot/fix-dockerfile-user-permission

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 7, 2026

Without a USER instruction, the container process runs as root, violating least-privilege principles and flagged as a high-severity security issue by Codacy.

Changes

  • TransactionProcessor/Dockerfile: In the final stage, create a dedicated non-root user (appuser) with explicit UID/GID 10001, no login shell, and switch to it before the entrypoint. The COPY instruction also sets ownership directly via --chown=appuser:appuser.
RUN groupadd --gid 10001 appuser \
    && useradd --uid 10001 --gid appuser --shell /usr/sbin/nologin appuser
COPY --from=publish --chown=appuser:appuser /app/publish .
USER appuser
ENTRYPOINT ["dotnet", "TransactionProcessor.dll"]

@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented Apr 7, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

TIP This summary will be updated as you push new changes. Give us feedback

Copilot AI changed the title [WIP] Fix security issue by specifying user in Dockerfile Fix container running as root in Dockerfile Apr 7, 2026
Copilot AI requested a review from StuartFerguson April 7, 2026 12:54
@StuartFerguson
Copy link
Copy Markdown
Member

@copilot here is what was done in one of my other repositories

FROM base AS final
WORKDIR /app
RUN groupadd --gid 10001 appuser
&& useradd --uid 10001 --gid appuser --shell /usr/sbin/nologin appuser
COPY --from=publish --chown=appuser:appuser /app/publish .
USER appuser
ENTRYPOINT ["dotnet", "TransactionProcessorACL.dll"]

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 7, 2026

@copilot here is what was done in one of my other repositories

FROM base AS final
...

Updated in commit 29f4d0f to match that pattern — explicit UID/GID 10001, --shell /usr/sbin/nologin, and --chown=appuser:appuser on the COPY instruction.

@StuartFerguson StuartFerguson marked this pull request as ready for review April 7, 2026 14:01
@StuartFerguson
Copy link
Copy Markdown
Member

@copilot my docker container now doesnt start in my integration tests, can you have a look why this could be

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 7, 2026

@copilot my docker container now doesnt start in my integration tests, can you have a look why this could be

The container was crashing before Kestrel could start because StatementFilePollerService.Start() calls Directory.CreateDirectory("/home/txnproc/statements/outbound") during app startup (app.PreWarm()). The /home/txnproc/ directory in the base image is owned by root, so appuser got an UnauthorizedAccessException, which caused the process to exit before ever binding to port 5002 — hence the "Connection refused" health check failures.

Fixed in commit 9d4d7a9: the RUN step in the final stage now pre-creates /home/txnproc/statements/outbound and runs chown -R appuser:appuser /home/txnproc so appuser owns the entire directory tree (trace logs, config, and the statements listening directory) before the app starts.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • f.feedz.io
    • Triggering command: /usr/bin/dotnet dotnet restore TransactionProcessor/TransactionProcessor.csproj grep -l er\|TransactionProcessorContainer\|txnprocbase\|aspnetapp cessor/TransactionProcessor/TransactionProcessor.BusinessLogic/Services/StatementBuilder.cs rep aspnetapp ionValidationSer--norc de/node/bin/grep--noprofile grep -l ProcessorContainer\|TransactionProcessorContainer\|txnprocbase\|aspnetapp onProcessor/TransactionProcessor.Reconciliation.DomainEvents/TransactionProcessor.Reconciliationstatus nfig/composer/vendor/bin/grep aspnetapp s.Tests.csproj rep grep (dns block)
    • Triggering command: /usr/bin/dotnet dotnet test TransactionProcessor.Tests/TransactionProcessor.Tests.csproj --no-restore -nologo ProcessorContainer\|TransactionProcessorContainer\|txnprocbase\|aspnetapp onProcessor/TransactionProcessor.Aggregates.Tests/TransactionProcessor.Aggregates.Tests.csproj nfig/composer/vendor/bin/grep aspnetapp DomainService.csls-files rep grep -l ProcessorContainer\|TransactionProcessorContainer\|txnprocbase\|aspnetapp onProcessor/TransactionProcessor.DomainEvents/TransactionProcessor.DomainEvents.csproj /home/REDACTED/.local/bin/grep aspnetapp oj nfig/composer/vendor/bin/grep grep (dns block)
    • Triggering command: /usr/bin/dotnet dotnet test TransactionProcessor.Tests/TransactionProcessor.Tests.csproj --no-restore -nologo ProcessorContain-nxv onProcessor/TransactionProcessor.IntegrationTests/TransactionProcessor.IntegrationTests.csproj ep aspnetapp ionValidationExc-c tnet/tools/grep grep -l (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@StuartFerguson StuartFerguson merged commit 06db5f6 into master Apr 7, 2026
7 checks passed
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.

[Security] By not specifying a USER, a program in the container may run as 'root'. This is a security hazard.

2 participants