Skip to content

fix: prevent SSH private key from leaking into build-failure notifications#63

Open
AminDhouib wants to merge 4 commits into
canaryfrom
port/upr-4630
Open

fix: prevent SSH private key from leaking into build-failure notifications#63
AminDhouib wants to merge 4 commits into
canaryfrom
port/upr-4630

Conversation

@AminDhouib

@AminDhouib AminDhouib commented Jul 12, 2026

Copy link
Copy Markdown
Member

Ports Dokploy#4630 by @jsheely (3 commits, cherry-picked with -x, original authorship preserved).

Vulnerability class

Build-failure notifications embedded the raw exec error.message, which contains the entire failed command line. For deployments cloned over SSH with a custom key, that command string can include the SSH private key material, so the key was forwarded to every configured notification channel.

Fix

  • getDeploymentErrorMessage() (new, in packages/server/src/services/deployment.ts): notifications now report the tail (last 50 lines) of the deployment log — which never contains the key — with a safe generic fallback, both for local and remote (serverId) deployments.
  • deployApplication / deployCompose pass that log-tail message instead of error?.message.
  • truncateErrorMessage() (new, in build-error.ts): channels with length limits (Discord, Lark, Teams) now truncate from the END of the message, so the real error at the bottom of the log stays visible.

Fork notifier audit (Gotify / Ntfy / custom webhook)

Audited the fork's build-error.ts: it is structurally identical to upstream's (Gotify, Ntfy, and the custom webhook notifier exist upstream too — no fork-only drift beyond render vs renderAsync). Since the fix sanitizes the message at the callers (application.ts/compose.ts, the only sendBuildErrorNotifications call sites in the fork), all channels — including Gotify, Ntfy, Pushover, and the custom webhook — receive the sanitized log-tail message. No fork-extension changes were required.

Adaptations

None — all 3 commits applied cleanly onto fork canary.

Test evidence

  • vitest run __test__/deploy/deployment-error-message.test.ts __test__/deploy/truncate-error-message.test.ts: 13/13 passed (Windows local).
  • pnpm --filter=dokploy run typecheck: clean.

Overlap notes

jsheely added 3 commits July 12, 2026 10:35
…d of leaking SSH key

Deployments run as a single shell command whose output is redirected into
the log file ((...) >> logPath 2>&1). When that command fails, Node's exec
error.message is the entire command string, which for git/ssh sources
contains the echo "<private key>" used to write the deploy key. That raw
message was passed straight to build-error notifications, so Discord (and
other channels) showed the SSH private key instead of the actual build error.

Add getDeploymentErrorMessage to read the tail of the deployment log (the
real build output, which never contains the key) and use it as the
notification error message for both application and compose deployments.

(cherry picked from commit e10ac33)
Adds unit tests verifying the deployment error message is read from the
deployment log (the real build error) rather than the raw command string,
so the SSH private key can no longer leak into notifications. Covers local
and remote reads, line limiting, and fallback behaviour.

(cherry picked from commit be56959)
Discord, Lark and Teams capped the error message with
errorMessage.substring(0, 800), which keeps the FIRST 800 characters. Since
the deployment log tail is sent as the error and the actual build error is at
the bottom, this showed the top of the log and cut off the real error.

Extract a truncateErrorMessage helper that keeps the LAST `limit` characters
(prefixed with "...") and use it in all three channels.

(cherry picked from commit afb128b)
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.

2 participants