Files
dokploy/packages/server/src/utils/restore/mariadb.ts
Mauricio Siu eeb6e7b8ea fix(security): escape S3/rclone args and restore paths to prevent command injection
Wrap S3 credential flags (getS3Credentials + destination.testConnection), the
listBackupFiles search path, and every restore backupPath/backupFile with
shell-quote's quote() so $(), backticks, quotes and spaces in destination
fields or backupFile can no longer break out of the rclone shell commands.
2026-07-20 16:11:16 -06:00

63 lines
1.7 KiB
TypeScript

import type { apiRestoreBackup } from "@dokploy/server/db/schema";
import type { Destination } from "@dokploy/server/services/destination";
import type { Mariadb } from "@dokploy/server/services/mariadb";
import { quote } from "shell-quote";
import type { z } from "zod";
import { getS3Credentials } from "../backups/utils";
import { execAsync, execAsyncRemote } from "../process/execAsync";
import { getRestoreCommand } from "./utils";
export const restoreMariadbBackup = async (
mariadb: Mariadb,
destination: Destination,
backupInput: z.infer<typeof apiRestoreBackup>,
emit: (log: string) => void,
) => {
try {
const { appName, serverId, databaseUser, databasePassword } = mariadb;
const rcloneFlags = getS3Credentials(destination);
const bucketPath = `:s3:${destination.bucket}`;
const backupPath = `${bucketPath}/${backupInput.backupFile}`;
const rcloneCommand = `rclone cat ${rcloneFlags.join(" ")} ${quote([backupPath])} | gunzip`;
const command = getRestoreCommand({
appName,
credentials: {
database: backupInput.databaseName,
databaseUser,
databasePassword,
},
type: "mariadb",
rcloneCommand,
restoreType: "database",
});
emit("Starting restore...");
emit(
`Restoring database: ${backupInput.databaseName} from ${backupInput.backupFile}`,
);
if (serverId) {
await execAsyncRemote(serverId, command);
} else {
await execAsync(command);
}
emit("Restore completed successfully!");
} catch (error) {
console.error(error);
emit(
`Error: ${
error instanceof Error
? error.message
: "Error restoring mariadb backup"
}`,
);
throw new Error(
error instanceof Error ? error.message : "Error restoring mariadb backup",
);
}
};