mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-14 01:50:39 +09:00
Harden issue artifact metadata
This commit is contained in:
parent
96d266109b
commit
bbf77fcb69
6 changed files with 292 additions and 5 deletions
|
|
@ -16,4 +16,26 @@ describe("attachmentArtifactWorkProductMetadataSchema", () => {
|
|||
expect(parsed.contentType).toBe("video/mp4");
|
||||
expect(parsed.downloadPath).toContain("download=1");
|
||||
});
|
||||
|
||||
it("rejects off-route or scriptable paths", () => {
|
||||
const parsed = attachmentArtifactWorkProductMetadataSchema.safeParse({
|
||||
attachmentId: "11111111-1111-4111-8111-111111111111",
|
||||
contentType: "video/mp4",
|
||||
byteSize: 1234,
|
||||
contentPath: "https://evil.example/video.mp4",
|
||||
openPath: "javascript:alert(1)",
|
||||
downloadPath: "/api/attachments/11111111-1111-4111-8111-111111111111/content",
|
||||
originalFilename: "demo.mp4",
|
||||
});
|
||||
|
||||
expect(parsed.success).toBe(false);
|
||||
if (parsed.success) {
|
||||
throw new Error("Expected invalid attachment artifact metadata");
|
||||
}
|
||||
expect(parsed.error.issues.map((issue) => issue.path.join("."))).toEqual([
|
||||
"contentPath",
|
||||
"openPath",
|
||||
"downloadPath",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import { z } from "zod";
|
||||
|
||||
function attachmentContentPath(attachmentId: string): string {
|
||||
return `/api/attachments/${attachmentId}/content`;
|
||||
}
|
||||
|
||||
export const issueWorkProductTypeSchema = z.enum([
|
||||
"preview_url",
|
||||
"runtime_service",
|
||||
|
|
@ -37,6 +41,29 @@ export const attachmentArtifactWorkProductMetadataSchema = z.object({
|
|||
openPath: z.string().min(1),
|
||||
downloadPath: z.string().min(1),
|
||||
originalFilename: z.string().optional().nullable(),
|
||||
}).superRefine((value, ctx) => {
|
||||
const contentPath = attachmentContentPath(value.attachmentId);
|
||||
if (value.contentPath !== contentPath) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["contentPath"],
|
||||
message: "contentPath must point to the same-origin attachment content route",
|
||||
});
|
||||
}
|
||||
if (value.openPath !== contentPath) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["openPath"],
|
||||
message: "openPath must point to the same-origin attachment content route",
|
||||
});
|
||||
}
|
||||
if (value.downloadPath !== `${contentPath}?download=1`) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["downloadPath"],
|
||||
message: "downloadPath must point to the same-origin attachment download route",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export type AttachmentArtifactWorkProductMetadata = z.infer<typeof attachmentArtifactWorkProductMetadataSchema>;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue