mirror of
https://github.com/Dokploy/dokploy.git
synced 2026-07-21 22:05:23 +02:00
fix(security): escape compose path and validate custom compose command
- composePath / appName are now passed through shell-quote in createCommand,
getCreateEnvFileCommand and services/compose.ts deploy commands, instead of
being interpolated raw into 'docker compose'/'docker stack' shell commands.
- compose.command: sanitizeCommand was cosmetic (trim + strip quotes). It now
rejects shell control characters (; & | ` $ () {} <> newline), which a normal
docker compose CLI line never contains, blocking breakout into host commands.
Closes GHSA-8r5w-vqjr-8c44, GHSA-5xv2-7f8w-9j5c, GHSA-qh6h-669j-77rw
This commit is contained in:
@@ -67,9 +67,20 @@ Compose Type: ${composeType} ✅`;
|
||||
return bashCommand;
|
||||
};
|
||||
|
||||
// Shell control characters that must never appear in a user-provided compose
|
||||
// command: they would let it break out of the `docker ${command}` invocation
|
||||
// into arbitrary host commands. A normal docker compose CLI line never needs them.
|
||||
const UNSAFE_COMPOSE_COMMAND = /[;&|`$(){}<>\n\\]/;
|
||||
|
||||
const sanitizeCommand = (command: string) => {
|
||||
const sanitizedCommand = command.trim();
|
||||
|
||||
if (UNSAFE_COMPOSE_COMMAND.test(sanitizedCommand)) {
|
||||
throw new Error(
|
||||
"Invalid characters in compose command: shell control characters are not allowed",
|
||||
);
|
||||
}
|
||||
|
||||
const parts = sanitizedCommand.split(/\s+/);
|
||||
|
||||
const restCommand = parts.map((arg) => arg.replace(/^"(.*)"$/, "$1"));
|
||||
@@ -88,9 +99,9 @@ export const createCommand = (compose: ComposeNested) => {
|
||||
let command = "";
|
||||
|
||||
if (composeType === "docker-compose") {
|
||||
command = `compose -p ${appName} -f ${path} up -d --build --remove-orphans`;
|
||||
command = `compose -p ${quote([appName])} -f ${quote([path])} up -d --build --remove-orphans`;
|
||||
} else if (composeType === "stack") {
|
||||
command = `stack deploy -c ${path} ${appName} --prune --with-registry-auth`;
|
||||
command = `stack deploy -c ${quote([path])} ${quote([appName])} --prune --with-registry-auth`;
|
||||
}
|
||||
|
||||
return command;
|
||||
@@ -124,8 +135,8 @@ export const getCreateEnvFileCommand = (compose: ComposeNested) => {
|
||||
|
||||
const encodedContent = encodeBase64(envFileContent);
|
||||
return `
|
||||
touch ${envFilePath};
|
||||
echo "${encodedContent}" | base64 -d > "${envFilePath}";
|
||||
touch ${quote([envFilePath])};
|
||||
echo "${encodedContent}" | base64 -d > ${quote([envFilePath])};
|
||||
`;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user