fix(security): stop user-supplied schedule appName and escape its shell paths

drizzle-zod exposed appName (notNull + $defaultFn) as optional in the insert
schema, letting callers override it; it then flowed unquoted into rm -rf/mkdir
paths. Omit appName from createScheduleSchema and quote() the schedule fullPath
sinks (completes GHSA-fgh8 VULN-015 alongside the mount/patch fixes).
This commit is contained in:
Mauricio Siu
2026-07-20 17:07:32 -06:00
parent 92310ddb14
commit 6943a395fe
2 changed files with 9 additions and 7 deletions

View File

@@ -81,7 +81,7 @@ export const schedulesRelations = relations(schedules, ({ one, many }) => ({
export const createScheduleSchema = createInsertSchema(schedules, {
scheduleType: z.enum(["application", "compose", "server", "dokploy-server"]),
});
}).omit({ appName: true });
export const updateScheduleSchema = createScheduleSchema.extend({
scheduleId: z.string().min(1),

View File

@@ -1,6 +1,7 @@
import path from "node:path";
import { TRPCError } from "@trpc/server";
import { eq } from "drizzle-orm";
import { quote } from "shell-quote";
import type { z } from "zod";
import { IS_CLOUD, paths } from "../constants";
import { db } from "../db";
@@ -142,7 +143,7 @@ export const deleteSchedule = async (scheduleId: string) => {
const { SCHEDULES_PATH } = paths(!!serverId);
const fullPath = path.join(SCHEDULES_PATH, schedule?.appName || "");
const command = `rm -rf ${fullPath}`;
const command = `rm -rf ${quote([fullPath])}`;
if (serverId) {
await execAsyncRemote(serverId, command);
} else {
@@ -198,12 +199,13 @@ const handleScript = async (schedule: Schedule) => {
${schedule?.script || ""}`;
const encodedContent = encodeBase64(scriptWithPid);
const scriptPath = `${fullPath}/script.sh`;
const script = `
mkdir -p ${fullPath}
rm -f ${fullPath}/script.sh
touch ${fullPath}/script.sh
chmod +x ${fullPath}/script.sh
echo "${encodedContent}" | base64 -d > ${fullPath}/script.sh
mkdir -p ${quote([fullPath])}
rm -f ${quote([scriptPath])}
touch ${quote([scriptPath])}
chmod +x ${quote([scriptPath])}
echo "${encodedContent}" | base64 -d > ${quote([scriptPath])}
`;
if (schedule?.scheduleType === "dokploy-server") {