Skip to content

Commit 1f4f940

Browse files
authored
fix: prevent registry password from appearing in error messages and shell commands (#4579)
1 parent e9a0932 commit 1f4f940

3 files changed

Lines changed: 41 additions & 11 deletions

File tree

packages/server/src/services/registry.ts

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,16 @@ export function safeDockerLoginCommand(
2727
return `printf %s ${escapedPassword} | docker login ${escapedRegistry} -u ${escapedUser} --password-stdin`;
2828
}
2929

30+
function sanitizeRegistryError(
31+
error: unknown,
32+
password: string | null | undefined,
33+
): string {
34+
const message =
35+
error instanceof Error ? error.message : "Error with registry login";
36+
if (!password) return message;
37+
return message.split(password).join("***");
38+
}
39+
3040
export const createRegistry = async (
3141
input: z.infer<typeof apiCreateRegistry>,
3242
organizationId: string,
@@ -59,10 +69,15 @@ export const createRegistry = async (
5969
input.username,
6070
input.password,
6171
);
62-
if (input.serverId && input.serverId !== "none") {
63-
await execAsyncRemote(input.serverId, loginCommand);
64-
} else if (newRegistry.registryType === "cloud") {
65-
await execAsync(loginCommand);
72+
try {
73+
if (input.serverId && input.serverId !== "none") {
74+
await execAsyncRemote(input.serverId, loginCommand);
75+
} else if (newRegistry.registryType === "cloud") {
76+
await execAsync(loginCommand);
77+
}
78+
} catch (error) {
79+
const sanitized = sanitizeRegistryError(error, input.password);
80+
throw new TRPCError({ code: "BAD_REQUEST", message: sanitized });
6681
}
6782

6883
return newRegistry;
@@ -129,16 +144,24 @@ export const updateRegistry = async (
129144
});
130145
}
131146

132-
if (registryData?.serverId && registryData?.serverId !== "none") {
133-
await execAsyncRemote(registryData.serverId, loginCommand);
134-
} else if (response?.registryType === "cloud") {
135-
await execAsync(loginCommand);
147+
try {
148+
if (registryData?.serverId && registryData?.serverId !== "none") {
149+
await execAsyncRemote(registryData.serverId, loginCommand);
150+
} else if (response?.registryType === "cloud") {
151+
await execAsync(loginCommand);
152+
}
153+
} catch (execError) {
154+
throw new Error(sanitizeRegistryError(execError, response?.password));
136155
}
137156

138157
return response;
139158
} catch (error) {
140159
const message =
141-
error instanceof Error ? error.message : "Error updating this registry";
160+
error instanceof TRPCError
161+
? error.message
162+
: error instanceof Error
163+
? error.message
164+
: "Error updating this registry";
142165
throw new TRPCError({
143166
code: "BAD_REQUEST",
144167
message,

packages/server/src/utils/cluster/upload.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { findAllDeploymentsByApplicationId } from "@dokploy/server/services/deployment";
22
import {
33
findRegistryByIdWithCredentials,
4+
safeDockerLoginCommand,
45
type Registry,
56
} from "@dokploy/server/services/registry";
67
import { createRollback } from "@dokploy/server/services/rollbacks";
@@ -117,9 +118,14 @@ const getRegistryCommands = (
117118
imageName: string,
118119
registryTag: string,
119120
): string => {
121+
const loginCmd = safeDockerLoginCommand(
122+
registry.registryUrl,
123+
registry.username,
124+
registry.password,
125+
);
120126
return `
121127
echo "📦 [Enabled Registry] Uploading image to '${registry.registryType}' | '${registryTag}'" ;
122-
echo "${registry.password}" | docker login ${registry.registryUrl} -u '${registry.username}' --password-stdin || {
128+
${loginCmd} || {
123129
echo "❌ DockerHub Failed" ;
124130
exit 1;
125131
}

packages/server/src/utils/providers/docker.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { safeDockerLoginCommand } from "@dokploy/server/services/registry";
12
import type { ApplicationNested } from "../builders";
23

34
export const buildRemoteDocker = async (application: ApplicationNested) => {
@@ -13,7 +14,7 @@ echo "Pulling ${dockerImage}";
1314

1415
if (username && password) {
1516
command += `
16-
if ! echo "${password}" | docker login --username "${username}" --password-stdin "${registryUrl || ""}" 2>&1; then
17+
if ! ${safeDockerLoginCommand(registryUrl || "", username, password)} 2>&1; then
1718
echo "❌ Login failed";
1819
exit 1;
1920
fi

0 commit comments

Comments
 (0)