aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2025-08-23 16:03:06 +0300
committerMohamedBassem <me@mbassem.com>2025-08-23 16:03:06 +0300
commita4b2fc7ca89c7916a32a3e279ab3880ebaa7a734 (patch)
tree0697484b3881a9a43d72a9e38ba58c24b081bfea /packages
parent096af7efffe11be563844a361fafd6d158dd5c81 (diff)
downloadkarakeep-a4b2fc7ca89c7916a32a3e279ab3880ebaa7a734.tar.zst
fix(security): Add CSP policies on asset serving path
Diffstat (limited to 'packages')
-rw-r--r--packages/api/utils/assets.ts21
1 files changed, 19 insertions, 2 deletions
diff --git a/packages/api/utils/assets.ts b/packages/api/utils/assets.ts
index 205e1a76..3da32ff2 100644
--- a/packages/api/utils/assets.ts
+++ b/packages/api/utils/assets.ts
@@ -22,6 +22,25 @@ export async function serveAsset(c: Context, assetId: string, userId: string) {
}),
]);
+ // Default Headers
+ c.header("Content-type", metadata.contentType);
+ c.header("X-Content-Type-Options", "nosniff");
+ c.header(
+ "Content-Security-Policy",
+ [
+ "sandbox",
+ "default-src 'none'",
+ "base-uri 'none'",
+ "form-action 'none'",
+ "img-src https: data: blob:",
+ "style-src 'unsafe-inline' https:",
+ "connect-src 'none'",
+ "media-src https: data: blob:",
+ "object-src 'none'",
+ "frame-src 'none'",
+ ].join("; "),
+ );
+
const range = c.req.header("Range");
if (range) {
const parts = range.replace(/bytes=/, "").split("-");
@@ -38,7 +57,6 @@ export async function serveAsset(c: Context, assetId: string, userId: string) {
c.header("Content-Range", `bytes ${start}-${end}/${size}`);
c.header("Accept-Ranges", "bytes");
c.header("Content-Length", (end - start + 1).toString());
- c.header("Content-type", metadata.contentType);
return stream(c, async (stream) => {
await stream.pipe(toWebReadableStream(fStream));
});
@@ -49,7 +67,6 @@ export async function serveAsset(c: Context, assetId: string, userId: string) {
});
c.status(200);
c.header("Content-Length", size.toString());
- c.header("Content-type", metadata.contentType);
return stream(c, async (stream) => {
await stream.pipe(toWebReadableStream(fStream));
});