matomo-org / matomo-org/docker
Harden file_env() to avoid persisting Docker Secrets as plaintext environment variables
Nobody has claimed this yet.
- Dominant language
- Shell
- Stars
- 1k
- Forks
- 384
- PR merge metrics
- No merged PRs in 30d
Description
**Title:** Harden `file_env()` to avoid persisting Docker Secrets as plaintext environment variables
**Body:**
## Summary
`docker-entrypoint.sh`'s `file_env()` function resolves `*_FILE` environment variables (the standard Docker Secrets pattern) by reading the referenced file and re-exporting its contents as a plaintext environment variable. For example, `MATOMO_DATABASE_PASSWORD_FILE=/run/secrets/db_password` becomes `MATOMO_DATABASE_PASSWORD=`, and this resolved value persists in the container's environment for its full lifetime, inherited by every child process (Apache/PHP workers, cron jobs, spawned shells).
This means any code that later executes within the PHP/web server process — e.g. via a plugin vulnerability or file upload flaw — can trivially retrieve the database credential via a single `getenv()` call, even though it was originally supplied via Docker Secrets specifically to avoid that exposure path.
## Context
This was reported and triaged via HackerOne (report #3859557), and closed as Informative — correctly, since resolving `*_FILE` into an env var is the standard `docker-library` `file_env` convention shared by the official Postgres, MariaDB, MySQL, and WordPress images, and exploiting it requires a separate code-execution primitive to already exist. I'm opening this issue at the triager's suggestion, as a hardening improvement rather than a vulnerability report.
## Suggested improvement
After Matomo's configuration file (`config/config.ini.php`) is generated from these values, the resolved environment variables could be unset so they don't persist for the container's remaining lifetime:
```sh
unset MATOMO_DATABASE_HOST
unset MATOMO_DATABASE_USERNAME
unset MATOMO_DATABASE_PASSWORD
unset MATOMO_DATABASE_DBNAME
```
This would reduce the exposure window from "the entire container lifetime" to "just the entrypoint's initialization phase," without changing any documented behavior or breaking compatibility with existing deployments.
## Reproduction
```bash
mkdir -p ./secrets
echo -n "examplepassword" > ./secrets/db_password.txt
docker run -d --name matomo-test \
-e MATOMO_DATABASE_PASSWORD_FILE=/run/secrets/db_password \
-v $(pwd)/secrets/db_password.txt:/run/secrets/db_password:ro \
matomo:apache
docker exec matomo-test sh -c 'cat /proc/1/environ | tr "\0" "\n" | grep MATOMO_DATABASE_PASSWORD'
# MATOMO_DATABASE_PASSWORD=examplepassword
```
Verified against `matomo:apache` `5.11.2`.
Happy to submit a PR implementing the `unset` change if that's welcome.
<img width="1427" height="603" alt="Image" src="https://github.com/user-attachments/assets/b95ea95c-f8b3-4431-9eda-70049fcc905d" />
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in docker-entrypoint.sh and trace file_env() through generation of config/config.ini.php. Reproduce with the provided Docker Secrets example, then verify the resolved MATOMO_DATABASE_* values are no longer present in the container environment after initialization while Matomo still has the expected database configuration.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, shell
- Domain
- devops, security
- Issue type
- Feature
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100