Sanitize target model header while preserving Unicode body

This commit is contained in:
musistudio
2026-08-15 23:16:15 +08:00
parent bb1db63c49
commit 83e01c3077
2 changed files with 37 additions and 1 deletions
+2 -1
View File
@@ -8,6 +8,7 @@ import { setTimeout as delay } from "node:timers/promises";
import type { GatewayMediaProtocol } from "@ccr/core/contracts/app";
import type { ImageEditRequest, ImageGenerateRequest, MediaExecutionContext, MediaExecutionResult, VideoGenerateRequest } from "@ccr/core/media/contracts";
import { detectMediaType } from "@ccr/core/media/storage";
import { sanitizeHeaderValue } from "@ccr/core/providers/runtime-topology";
import { fetchWithSystemProxy } from "@ccr/core/proxy/system-proxy-fetch";
const maxApiArtifactBytes = 250 * 1024 * 1024;
@@ -185,7 +186,7 @@ export class GatewayMediaExecutor {
: {}),
...(jsonBody ? { "content-type": "application/json" } : {}),
...(idempotencyKey ? { "idempotency-key": idempotencyKey } : {}),
"x-target-model": this.target.model,
"x-target-model": sanitizeHeaderValue(this.target.model),
"x-target-provider": this.target.providerSelector
};
}
@@ -118,6 +118,41 @@ test("media gateway errors expose the concrete failed provider attempt", async (
);
});
test("media gateway sanitizes target model header while preserving unicode body model", async (t) => {
const rawModel = "「中文模型」image-model";
let requestBody;
let targetModelHeader;
const server = createServer(async (request, response) => {
if (request.method === "POST" && request.url === "/v1/images/generations") {
targetModelHeader = request.headers["x-target-model"];
requestBody = JSON.parse((await consume(request)).toString("utf8"));
json(response, { data: [{ url: "https://media.example/artifact.png" }] });
return;
}
response.writeHead(404).end();
});
if (!await listenOrSkip(t, server)) return;
await waitForTcpListener(server);
t.after(() => server.close());
const executor = new GatewayMediaExecutor({
model: rawModel,
protocol: "openai_image_generations",
providerBaseUrl: "https://media.example/v1",
providerName: "Unicode Media Provider",
providerSelector: "unicode-media::openai_image_generations"
}, { baseUrl: baseUrl(server) });
await executor.imageGenerate({ prompt: "A blue cup" }, {
job: { id: "unicode-model-header-test" },
onRemoteRequestId() {},
signal: new AbortController().signal
});
assert.equal(targetModelHeader, "image-model");
assert.equal(requestBody.model, rawModel);
});
test("implicit media input roots reject the filesystem root and home directory", () => {
const home = path.resolve(os.homedir());
assert.equal(mediaServiceForTest.isSafeImplicitWorkingDirectory(path.parse(home).root, home), false);