Initial commit
This commit is contained in:
55
mcp-server/utils/cmsTargetSafety.js
Normal file
55
mcp-server/utils/cmsTargetSafety.js
Normal file
@@ -0,0 +1,55 @@
|
||||
const SAFE_INTERNAL_HOSTS = new Set(["web", "acai-web", "localhost", "127.0.0.1"]);
|
||||
|
||||
function parseUrl(url, fieldName, context) {
|
||||
try {
|
||||
return new URL(url);
|
||||
} catch {
|
||||
throw new Error(`[${context}] Invalid ${fieldName}: ${url || "<empty>"}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function assertSafeCmsTarget(target, context = "cms") {
|
||||
const publicUrl = typeof target === "string" ? target : (target?.web_url || "");
|
||||
const apiUrl = typeof target === "string" ? target : (target?.api_web_url || "");
|
||||
|
||||
if (!apiUrl) {
|
||||
throw new Error(
|
||||
`[${context}] ACAI_API_WEB_URL is required. Refusing to use ACAI_WEB_URL directly for CMS requests.`
|
||||
);
|
||||
}
|
||||
|
||||
const parsedApiUrl = parseUrl(apiUrl, "ACAI_API_WEB_URL", context);
|
||||
if (!SAFE_INTERNAL_HOSTS.has(parsedApiUrl.hostname)) {
|
||||
throw new Error(
|
||||
`[${context}] Unsafe ACAI_API_WEB_URL host "${parsedApiUrl.hostname}". ` +
|
||||
`Only approved local hosts are allowed: ${Array.from(SAFE_INTERNAL_HOSTS).join(", ")}.`
|
||||
);
|
||||
}
|
||||
|
||||
if (!["http:", "https:"].includes(parsedApiUrl.protocol)) {
|
||||
throw new Error(
|
||||
`[${context}] Unsafe ACAI_API_WEB_URL protocol "${parsedApiUrl.protocol}".`
|
||||
);
|
||||
}
|
||||
|
||||
if (publicUrl) {
|
||||
const parsedPublicUrl = parseUrl(publicUrl, "ACAI_WEB_URL", context);
|
||||
const publicIsSafeInternal = SAFE_INTERNAL_HOSTS.has(parsedPublicUrl.hostname);
|
||||
if (!publicIsSafeInternal && parsedPublicUrl.host === parsedApiUrl.host) {
|
||||
throw new Error(
|
||||
`[${context}] ACAI_API_WEB_URL resolves to the same public host as ACAI_WEB_URL (${parsedApiUrl.host}).`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
publicUrl,
|
||||
apiUrl,
|
||||
forgeHost: typeof target === "string" ? null : (target?.forge_host || null),
|
||||
};
|
||||
}
|
||||
|
||||
export function isSafeInternalHost(hostname) {
|
||||
return SAFE_INTERNAL_HOSTS.has(hostname);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user