Understanding security implications of secrets vs. env vars in Docker Compose

Hi :wave:t2:

I have a question of understanding about the difference between using secrets instead of environment variables in Docker Compose. In the official docs, I find the following statement:

Docker Compose provides a way for you to use secrets without having to use environment variables to store information. If you’re injecting passwords and API keys as environment variables, you risk unintentional information exposure. Services can only access secrets when explicitly granted by a secrets attribute within the services top-level element.

Environment variables are often available to all processes, and it can be difficult to track access. They can also be printed in logs when debugging errors without your knowledge. Using secrets mitigates these risks.

The highlighted text confuses me. Assuming I have a very simple ASP.NET Core application inside a Docker Compose stack like this:

services:
  aspnet_sample:
    user: app
    environment:
      - MyFirstPassword=SuperSecret
    image: mcr.microsoft.com/dotnet/samples:aspnetapp
    ports:
      - "8080:8080"
    secrets:
      - MySecondPassword
secrets:
  MySecondPassword:
    file: ./MySecondPassword.txt

Let’s further assume that I ran the following commands:

chown app MySecondPassword.txt
chmod 600 MySecondPassword.txt

This is my current understanding:

  • Only the user app can access the file MySecondPassword.txt.
  • The Docker container runs as app user. Therefore, it can access the file MySecondPassword.txt.

What I don’t understand is why this is more secure than using environment variables. Of course, in my rather contrived example the env var MyFirstPassword is part of the docker-compose.yml, but that could be mitigated by using an *.env file.

Environment variables are often available to all processes, […]. Using secrets mitigates these risks.

How can a Docker container contain multiple processes, running as different users? Or putting it differently: how can there be another process inside the Docker container that does not run as app and therefore cannot access the file MySecondPassword.txt but can access the environment variable? My understanding has always been that everything inside a container runs under the same user - but under this assumption, the statement from the docs does not make a lot of sense to me :thinking:

Or is it more about the fact that one can always execute docker exec aspnet_sample env and thereby exfiltrate secrets whereas the access to the file MySecondPassword.txt from the outside is more limited?

Thx for some clarifying words :slightly_smiling_face:

If you have an api endpoint that allows to dump environment variables (e.g. for troubleshooting in production) then secrets in environment variables wouldn’t be secret anymore. A good example for this is the Java Actuator Endpoint, which if done wrong allows dumping environment variables.

It is less likely someone accidentally reads a file and outputs its content in an endpoint. I am not saying it’s impossible that someone still comes up with the brilliant idea to do so… but it is less likely…

2 Likes

Hi

We can jump into your container by starting /bin/sh as the entrypoint then, one the console is displayed, we can run the printenv command to dump OS variables.

1 Like

Thank you guys :+1:t2:

So my suspicion was more or less correct: it’s more about the fact that revealing secrets in env vars is more likely/easy than files. The official docs gave me the impression that there is something more than this simple fact.

It is, depending on how you look at it :slight_smile:

Your conclusion is correct, if the compose file is deployed as docker compose project

Though, if the compose file is deployed as swarm stack, real secret resources are created and shared in encrypted state to all swarm cluster nodes. Thus, the files containing the secrets do not necessarily have to exist on any node.

1 Like