feat(import): harden untrusted spreadsheet boundaries

This commit is contained in:
2026-03-30 08:02:52 +02:00
parent fac8c1c3a5
commit f6daf21983
13 changed files with 561 additions and 76 deletions
+17 -10
View File
@@ -23,6 +23,13 @@ const paginationSchema = z.object({
const importBatchStatusSchema = z.nativeEnum(ImportBatchStatus);
const stagedRecordStatusSchema = z.nativeEnum(StagedRecordStatus);
const stagedRecordTypeSchema = z.nativeEnum(DispoStagedRecordType);
const workbookPathSchema = z
.string()
.trim()
.min(1, "Workbook path is required.")
.refine((value) => value.toLowerCase().endsWith(".xlsx"), {
message: "Only .xlsx workbook paths are supported.",
});
// ─── Router ──────────────────────────────────────────────────────────────────
@@ -32,12 +39,12 @@ export const dispoRouter = createTRPCRouter({
stageImportBatch: adminProcedure
.input(
z.object({
chargeabilityWorkbookPath: z.string(),
costWorkbookPath: z.string().optional(),
chargeabilityWorkbookPath: workbookPathSchema,
costWorkbookPath: workbookPathSchema.optional(),
notes: z.string().nullish(),
planningWorkbookPath: z.string(),
referenceWorkbookPath: z.string(),
rosterWorkbookPath: z.string().optional(),
planningWorkbookPath: workbookPathSchema,
referenceWorkbookPath: workbookPathSchema,
rosterWorkbookPath: workbookPathSchema.optional(),
}),
)
.mutation(async ({ ctx, input }) => {
@@ -56,13 +63,13 @@ export const dispoRouter = createTRPCRouter({
validateImportBatch: adminProcedure
.input(
z.object({
chargeabilityWorkbookPath: z.string(),
costWorkbookPath: z.string().optional(),
chargeabilityWorkbookPath: workbookPathSchema,
costWorkbookPath: workbookPathSchema.optional(),
importBatchId: z.string().optional(),
notes: z.string().nullish(),
planningWorkbookPath: z.string(),
referenceWorkbookPath: z.string(),
rosterWorkbookPath: z.string().optional(),
planningWorkbookPath: workbookPathSchema,
referenceWorkbookPath: workbookPathSchema,
rosterWorkbookPath: workbookPathSchema.optional(),
}),
)
.query(async ({ input }) => {