Secrets (SSH deploy key, TLS certificate private key) interpolated into shell commands and logged unredacted (CWE-532)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 37.4k
- Forks
- 3k
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 73
Description
To Reproduce
- Create an Application or Compose using the Git provider with an SSH URL (
git@host:org/repo) and an SSH key. - Cause the clone command to fail. A reliable trigger: an SSH host whose
ssh-keyscanreturns non-zero (e.g.hf.co), which aborts theset -eclone script beforegit clone. - On the Dokploy host:
docker service logs dokploy 2>&1 | grep -A3 "BEGIN OPENSSH PRIVATE KEY" - The configured private key is printed in plaintext inside the logged command string.
Current vs. Expected behavior
Current: when a shell command fails, the full command string is logged to the service logs. Some commands embed a private key directly in the string, so the key is written to docker service logs in plaintext.
Commands that embed a private key:
packages/server/src/utils/providers/git.ts:47and:77— SSH deploy key:echo "${sshKey.privateKey}" > /tmp/id_rsapackages/server/src/services/certificate.ts:113— TLS certificate private key:echo "${privateKey}" | base64 -d > "${keyPath}"(theserverId/ remote path; the local branch usesfs.writeFileSyncand is unaffected)
The command is stored and logged unredacted:
packages/server/src/utils/process/ExecError.ts—commandis a public field andgetDetailedMessage()includes itpackages/server/src/utils/process/execAsync.ts— the rawcommandis attached inexecAsync(L31),execAsyncStream(L60/L93) andexecAsyncRemote(L178)- it is then logged at
execAsync.ts:91andutils/builders/index.ts:185viaconsole.log(error). The sameconsole.log(error)/console.error(error)ofExecErrorobjects recurs across the backups/restore/notifications paths, so any command built with an embedded secret can leak the same way (e.g. DB credentials in backup/restore commands, tokens in HTTPS clone URLs).
Expected: private keys are never placed into a command string, and secrets are redacted before any command / stdout / stderr is logged.
Severity / scope
Low. Reading these logs requires privileged access to the host (docker/root), and a host-root actor can already read the same keys from Dokploy's local database — so the log exposure grants little incremental access. The practical risk is secrets propagating into forwarded log aggregators / retention systems whose read access is broader than host root. This is a secret-hygiene / defense-in-depth issue (CWE-532), not a remotely exploitable vulnerability.
Suggested fix
- Do not interpolate private keys into shell commands. Provision the key file out of band — write via stdin / SFTP for remote servers, or write locally then transfer — so the key never appears in a command string.
- Redact secrets in
ExecErrorbefore storing/logging: mask content betweenBEGIN/ENDkey markers and base64 blobs piped tobase64 -d, incommand/stdout/stderr. - Avoid logging bare error objects in the deploy/build/backup paths; log a sanitized message instead.
Provide environment information
Dokploy version: 0.29.8
Host OS: Ubuntu 24.04 LTS, x86_64 (Docker Swarm, single manager)
Deploy target: remote server (Docker Compose), custom Git over SSH
Which area(s) are affected?
Application, Docker Compose, Remote server, Traefik (certificate provisioning)
Are you deploying the applications where Dokploy is installed or on a remote server?
Both — the git code path applies to local and remote; the certificate path is remote-only.
Will you send a PR to fix it?
No
Contributor guide
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 with packages/server/src/utils/providers/git.ts, packages/server/src/services/certificate.ts, and the ExecError and execAsync files to trace how secret-bearing commands become logged. Compare local and remote paths, then check the deploy, build, backup, and restore logging mentioned in the issue. Done means private keys and other embedded secrets no longer appear in command, stdout, stderr, or service logs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, git, typescript
- Domain
- backend, devops, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100