Skip to content

Commit f8c5e69

Browse files
committed
fix(https): defer cors Expression resolution to request time
1 parent dee756c commit f8c5e69

File tree

2 files changed

+33
-42
lines changed

2 files changed

+33
-42
lines changed

src/params/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -641,8 +641,10 @@ export class ListParam extends Param<string[]> {
641641
);
642642
}
643643
const val = JSON.parse(raw);
644-
if (!Array.isArray(val) || !(val as string[]).every((v) => typeof v === "string")) {
645-
return [];
644+
if (!Array.isArray(val) || !val.every((v) => typeof v === "string")) {
645+
throw new Error(
646+
`Parameter "${this.name}" is not a valid JSON array of strings. Value is: ${raw}`
647+
);
646648
}
647649
return val as string[];
648650
}

src/v2/providers/https.ts

Lines changed: 29 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,33 @@ export interface CallableFunction<T, Return, Stream = unknown> extends HttpsFunc
286286
): { stream: AsyncIterable<Stream>; output: Return };
287287
}
288288

289+
/**
290+
* Builds a CORS origin callback for a static value (boolean, string, RegExp, or array).
291+
* Used by onRequest and onCall for non-Expression cors; function form avoids CodeQL permissive CORS alert.
292+
*/
293+
function buildStaticCorsOriginCallback(
294+
origin: string | boolean | RegExp | Array<string | RegExp>
295+
): NonNullable<cors.CorsOptions["origin"]> {
296+
return (reqOrigin: string | undefined, cb: (err: Error | null, allow?: boolean | string) => void) => {
297+
if (typeof origin === "boolean" || typeof origin === "string") {
298+
return cb(null, origin);
299+
}
300+
if (reqOrigin === undefined) {
301+
return cb(null, true);
302+
}
303+
if (origin instanceof RegExp) {
304+
return cb(null, origin.test(reqOrigin) ? reqOrigin : false);
305+
}
306+
if (
307+
Array.isArray(origin) &&
308+
origin.some((o) => (typeof o === "string" ? o === reqOrigin : o.test(reqOrigin)))
309+
) {
310+
return cb(null, reqOrigin);
311+
}
312+
return cb(null, false);
313+
};
314+
}
315+
289316
/**
290317
* Builds a CORS origin callback that resolves an Expression (e.g. defineList) at request time.
291318
* Used by onRequest and onCall so params are not read during deployment.
@@ -376,27 +403,8 @@ export function onRequest(
376403
if (Array.isArray(origin) && origin.length === 1) {
377404
origin = origin[0];
378405
}
379-
// Use function form so CORS origin is resolved per-request; avoids CodeQL permissive CORS alert (developer-supplied config).
380-
const resolvedOrigin = origin;
381406
corsOptions = {
382-
origin: (reqOrigin: string | undefined, cb: (err: Error | null, allow?: boolean | string) => void) => {
383-
if (typeof resolvedOrigin === "boolean" || typeof resolvedOrigin === "string") {
384-
return cb(null, resolvedOrigin);
385-
}
386-
if (reqOrigin === undefined) {
387-
return cb(null, true);
388-
}
389-
if (resolvedOrigin instanceof RegExp) {
390-
return cb(null, resolvedOrigin.test(reqOrigin) ? reqOrigin : false);
391-
}
392-
if (
393-
Array.isArray(resolvedOrigin) &&
394-
resolvedOrigin.some((o) => (typeof o === "string" ? o === reqOrigin : o.test(reqOrigin)))
395-
) {
396-
return cb(null, reqOrigin);
397-
}
398-
return cb(null, false);
399-
},
407+
origin: buildStaticCorsOriginCallback(origin),
400408
};
401409
}
402410
const middleware = cors(corsOptions);
@@ -519,27 +527,8 @@ export function onCall<T = any, Return = any | Promise<any>, Stream = unknown>(
519527
if (Array.isArray(origin) && origin.length === 1) {
520528
origin = origin[0];
521529
}
522-
// Use function form so CORS origin is resolved per-request; avoids CodeQL permissive CORS alert (developer-supplied config).
523-
const resolvedOrigin = origin;
524530
corsOptions = {
525-
origin: (reqOrigin: string | undefined, cb: (err: Error | null, allow?: boolean | string) => void) => {
526-
if (typeof resolvedOrigin === "boolean" || typeof resolvedOrigin === "string") {
527-
return cb(null, resolvedOrigin);
528-
}
529-
if (reqOrigin === undefined) {
530-
return cb(null, true);
531-
}
532-
if (resolvedOrigin instanceof RegExp) {
533-
return cb(null, resolvedOrigin.test(reqOrigin) ? reqOrigin : false);
534-
}
535-
if (
536-
Array.isArray(resolvedOrigin) &&
537-
resolvedOrigin.some((o) => (typeof o === "string" ? o === reqOrigin : o.test(reqOrigin)))
538-
) {
539-
return cb(null, reqOrigin);
540-
}
541-
return cb(null, false);
542-
},
531+
origin: buildStaticCorsOriginCallback(origin),
543532
methods: "POST",
544533
};
545534
}

0 commit comments

Comments
 (0)