aboutsummaryrefslogtreecommitdiffstats
path: root/packages/api/utils
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--packages/api/utils/assets.ts1
-rw-r--r--packages/api/utils/types.ts3
-rw-r--r--packages/api/utils/upload.ts12
3 files changed, 13 insertions, 3 deletions
diff --git a/packages/api/utils/assets.ts b/packages/api/utils/assets.ts
index 3da32ff2..7936f4ba 100644
--- a/packages/api/utils/assets.ts
+++ b/packages/api/utils/assets.ts
@@ -25,6 +25,7 @@ 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("Cache-Control", "private, max-age=31536000, immutable");
c.header(
"Content-Security-Policy",
[
diff --git a/packages/api/utils/types.ts b/packages/api/utils/types.ts
index bdaf815f..c1f342db 100644
--- a/packages/api/utils/types.ts
+++ b/packages/api/utils/types.ts
@@ -8,8 +8,7 @@ export const zStringBool = z
.transform((val) => val === "true");
export const zIncludeContentSearchParamsSchema = z.object({
- // TODO: Change the default to false in a couple of releases.
- includeContent: zStringBool.optional().default("true"),
+ includeContent: zStringBool.optional().default("false"),
});
export const zGetBookmarkQueryParamsSchema = z
diff --git a/packages/api/utils/upload.ts b/packages/api/utils/upload.ts
index a843e29c..b82bc855 100644
--- a/packages/api/utils/upload.ts
+++ b/packages/api/utils/upload.ts
@@ -3,6 +3,7 @@ import * as os from "os";
import * as path from "path";
import { Readable } from "stream";
import { pipeline } from "stream/promises";
+import { fileTypeFromBlob, supportedMimeTypes } from "file-type";
import { assets, AssetTypes } from "@karakeep/db/schema";
import { QuotaService, StorageQuotaError } from "@karakeep/shared-server";
@@ -58,7 +59,16 @@ export async function uploadAsset(
data = formData.image;
}
- const contentType = data.type;
+ const detectedType = await fileTypeFromBlob(data);
+ const fallbackType =
+ data.type && data.type.trim().length > 0 ? data.type : null;
+ // Security: reject browser-provided MIME when we cannot sniff a valid type.
+ if (fallbackType && supportedMimeTypes.has(fallbackType) && !detectedType) {
+ return { error: "Unsupported asset type", status: 400 };
+ }
+ const contentType =
+ detectedType?.mime ?? fallbackType ?? "application/octet-stream";
+
// Replace all non-ascii characters with underscores
const fileName = data.name.replace(/[^\x20-\x7E]/g, "_");
if (!SUPPORTED_UPLOAD_ASSET_TYPES.has(contentType)) {