UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

216 lines (215 loc) 8.21 kB
import { c as normalizeOptionalLowercaseString } from "./string-coerce-CIXf7egm.js"; //#region src/infra/exec-approvals-core.ts const EXEC_TARGET_VALUES = [ "auto", "sandbox", "gateway", "node" ]; function normalizeExecHost(value) { const normalized = normalizeOptionalLowercaseString(value); if (normalized === "sandbox" || normalized === "gateway" || normalized === "node") return normalized; return null; } function normalizeExecTarget(value) { const normalized = normalizeOptionalLowercaseString(value); if (normalized === "auto") return normalized; return normalizeExecHost(normalized); } function requireValidExecTarget(value) { if (value == null) return null; if (typeof value !== "string") throw new Error(`Invalid exec host value type ${typeof value}. Allowed values: ${EXEC_TARGET_VALUES.join(", ")}.`); const normalized = normalizeOptionalLowercaseString(value); if (!normalized) return null; const target = normalizeExecTarget(normalized); if (target) return target; throw new Error(`Invalid exec host "${value}". Allowed values: ${EXEC_TARGET_VALUES.join(", ")}.`); } function normalizeExecSecurity(value) { const normalized = normalizeOptionalLowercaseString(value); if (normalized === "deny" || normalized === "allowlist" || normalized === "full") return normalized; return null; } function normalizeExecAsk(value) { const normalized = normalizeOptionalLowercaseString(value); if (normalized === "off" || normalized === "on-miss" || normalized === "always") return normalized; return null; } function normalizeExecMode(value) { const normalized = normalizeOptionalLowercaseString(value); if (normalized === "deny" || normalized === "allowlist" || normalized === "ask" || normalized === "auto" || normalized === "full") return normalized; return null; } function resolveExecModeFromPolicy(params) { if (params.security === "deny") return "deny"; if (params.security === "allowlist" && params.ask === "off") return "allowlist"; if (params.security === "full" && params.ask !== "always") return "full"; return "ask"; } function resolveExecPolicyForMode(mode) { switch (mode) { case "deny": return { security: "deny", ask: "off", autoReview: false }; case "allowlist": return { security: "allowlist", ask: "off", autoReview: false }; case "ask": return { security: "allowlist", ask: "on-miss", autoReview: false }; case "auto": return { security: "allowlist", ask: "on-miss", autoReview: true }; case "full": return { security: "full", ask: "off", autoReview: false }; } throw new Error(`Unsupported exec mode: ${String(mode)}`); } function resolveExecModePolicy(params) { if (!params.mode) return { mode: resolveExecModeFromPolicy({ security: params.security, ask: params.ask }), security: params.security, ask: params.ask, autoReview: false }; return { mode: params.mode, ...resolveExecPolicyForMode(params.mode) }; } const DEFAULT_EXEC_APPROVAL_TIMEOUT_MS = 18e5; //#endregion //#region src/infra/exec-approvals-policy.ts function requiresExecApproval(params) { if (params.ask === "always") return true; if (params.durableApprovalSatisfied === true) return false; return params.ask === "on-miss" && params.security === "allowlist" && (!params.analysisOk || !params.allowlistSatisfied); } function normalizeCommandName(value) { return (value ?? "").split(/[\\/]/).pop()?.toLowerCase() ?? ""; } function textMentionsSecurityAuditSuppressions(value) { const normalized = value.toLowerCase(); return normalized.includes("security.audit.suppressions") || /["']?security["']?[\s\S]{0,200}["']?audit["']?[\s\S]{0,200}["']?suppressions["']?/.test(normalized); } function isReadOnlySecurityAuditSuppressionInspection(argv) { let offset = normalizeCommandName(argv[0]) === "pnpm" && argv[1] === "openclaw" ? 1 : 0; if (normalizeCommandName(argv[offset]) !== "openclaw") return false; offset += 1; while (offset < argv.length) { const arg = argv[offset]; if (["--dev", "--no-color"].includes(arg ?? "")) { offset += 1; continue; } if ([ "--profile", "--container", "--log-level" ].includes(arg ?? "")) { offset += 2; continue; } if (arg?.startsWith("--profile=") || arg?.startsWith("--container=") || arg?.startsWith("--log-level=")) { offset += 1; continue; } break; } return argv[offset] === "config" && [ "get", "schema", "validate" ].includes(argv[offset + 1] ?? ""); } function removeParsedSegmentText(command, segments) { let remaining = command; for (const segment of segments) { const raw = (segment.raw ?? segment.argv?.join(" "))?.trim(); if (!raw) continue; remaining = remaining.replace(raw, " "); } return remaining; } function commandRequiresSecurityAuditSuppressionApproval(params) { let sawSegmentMention = false; for (const segment of params.segments) { if (!textMentionsSecurityAuditSuppressions(`${segment.raw ?? ""} ${segment.argv.join(" ")}`)) continue; sawSegmentMention = true; if (!isReadOnlySecurityAuditSuppressionInspection(segment.argv)) return true; } if (sawSegmentMention) { if (textMentionsSecurityAuditSuppressions(removeParsedSegmentText(params.command, params.segments))) return true; return false; } return textMentionsSecurityAuditSuppressions(params.command); } function minSecurity(a, b) { const order = { deny: 0, allowlist: 1, full: 2 }; return order[a] <= order[b] ? a : b; } function maxAsk(a, b) { const order = { off: 0, "on-miss": 1, always: 2 }; return order[a] >= order[b] ? a : b; } const DEFAULT_EXEC_APPROVAL_DECISIONS = [ "allow-once", "allow-always", "deny" ]; const OPTIONAL_EXEC_APPROVAL_DECISIONS = ["allow-always"]; const OPTIONAL_EXEC_APPROVAL_DECISION_SET = new Set(OPTIONAL_EXEC_APPROVAL_DECISIONS); function isOptionalExecApprovalDecision(decision) { return OPTIONAL_EXEC_APPROVAL_DECISION_SET.has(decision); } function collectExecApprovalUnavailableDecisionSet(decisions) { const unavailable = /* @__PURE__ */ new Set(); if (!Array.isArray(decisions)) return unavailable; for (const decision of decisions) if (isOptionalExecApprovalDecision(decision)) unavailable.add(decision); return unavailable; } function normalizeExecApprovalUnavailableDecisions(decisions) { const unavailable = collectExecApprovalUnavailableDecisionSet(decisions); return OPTIONAL_EXEC_APPROVAL_DECISIONS.filter((decision) => unavailable.has(decision)); } function resolveExecApprovalAllowedDecisions(params) { if (normalizeExecAsk(params?.ask) === "always" || params?.allowAlwaysPersistence?.kind === "one-shot") return ["allow-once", "deny"]; return DEFAULT_EXEC_APPROVAL_DECISIONS; } function resolveExecApprovalUnavailableDecisions(params) { const allowed = new Set(resolveExecApprovalAllowedDecisions(params)); return OPTIONAL_EXEC_APPROVAL_DECISIONS.filter((decision) => !allowed.has(decision)); } function resolveExecApprovalRequestAllowedDecisions(params) { const policyDecisions = resolveExecApprovalAllowedDecisions({ ask: params?.ask }); const unavailableDecisions = collectExecApprovalUnavailableDecisionSet(params?.unavailableDecisions); if (unavailableDecisions.size === 0) return policyDecisions; return policyDecisions.filter((decision) => !isOptionalExecApprovalDecision(decision) || !unavailableDecisions.has(decision)); } function isExecApprovalDecisionAllowed(params) { return resolveExecApprovalAllowedDecisions({ ask: params.ask }).includes(params.decision); } //#endregion export { resolveExecPolicyForMode as S, normalizeExecSecurity as _, maxAsk as a, resolveExecModeFromPolicy as b, requiresExecApproval as c, resolveExecApprovalUnavailableDecisions as d, DEFAULT_EXEC_APPROVAL_TIMEOUT_MS as f, normalizeExecMode as g, normalizeExecHost as h, isExecApprovalDecisionAllowed as i, resolveExecApprovalAllowedDecisions as l, normalizeExecAsk as m, OPTIONAL_EXEC_APPROVAL_DECISIONS as n, minSecurity as o, EXEC_TARGET_VALUES as p, commandRequiresSecurityAuditSuppressionApproval as r, normalizeExecApprovalUnavailableDecisions as s, DEFAULT_EXEC_APPROVAL_DECISIONS as t, resolveExecApprovalRequestAllowedDecisions as u, normalizeExecTarget as v, resolveExecModePolicy as x, requireValidExecTarget as y };