Security: trim audit policy import surfaces
This commit is contained in:
parent
ebfd32efc3
commit
4cb46f223c
@ -7,7 +7,6 @@ import { normalizeAgentId } from "../routing/session-key.js";
|
||||
import { resolveThreadParentSessionKey } from "../sessions/session-key-utils.js";
|
||||
import { normalizeMessageChannel } from "../utils/message-channel.js";
|
||||
import { resolveAgentConfig, resolveAgentIdFromSessionKey } from "./agent-scope.js";
|
||||
import { compileGlobPatterns, matchesAnyGlobPattern } from "./glob-pattern.js";
|
||||
import type { AnyAgentTool } from "./pi-tools.types.js";
|
||||
import { pickSandboxToolPolicy } from "./sandbox-tool-policy.js";
|
||||
import type { SandboxToolPolicy } from "./sandbox.js";
|
||||
@ -15,34 +14,8 @@ import {
|
||||
resolveStoredSubagentCapabilities,
|
||||
type SubagentSessionRole,
|
||||
} from "./subagent-capabilities.js";
|
||||
import { expandToolGroups, normalizeToolName } from "./tool-policy.js";
|
||||
|
||||
function makeToolPolicyMatcher(policy: SandboxToolPolicy) {
|
||||
const deny = compileGlobPatterns({
|
||||
raw: expandToolGroups(policy.deny ?? []),
|
||||
normalize: normalizeToolName,
|
||||
});
|
||||
const allow = compileGlobPatterns({
|
||||
raw: expandToolGroups(policy.allow ?? []),
|
||||
normalize: normalizeToolName,
|
||||
});
|
||||
return (name: string) => {
|
||||
const normalized = normalizeToolName(name);
|
||||
if (matchesAnyGlobPattern(normalized, deny)) {
|
||||
return false;
|
||||
}
|
||||
if (allow.length === 0) {
|
||||
return true;
|
||||
}
|
||||
if (matchesAnyGlobPattern(normalized, allow)) {
|
||||
return true;
|
||||
}
|
||||
if (normalized === "apply_patch" && matchesAnyGlobPattern("exec", allow)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
import { isToolAllowedByPolicies, isToolAllowedByPolicyName } from "./tool-policy-match.js";
|
||||
import { normalizeToolName } from "./tool-policy.js";
|
||||
|
||||
/**
|
||||
* Tools always denied for sub-agents regardless of depth.
|
||||
@ -140,19 +113,11 @@ export function resolveSubagentToolPolicyForSession(
|
||||
return { allow: mergedAllow, deny };
|
||||
}
|
||||
|
||||
export function isToolAllowedByPolicyName(name: string, policy?: SandboxToolPolicy): boolean {
|
||||
if (!policy) {
|
||||
return true;
|
||||
}
|
||||
return makeToolPolicyMatcher(policy)(name);
|
||||
}
|
||||
|
||||
export function filterToolsByPolicy(tools: AnyAgentTool[], policy?: SandboxToolPolicy) {
|
||||
if (!policy) {
|
||||
return tools;
|
||||
}
|
||||
const matcher = makeToolPolicyMatcher(policy);
|
||||
return tools.filter((tool) => matcher(tool.name));
|
||||
return tools.filter((tool) => isToolAllowedByPolicyName(tool.name, policy));
|
||||
}
|
||||
|
||||
type ToolPolicyConfig = {
|
||||
@ -381,9 +346,4 @@ export function resolveGroupToolPolicy(params: {
|
||||
return pickSandboxToolPolicy(toolsConfig);
|
||||
}
|
||||
|
||||
export function isToolAllowedByPolicies(
|
||||
name: string,
|
||||
policies: Array<SandboxToolPolicy | undefined>,
|
||||
) {
|
||||
return policies.every((policy) => isToolAllowedByPolicyName(name, policy));
|
||||
}
|
||||
export { isToolAllowedByPolicies, isToolAllowedByPolicyName } from "./tool-policy-match.js";
|
||||
|
||||
44
src/agents/tool-policy-match.ts
Normal file
44
src/agents/tool-policy-match.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { compileGlobPatterns, matchesAnyGlobPattern } from "./glob-pattern.js";
|
||||
import type { SandboxToolPolicy } from "./sandbox/types.js";
|
||||
import { expandToolGroups, normalizeToolName } from "./tool-policy.js";
|
||||
|
||||
function makeToolPolicyMatcher(policy: SandboxToolPolicy) {
|
||||
const deny = compileGlobPatterns({
|
||||
raw: expandToolGroups(policy.deny ?? []),
|
||||
normalize: normalizeToolName,
|
||||
});
|
||||
const allow = compileGlobPatterns({
|
||||
raw: expandToolGroups(policy.allow ?? []),
|
||||
normalize: normalizeToolName,
|
||||
});
|
||||
return (name: string) => {
|
||||
const normalized = normalizeToolName(name);
|
||||
if (matchesAnyGlobPattern(normalized, deny)) {
|
||||
return false;
|
||||
}
|
||||
if (allow.length === 0) {
|
||||
return true;
|
||||
}
|
||||
if (matchesAnyGlobPattern(normalized, allow)) {
|
||||
return true;
|
||||
}
|
||||
if (normalized === "apply_patch" && matchesAnyGlobPattern("exec", allow)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
export function isToolAllowedByPolicyName(name: string, policy?: SandboxToolPolicy): boolean {
|
||||
if (!policy) {
|
||||
return true;
|
||||
}
|
||||
return makeToolPolicyMatcher(policy)(name);
|
||||
}
|
||||
|
||||
export function isToolAllowedByPolicies(
|
||||
name: string,
|
||||
policies: Array<SandboxToolPolicy | undefined>,
|
||||
) {
|
||||
return policies.every((policy) => isToolAllowedByPolicyName(name, policy));
|
||||
}
|
||||
24
src/gateway/hooks-policy.ts
Normal file
24
src/gateway/hooks-policy.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { normalizeAgentId } from "../routing/session-key.js";
|
||||
|
||||
export function resolveAllowedAgentIds(raw: string[] | undefined): Set<string> | undefined {
|
||||
if (!Array.isArray(raw)) {
|
||||
return undefined;
|
||||
}
|
||||
const allowed = new Set<string>();
|
||||
let hasWildcard = false;
|
||||
for (const entry of raw) {
|
||||
const trimmed = entry.trim();
|
||||
if (!trimmed) {
|
||||
continue;
|
||||
}
|
||||
if (trimmed === "*") {
|
||||
hasWildcard = true;
|
||||
break;
|
||||
}
|
||||
allowed.add(normalizeAgentId(trimmed));
|
||||
}
|
||||
if (hasWildcard) {
|
||||
return undefined;
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
@ -5,9 +5,10 @@ import { listChannelPlugins } from "../channels/plugins/index.js";
|
||||
import type { ChannelId } from "../channels/plugins/types.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { readJsonBodyWithLimit, requestBodyErrorToText } from "../infra/http-body.js";
|
||||
import { normalizeAgentId, parseAgentSessionKey } from "../routing/session-key.js";
|
||||
import { parseAgentSessionKey } from "../routing/session-key.js";
|
||||
import { normalizeMessageChannel } from "../utils/message-channel.js";
|
||||
import { type HookMappingResolved, resolveHookMappings } from "./hooks-mapping.js";
|
||||
import { resolveAllowedAgentIds } from "./hooks-policy.js";
|
||||
|
||||
const DEFAULT_HOOKS_PATH = "/hooks";
|
||||
const DEFAULT_HOOKS_MAX_BODY_BYTES = 256 * 1024;
|
||||
@ -100,29 +101,6 @@ function resolveKnownAgentIds(cfg: OpenClawConfig, defaultAgentId: string): Set<
|
||||
return known;
|
||||
}
|
||||
|
||||
export function resolveAllowedAgentIds(raw: string[] | undefined): Set<string> | undefined {
|
||||
if (!Array.isArray(raw)) {
|
||||
return undefined;
|
||||
}
|
||||
const allowed = new Set<string>();
|
||||
let hasWildcard = false;
|
||||
for (const entry of raw) {
|
||||
const trimmed = entry.trim();
|
||||
if (!trimmed) {
|
||||
continue;
|
||||
}
|
||||
if (trimmed === "*") {
|
||||
hasWildcard = true;
|
||||
break;
|
||||
}
|
||||
allowed.add(normalizeAgentId(trimmed));
|
||||
}
|
||||
if (hasWildcard) {
|
||||
return undefined;
|
||||
}
|
||||
return allowed;
|
||||
}
|
||||
|
||||
function resolveSessionKey(raw: string | undefined): string | undefined {
|
||||
const value = raw?.trim();
|
||||
return value ? value : undefined;
|
||||
|
||||
@ -6,15 +6,13 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import { resolveDefaultAgentId } from "../agents/agent-scope.js";
|
||||
import { isToolAllowedByPolicies } from "../agents/pi-tools.policy.js";
|
||||
import {
|
||||
resolveSandboxConfigForAgent,
|
||||
resolveSandboxToolPolicyForAgent,
|
||||
} from "../agents/sandbox.js";
|
||||
import { resolveSandboxConfigForAgent } from "../agents/sandbox/config.js";
|
||||
import { SANDBOX_BROWSER_SECURITY_HASH_EPOCH } from "../agents/sandbox/constants.js";
|
||||
import { execDockerRaw, type ExecDockerRawResult } from "../agents/sandbox/docker.js";
|
||||
import { resolveSandboxToolPolicyForAgent } from "../agents/sandbox/tool-policy.js";
|
||||
import type { SandboxToolPolicy } from "../agents/sandbox/types.js";
|
||||
import { loadWorkspaceSkillEntries } from "../agents/skills.js";
|
||||
import { isToolAllowedByPolicies } from "../agents/tool-policy-match.js";
|
||||
import { resolveToolProfilePolicy } from "../agents/tool-policy.js";
|
||||
import { listAgentWorkspaceDirs } from "../agents/workspace-dirs.js";
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
import { isToolAllowedByPolicies } from "../agents/pi-tools.policy.js";
|
||||
import {
|
||||
resolveSandboxConfigForAgent,
|
||||
resolveSandboxToolPolicyForAgent,
|
||||
} from "../agents/sandbox.js";
|
||||
import { resolveSandboxConfigForAgent } from "../agents/sandbox/config.js";
|
||||
import { isDangerousNetworkMode, normalizeNetworkMode } from "../agents/sandbox/network-mode.js";
|
||||
/**
|
||||
* Synchronous security audit collector functions.
|
||||
*
|
||||
* These functions analyze config-based security properties without I/O.
|
||||
*/
|
||||
import { resolveSandboxToolPolicyForAgent } from "../agents/sandbox/tool-policy.js";
|
||||
import type { SandboxToolPolicy } from "../agents/sandbox/types.js";
|
||||
import { getBlockedBindReason } from "../agents/sandbox/validate-sandbox-security.js";
|
||||
import { isToolAllowedByPolicies } from "../agents/tool-policy-match.js";
|
||||
import { resolveToolProfilePolicy } from "../agents/tool-policy.js";
|
||||
import { resolveBrowserConfig } from "../browser/config.js";
|
||||
import { formatCliCommand } from "../cli/command-format.js";
|
||||
@ -21,7 +19,7 @@ import {
|
||||
} from "../config/model-input.js";
|
||||
import type { AgentToolsConfig } from "../config/types.tools.js";
|
||||
import { resolveGatewayAuth } from "../gateway/auth.js";
|
||||
import { resolveAllowedAgentIds } from "../gateway/hooks.js";
|
||||
import { resolveAllowedAgentIds } from "../gateway/hooks-policy.js";
|
||||
import {
|
||||
DEFAULT_DANGEROUS_NODE_COMMANDS,
|
||||
resolveNodeCommandAllowlist,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user