fix: prevent SSH private key from leaking into build-failure notifications#4630
Open
jsheely wants to merge 3 commits into
Open
fix: prevent SSH private key from leaking into build-failure notifications#4630jsheely wants to merge 3 commits into
jsheely wants to merge 3 commits into
Conversation
…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.
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.
Author
|
I will note that at least the SSH key is clipped so while it does expose your key it's only about a third of the entire thing and not usable. |
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.
Author
Author
|
Would be nice if we could tease into those docker build file logs and obtain the actual build failure. In this case I have a test project that is meant to fail https://github.com/jsheely/dokploy-build-failure Ideally I would like to get the vite build error not the docker build failure message but that is a job for another PR.
For clarity this is the message from the log. Which is accurate but buries the actionable error message so the discord message won't see it and you have to view the logs.
But like I said, a future PR |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Problem
When a deployment fails, the build-failure notification (Discord, Slack, Telegram, etc.) shows the SSH private key instead of the actual build error. The "Error Message" field renders something like:
This is both a secret-leak (the deploy key ends up in a chat channel) and a usability bug (the real build error is hidden, even though it shows correctly on the deployment tab).
Root cause
A deployment runs as a single shell command whose entire output is redirected into the deployment log file:
For git/SSH sources, the clone step writes the deploy key inline:
When a later step (e.g. the build) fails, Node's
child_process.execsetserror.messageto the whole command string (Command failed: <command>), which therefore contains the echoed private key. Because2>&1already routed the real output into the log file,error.stderris empty — so the error handler fell back to that rawerror.messageand passed it straight tosendBuildErrorNotifications.The actual build error only exists in the log file (which never contains the key, since the
echoredirects the key to a file rather than stdout).Solution
Add
getDeploymentErrorMessageinservices/deployment.ts, which reads the tail of the deployment log — the real build output — and use that as the notification's error message for both application and compose deployments:tail -n N <logPath>over SSH."Error building, check the logs for details."when the log is missing/empty/unreadable.Because the message is now sourced from the log instead of Node's command string, the private key can no longer leak, and notifications show the actual build error.
Changes
packages/server/src/services/deployment.ts— newgetDeploymentErrorMessagehelper.packages/server/src/services/application.ts— use it in the deploy error handler.packages/server/src/services/compose.ts— use it in the deploy error handler.apps/dokploy/__test__/deploy/deployment-error-message.test.ts— unit tests.Testing
Added
deployment-error-message.test.ts(9 tests, all passing) covering:""/".".maxLineslines.Existing
application.command.test.tsstill passes (no regression).