mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
fix(media): case-sensitive Content-Type checks bypass header extension and image-header safety rules (#111184)
* fix(media): normalize Content-Type casing in header extension and image-header checks * test(media): consolidate MIME case coverage Co-authored-by: 潘晓波0668000512 <pan.xiaobo@xydigit.com> --------- Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
co-authored by
Peter Steinberger
parent
ce9e393196
commit
1508a58674
@@ -458,12 +458,12 @@ describe("media store", () => {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "prefers detected stream mime over generic zip header extension",
|
||||
name: "prefers detected stream mime over mixed-case generic zip header extension",
|
||||
run: async () => {
|
||||
await withTempStore(async (storeLocal10) => {
|
||||
const saved = await storeLocal10.saveMediaStream(
|
||||
Readable.from([Buffer.from("docx")]),
|
||||
"application/zip",
|
||||
"Application/Zip",
|
||||
"stream-inbound",
|
||||
1024,
|
||||
undefined,
|
||||
@@ -687,13 +687,13 @@ describe("media store", () => {
|
||||
expectedExtension: ".custom",
|
||||
},
|
||||
{
|
||||
name: "does not preserve image header extensions for generic container buffers",
|
||||
name: "does not preserve mixed-case image header extensions for generic container buffers",
|
||||
bufferFactory: async () => {
|
||||
const zip = new JSZip();
|
||||
zip.file("hello.txt", "hi");
|
||||
return await zip.generateAsync({ type: "nodebuffer" });
|
||||
},
|
||||
contentType: "image/png",
|
||||
contentType: "IMAGE/PNG",
|
||||
originalFilename: "fake.png",
|
||||
expectedContentType: "application/zip",
|
||||
expectedExtension: ".zip",
|
||||
|
||||
+3
-4
@@ -9,9 +9,8 @@ import {
|
||||
extnameFromAnyPath,
|
||||
nameFromAnyPath,
|
||||
} from "@openclaw/media-core/file-name";
|
||||
import { detectMime, extensionForMime } from "@openclaw/media-core/mime";
|
||||
import { detectMime, extensionForMime, normalizeMimeType } from "@openclaw/media-core/mime";
|
||||
import { hasHttpUrlPrefix } from "@openclaw/net-policy/url-protocol";
|
||||
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
|
||||
import { truncateUtf16Safe } from "@openclaw/normalization-core/utf16-slice";
|
||||
import { fileStore } from "../infra/file-store.js";
|
||||
import { sanitizeUntrustedFileName } from "../infra/fs-safe-advanced.js";
|
||||
@@ -246,7 +245,7 @@ function safeOriginalFilenameExtension(originalFilename?: string): string | unde
|
||||
}
|
||||
|
||||
function extensionForAuthoritativeHeaderMime(contentType?: string): string | undefined {
|
||||
const mime = normalizeOptionalString(contentType?.split(";")[0]);
|
||||
const mime = normalizeMimeType(contentType);
|
||||
if (!mime || mime === "application/octet-stream" || mime === "binary/octet-stream") {
|
||||
return undefined;
|
||||
}
|
||||
@@ -261,7 +260,7 @@ function isGenericContainerMime(mime?: string): boolean {
|
||||
}
|
||||
|
||||
function isImageHeaderMime(contentType?: string): boolean {
|
||||
return normalizeOptionalString(contentType?.split(";")[0])?.startsWith("image/") === true;
|
||||
return normalizeMimeType(contentType)?.startsWith("image/") === true;
|
||||
}
|
||||
|
||||
function resolveSavedMediaExtension(params: {
|
||||
|
||||
Reference in New Issue
Block a user