comfyui-mcp
Version:
Local-first, agent-native control plane for ComfyUI — MCP server + autonomous sidebar agent that drives your live graph in natural language on ANY LLM: Claude/ChatGPT/Gemini on your subscription (no API key), free local models via Ollama (fully offline),
103 lines • 3.64 kB
JavaScript
import { ValidationError } from "../utils/errors.js";
const TOKEN_QUERY_RE = /token|key|secret|signature|auth|password|credential/i;
const REDACTED = "[REDACTED]";
const HEADER_NAME_RE = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
const ASCII_CONTROL_RE = /[\x00-\x1F\x7F]/;
const AZURE_BLOB_HOST_SUFFIX = ".blob.core.windows.net";
const AWS_PRESIGNED_QUERY_RE = /^x-amz-/i;
function rejectControlChars(label, value) {
if (ASCII_CONTROL_RE.test(value)) {
throw new ValidationError(`${label} cannot contain ASCII control characters.`);
}
}
function validateDownloadAuth(auth) {
if (auth.type === "bearer") {
rejectControlChars("Bearer token", auth.token);
return;
}
if (auth.type === "basic") {
rejectControlChars("Basic auth username", auth.username);
rejectControlChars("Basic auth password", auth.password);
return;
}
if (auth.type === "header") {
if (!HEADER_NAME_RE.test(auth.header_name)) {
throw new ValidationError("Header auth header_name must be a valid HTTP header token.");
}
rejectControlChars("Header auth header_value", auth.header_value);
return;
}
if (auth.type === "s3") {
rejectControlChars("S3 access_key_id", auth.access_key_id);
rejectControlChars("S3 secret_access_key", auth.secret_access_key);
if (auth.session_token)
rejectControlChars("S3 session_token", auth.session_token);
if (auth.region)
rejectControlChars("S3 region", auth.region);
if (auth.endpoint)
rejectControlChars("S3 endpoint", auth.endpoint);
return;
}
if (auth.query_param.length === 0) {
throw new ValidationError("Query auth query_param must be a non-empty string.");
}
rejectControlChars("Query auth query_param", auth.query_param);
}
function shouldRedactAllQueryValues(parsed) {
if (parsed.hostname.endsWith(AZURE_BLOB_HOST_SUFFIX))
return true;
return [...parsed.searchParams.keys()].some((key) => AWS_PRESIGNED_QUERY_RE.test(key));
}
export function redactUrlForLogs(url, extraSensitiveParams = []) {
try {
const parsed = new URL(url);
const redactAll = shouldRedactAllQueryValues(parsed);
const sensitive = new Set(extraSensitiveParams.map((p) => p.toLowerCase()));
for (const key of [...parsed.searchParams.keys()]) {
if (redactAll || sensitive.has(key.toLowerCase()) || TOKEN_QUERY_RE.test(key)) {
parsed.searchParams.set(key, REDACTED);
}
}
return parsed.toString();
}
catch {
return url;
}
}
export function applyDownloadAuth(url, auth) {
if (!auth)
return { url, headers: {} };
validateDownloadAuth(auth);
if (auth.type === "bearer") {
return {
url,
headers: { Authorization: `Bearer ${auth.token}` },
};
}
if (auth.type === "basic") {
const encoded = Buffer.from(`${auth.username}:${auth.password}`).toString("base64");
return {
url,
headers: { Authorization: `Basic ${encoded}` },
};
}
if (auth.type === "header") {
return {
url,
headers: { [auth.header_name]: auth.header_value },
};
}
if (auth.type === "s3") {
return {
url,
headers: {},
};
}
const parsed = new URL(url);
parsed.searchParams.set(auth.query_param, auth.query_value);
return {
url: parsed.toString(),
headers: {},
};
}
//# sourceMappingURL=download-auth.js.map