mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-06 23:55:12 +00:00
refactor: share ssrf policy merging
This commit is contained in:
@@ -14,6 +14,7 @@ import {
|
||||
buildHostnameAllowlistPolicyFromSuffixAllowlist,
|
||||
fetchWithSsrFGuard,
|
||||
isPrivateOrLoopbackHost,
|
||||
mergeSsrFPolicies,
|
||||
ssrfPolicyFromDangerouslyAllowPrivateNetwork,
|
||||
type SsrFPolicy,
|
||||
} from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
@@ -102,35 +103,6 @@ function readConfigInteger(config: ComfyProviderConfig, key: string): number | u
|
||||
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
|
||||
}
|
||||
|
||||
function mergeSsrFPolicies(...policies: Array<SsrFPolicy | undefined>): SsrFPolicy | undefined {
|
||||
const merged: SsrFPolicy = {};
|
||||
for (const policy of policies) {
|
||||
if (!policy) {
|
||||
continue;
|
||||
}
|
||||
if (policy.allowPrivateNetwork) {
|
||||
merged.allowPrivateNetwork = true;
|
||||
}
|
||||
if (policy.dangerouslyAllowPrivateNetwork) {
|
||||
merged.dangerouslyAllowPrivateNetwork = true;
|
||||
}
|
||||
if (policy.allowRfc2544BenchmarkRange) {
|
||||
merged.allowRfc2544BenchmarkRange = true;
|
||||
}
|
||||
if (policy.allowedHostnames?.length) {
|
||||
merged.allowedHostnames = Array.from(
|
||||
new Set([...(merged.allowedHostnames ?? []), ...policy.allowedHostnames]),
|
||||
);
|
||||
}
|
||||
if (policy.hostnameAllowlist?.length) {
|
||||
merged.hostnameAllowlist = Array.from(
|
||||
new Set([...(merged.hostnameAllowlist ?? []), ...policy.hostnameAllowlist]),
|
||||
);
|
||||
}
|
||||
}
|
||||
return Object.keys(merged).length > 0 ? merged : undefined;
|
||||
}
|
||||
|
||||
export function getComfyConfig(cfg?: OpenClawConfig): ComfyProviderConfig {
|
||||
const raw = cfg?.models?.providers?.comfy;
|
||||
return isRecord(raw) ? raw : {};
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import {
|
||||
buildHostnameAllowlistPolicyFromSuffixAllowlist,
|
||||
fetchWithSsrFGuard,
|
||||
mergeSsrFPolicies,
|
||||
type SsrFPolicy,
|
||||
ssrfPolicyFromDangerouslyAllowPrivateNetwork,
|
||||
} from "openclaw/plugin-sdk/ssrf-runtime";
|
||||
@@ -55,35 +56,6 @@ export function _setFalFetchGuardForTesting(impl: typeof fetchWithSsrFGuard | nu
|
||||
falFetchGuard = impl ?? fetchWithSsrFGuard;
|
||||
}
|
||||
|
||||
function mergeSsrFPolicies(...policies: Array<SsrFPolicy | undefined>): SsrFPolicy | undefined {
|
||||
const merged: SsrFPolicy = {};
|
||||
for (const policy of policies) {
|
||||
if (!policy) {
|
||||
continue;
|
||||
}
|
||||
if (policy.allowPrivateNetwork) {
|
||||
merged.allowPrivateNetwork = true;
|
||||
}
|
||||
if (policy.dangerouslyAllowPrivateNetwork) {
|
||||
merged.dangerouslyAllowPrivateNetwork = true;
|
||||
}
|
||||
if (policy.allowRfc2544BenchmarkRange) {
|
||||
merged.allowRfc2544BenchmarkRange = true;
|
||||
}
|
||||
if (policy.allowedHostnames?.length) {
|
||||
merged.allowedHostnames = Array.from(
|
||||
new Set([...(merged.allowedHostnames ?? []), ...policy.allowedHostnames]),
|
||||
);
|
||||
}
|
||||
if (policy.hostnameAllowlist?.length) {
|
||||
merged.hostnameAllowlist = Array.from(
|
||||
new Set([...(merged.hostnameAllowlist ?? []), ...policy.hostnameAllowlist]),
|
||||
);
|
||||
}
|
||||
}
|
||||
return Object.keys(merged).length > 0 ? merged : undefined;
|
||||
}
|
||||
|
||||
function matchesTrustedHostSuffix(hostname: string, trustedSuffix: string): boolean {
|
||||
const normalizedHost = normalizeLowercaseStringOrEmpty(hostname);
|
||||
const normalizedSuffix = normalizeLowercaseStringOrEmpty(trustedSuffix);
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
hasLegacyFlatAllowPrivateNetworkAlias,
|
||||
isPrivateNetworkOptInEnabled,
|
||||
isHttpsUrlAllowedByHostnameSuffixAllowlist,
|
||||
mergeSsrFPolicies,
|
||||
migrateLegacyFlatAllowPrivateNetworkAlias,
|
||||
normalizeHostnameSuffixAllowlist,
|
||||
ssrfPolicyFromDangerouslyAllowPrivateNetwork,
|
||||
@@ -130,6 +131,36 @@ describe("ssrfPolicyFromPrivateNetworkOptIn", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("mergeSsrFPolicies", () => {
|
||||
it("returns undefined when no policy contributes values", () => {
|
||||
expect(mergeSsrFPolicies(undefined, {})).toBeUndefined();
|
||||
});
|
||||
|
||||
it("merges boolean flags and dedupes host allowlists", () => {
|
||||
expect(
|
||||
mergeSsrFPolicies(
|
||||
{
|
||||
allowPrivateNetwork: true,
|
||||
allowedHostnames: ["api.example.com"],
|
||||
hostnameAllowlist: ["downloads.example.com"],
|
||||
},
|
||||
{
|
||||
dangerouslyAllowPrivateNetwork: true,
|
||||
allowRfc2544BenchmarkRange: true,
|
||||
allowedHostnames: ["api.example.com", "cdn.example.com"],
|
||||
hostnameAllowlist: ["downloads.example.com", "assets.example.com"],
|
||||
},
|
||||
),
|
||||
).toEqual({
|
||||
allowPrivateNetwork: true,
|
||||
dangerouslyAllowPrivateNetwork: true,
|
||||
allowRfc2544BenchmarkRange: true,
|
||||
allowedHostnames: ["api.example.com", "cdn.example.com"],
|
||||
hostnameAllowlist: ["downloads.example.com", "assets.example.com"],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("legacy private-network alias helpers", () => {
|
||||
it("detects the flat allowPrivateNetwork alias", () => {
|
||||
expect(hasLegacyFlatAllowPrivateNetworkAlias({ allowPrivateNetwork: true })).toBe(true);
|
||||
|
||||
@@ -60,6 +60,37 @@ export function ssrfPolicyFromDangerouslyAllowPrivateNetwork(
|
||||
return ssrfPolicyFromPrivateNetworkOptIn(dangerouslyAllowPrivateNetwork);
|
||||
}
|
||||
|
||||
export function mergeSsrFPolicies(
|
||||
...policies: Array<SsrFPolicy | undefined>
|
||||
): SsrFPolicy | undefined {
|
||||
const merged: SsrFPolicy = {};
|
||||
for (const policy of policies) {
|
||||
if (!policy) {
|
||||
continue;
|
||||
}
|
||||
if (policy.allowPrivateNetwork) {
|
||||
merged.allowPrivateNetwork = true;
|
||||
}
|
||||
if (policy.dangerouslyAllowPrivateNetwork) {
|
||||
merged.dangerouslyAllowPrivateNetwork = true;
|
||||
}
|
||||
if (policy.allowRfc2544BenchmarkRange) {
|
||||
merged.allowRfc2544BenchmarkRange = true;
|
||||
}
|
||||
if (policy.allowedHostnames?.length) {
|
||||
merged.allowedHostnames = Array.from(
|
||||
new Set([...(merged.allowedHostnames ?? []), ...policy.allowedHostnames]),
|
||||
);
|
||||
}
|
||||
if (policy.hostnameAllowlist?.length) {
|
||||
merged.hostnameAllowlist = Array.from(
|
||||
new Set([...(merged.hostnameAllowlist ?? []), ...policy.hostnameAllowlist]),
|
||||
);
|
||||
}
|
||||
}
|
||||
return Object.keys(merged).length > 0 ? merged : undefined;
|
||||
}
|
||||
|
||||
export function hasLegacyFlatAllowPrivateNetworkAlias(value: unknown): boolean {
|
||||
const entry = asNullableRecord(value);
|
||||
return Boolean(entry && Object.prototype.hasOwnProperty.call(entry, "allowPrivateNetwork"));
|
||||
|
||||
@@ -19,6 +19,7 @@ export {
|
||||
createLegacyPrivateNetworkDoctorContract,
|
||||
hasLegacyFlatAllowPrivateNetworkAlias,
|
||||
isPrivateNetworkOptInEnabled,
|
||||
mergeSsrFPolicies,
|
||||
migrateLegacyFlatAllowPrivateNetworkAlias,
|
||||
ssrfPolicyFromDangerouslyAllowPrivateNetwork,
|
||||
ssrfPolicyFromPrivateNetworkOptIn,
|
||||
|
||||
Reference in New Issue
Block a user