mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-28 04:02:18 +01:00
Reject protocol-relative work product paths
This commit is contained in:
1 parent
8074c5bd11
commit
c84b3e7ca5
2 files changed
+23
-1
No files matched your search
@@ -437,6 +437,28 @@ describe("ExecutionWorkspaceDetail plugin slots", () => {
|
||||
expect(container.querySelector('[data-testid="plugin-slot-mount"]')).toBeNull();
|
||||
});
|
||||
|
||||
it("does not render protocol-relative metadata work-product links", async () => {
|
||||
mockRouteLocation.pathname = "/execution-workspaces/workspace-1/work-products";
|
||||
mockIssuesApi.list.mockResolvedValue([issue()]);
|
||||
mockExecutionWorkspacesApi.get.mockResolvedValue(workspace({
|
||||
workProducts: [
|
||||
workProduct({
|
||||
id: "wp-file",
|
||||
title: "agent-report.html",
|
||||
metadata: {
|
||||
openPath: "//evil.example/report.html",
|
||||
},
|
||||
}),
|
||||
],
|
||||
}));
|
||||
|
||||
await render();
|
||||
|
||||
expect(container.textContent).toContain("agent-report.html");
|
||||
expect(container.querySelector('a[href="//evil.example/report.html"]')).toBeNull();
|
||||
expect(container.querySelector('a[href="https://evil.example/report.html"]')).toBeNull();
|
||||
});
|
||||
|
||||
it("orders execution workspace plugin tabs against built-in tabs by slot order", async () => {
|
||||
mockPluginSlotState.slots = [
|
||||
pluginSlot({ id: "default-tab", displayName: "Default" }),
|
||||
|
||||
@@ -315,7 +315,7 @@ function safeWorkProductHref(workProduct: IssueWorkProduct) {
|
||||
const metadataOpenPath = metadata && typeof metadata.openPath === "string" ? metadata.openPath : null;
|
||||
const candidate = workProduct.url ?? metadataOpenPath;
|
||||
if (!candidate) return null;
|
||||
if (candidate.startsWith("/")) return candidate;
|
||||
if (candidate.startsWith("/") && !candidate.startsWith("//")) return candidate;
|
||||
return isSafeExternalUrl(candidate) ? candidate : null;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user