Files
openclaw-zero-token/gateway/origin-check.ts
sjhu 571e14a236 feat: upgrade to upstream v2026.3.28
Major upgrade from e26988a38 to upstream v2026.3.28 (f9b107928).
Key changes:
- Upstream src/, ui/, extensions/ (89 bundled extensions)
- Zero-token web providers preserved in src/zero-token/
- AskOnce plugin restored and registered as CLI command
- Added missing packages: @anthropic-ai/vertex-sdk, @modelcontextprotocol/sdk
- Fixed tsconfig rootDir, skipLibCheck for plugin-sdk DTS build
- Added askonce to bundled plugin metadata and package.json exports
- Fixed AskOnce CLI command registration (missing commands metadata)
- Restored AskOnce adapter imports (correct 5-level relative paths)
- Removed stale migration artifacts from root directory
2026-03-30 17:58:12 +08:00

64 lines
1.7 KiB
TypeScript

import { isLoopbackHost, normalizeHostHeader } from "./net.js";
type OriginCheckResult =
| {
ok: true;
matchedBy: "allowlist" | "host-header-fallback" | "local-loopback";
}
| { ok: false; reason: string };
function parseOrigin(
originRaw?: string,
): { origin: string; host: string; hostname: string } | null {
const trimmed = (originRaw ?? "").trim();
if (!trimmed || trimmed === "null") {
return null;
}
try {
const url = new URL(trimmed);
return {
origin: url.origin.toLowerCase(),
host: url.host.toLowerCase(),
hostname: url.hostname.toLowerCase(),
};
} catch {
return null;
}
}
export function checkBrowserOrigin(params: {
requestHost?: string;
origin?: string;
allowedOrigins?: string[];
allowHostHeaderOriginFallback?: boolean;
isLocalClient?: boolean;
}): OriginCheckResult {
const parsedOrigin = parseOrigin(params.origin);
if (!parsedOrigin) {
return { ok: false, reason: "origin missing or invalid" };
}
const allowlist = new Set(
(params.allowedOrigins ?? []).map((value) => value.trim().toLowerCase()).filter(Boolean),
);
if (allowlist.has("*") || allowlist.has(parsedOrigin.origin)) {
return { ok: true, matchedBy: "allowlist" };
}
const requestHost = normalizeHostHeader(params.requestHost);
if (
params.allowHostHeaderOriginFallback === true &&
requestHost &&
parsedOrigin.host === requestHost
) {
return { ok: true, matchedBy: "host-header-fallback" };
}
// Dev fallback only for genuinely local socket clients, not Host-header claims.
if (params.isLocalClient && isLoopbackHost(parsedOrigin.hostname)) {
return { ok: true, matchedBy: "local-loopback" };
}
return { ok: false, reason: "origin not allowed" };
}