fix: redact private keys from logged command errors#4602
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 84f21b183f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const candidate = error as T & { cmd?: string }; | ||
| candidate.message = redactSecrets(candidate.message); |
There was a problem hiding this comment.
Redact exec error output properties
When a local execAsync command fails after writing a secret to stdout or stderr, the promisified child_process.exec error passed as originalError carries enumerable stdout and stderr properties. ExecError now redacts its own top-level output fields, but console.log(new ExecError(...)) will still print originalError.stdout/stderr, so a failed command that emits a PEM or base64 key before exiting can still leak the same secret this change is trying to remove.
Useful? React with 👍 / 👎.
SSH keys (SSH clone) and base64-encoded TLS keys (remote certificate provisioning) are interpolated into the shell commands Dokploy runs. When a command fails, its ExecError — which carries the full command — is logged, leaking the key to the service logs in plain text. Redact PEM private-key blocks and `echo "<base64>" | base64 -d` payloads on ExecError (command, stdout, stderr, message and any wrapped original error) so no log path can surface them.
84f21b1 to
ff457b4
Compare
What is this PR about?
Private keys can end up in the logs. When Dokploy clones a repository over SSH it writes the SSH key to
/tmp/id_rsaviaecho "<key>", and when it provisions a TLS certificate on a remote server it pipes the base64 key tobase64 -d— both inside shell command strings. On failure the resultingExecErrorcarries the full command (plus stdout/stderr and the wrapped original error) and is logged viaconsole.log(error), so the key lands indocker service logsin plain text and propagates to any forwarded log store.This redacts private-key material at the single point every log path funnels through —
ExecError. A smallredactSecretshelper strips PEM private-key blocks andecho "<base64>" | base64 -dpayloads from the command, stdout, stderr, message and any wrapped original error, so no caller orconsole.log(error)sink can leak them.Reading these logs already requires host/root access, so this is a secret-hygiene / defense-in-depth fix (CWE-532), not a remotely exploitable issue. It follows the same direction as #4579, which kept the registry password out of the login command.
Affected sources for reference:
utils/providers/git.ts(SSH key) andservices/certificate.ts(TLS key); the redaction lives inutils/process/ExecError.tsso it also covers any future secret-bearing command.Checklist
Before submitting this PR, please make sure that:
canarybranch.__test__/process/redact-secrets.test.ts) and verified the redaction against real command output captured fromdocker service logs. The change is confined to log-string redaction and does not alter any deploy path.Issues related (if applicable)
closes #4600