本章总览
entrypoints/sandboxTypes.ts 定义 Claude Code Agent SDK 的 沙箱配置 Zod schema,被 settings 校验、SDK coreTypes re-export、运行时 sandbox 服务共同引用。文件头声明 "single source of truth"。本章讲解 network/filesystem schema 字段、lazySchema 用法、与 coreSchemas 的汇入关系。
学完本章你应该能
- 说明 SandboxSettingsSchema 顶层字段语义
- 解释 allowManagedDomainsOnly / allowManagedReadPathsOnly 企业策略位
- 理解 lazySchema 延迟构建 Zod 的原因
- 描述 enabledPlatforms passthrough 与 NVIDIA rollout 注释
- 追踪类型从 sandboxTypes → coreTypes → settings 校验链
核心概念(先读懂这些)
sandbox 类型不属于 screens/components
沙箱类型放在 entrypoints/ 因为它们是 SDK 与 CLI 共享的契约,而非 UI concern。Doctor 屏通过 SandboxDoctorSection 展示运行时状态,但 schema 定义留在 sandboxTypes.ts。
lazySchema 避免循环与冷启动成本
SandboxNetworkConfigSchema、SandboxFilesystemConfigSchema、SandboxSettingsSchema 均用 lazySchema(() => z.object(...)),与 utils/lazySchema.js 配合,在首次 validate 时才 materialize Zod object,减少 module eval 时 Zod graph 构建开销。SDK coreSchemas 嵌入同一 lazy 引用,保证 CLI settings 与 npm SDK 包 validate 行为 bit-identical。
建议学习步骤
- 阅读文件头与 network schema(源码块 A)
- 阅读 filesystem allow/deny 字段(源码块 B)
- 阅读 SandboxSettingsSchema 顶层(源码块 C)
- 对照 coreTypes re-export(源码块 D)
- 查阅 coreSchemas 中 sandbox 嵌入点(源码块 E)
- 阅读 autoAllowBashIfSandboxed 企业注释(源码块 F)
常见误区
注意
enabledPlatforms 为 undocumented passthrough,仅 managed settings 读取
注意
failIfUnavailable 默认 false——sandbox 启但不可用时不 hard exit
注意
allowUnsandboxedCommands 默认 true,false 时忽略 dangerouslyDisableSandbox
单一真相源设计
sandboxTypes.ts 头注释:
> This file is the single source of truth for sandbox configuration types.
> Both the SDK and the settings validation import from here.
数据流:
sandboxTypes.ts (Zod schemas)
├─ utils/settings/* validation
├─ sdk/coreTypes.ts (type re-export)
├─ sdk/coreSchemas.ts (embed in larger schema)
└─ services/sandbox/* runtime 读取解析后的 settings
Doctor 屏 SandboxDoctorSection 展示 运行时 状态(是否 active、违规列表),不重复定义 schema。
源码引用: src/entrypoints/sandboxTypes.ts · 第 1–10 行(共 157 行)
1| /**
2| * Sandbox types for the Claude Code Agent SDK
3| *
4| * This file is the single source of truth for sandbox configuration types.
5| * Both the SDK and the settings validation import from here.
6| */
7|
8| import { z } from 'zod/v4'
9| import { lazySchema } from '../utils/lazySchema.js'
10|
源码引用: src/entrypoints/sdk/coreTypes.ts · 第 11–17 行(共 63 行)
11| // Re-export sandbox types for SDK consumers
12| export type {
13| SandboxFilesystemConfig,
14| SandboxIgnoreViolations,
15| SandboxNetworkConfig,
16| SandboxSettings,
17| } from '../sandboxTypes.js'
SandboxNetworkConfigSchema
网络沙箱字段:
| 字段 | 含义 |
|---|---|
allowedDomains | 允许访问的域名列表 |
allowManagedDomainsOnly | true 时仅 respect managed settings 的 domain allow + WebFetch allow |
allowUnixSockets | macOS:允许 unix socket 路径 |
allowAllUnixSockets | 允许所有 unix socket |
allowLocalBinding | 是否允许 bind 本地端口 |
httpProxyPort / socksProxyPort | 沙箱内代理端口 |
.describe() 字符串直接进入 JSON schema documentation,供 SDK 代码生成与 docs 站引用。
Linux seccomp 无法按 path 过滤 unix socket,故 allowUnixSockets macOS only 注释。
源码引用: src/entrypoints/sandboxTypes.ts · 第 14–42 行(共 157 行)
14| export const SandboxNetworkConfigSchema = lazySchema(() =>
15| z
16| .object({
17| allowedDomains: z.array(z.string()).optional(),
18| allowManagedDomainsOnly: z
19| .boolean()
20| .optional()
21| .describe(
22| 'When true (and set in managed settings), only allowedDomains and WebFetch(domain:...) allow rules from managed settings are respected. ' +
23| 'User, project, local, and flag settings domains are ignored. Denied domains are still respected from all sources.',
24| ),
25| allowUnixSockets: z
26| .array(z.string())
27| .optional()
28| .describe(
29| 'macOS only: Unix socket paths to allow. Ignored on Linux (seccomp cannot filter by path).',
30| ),
31| allowAllUnixSockets: z
32| .boolean()
33| .optional()
34| .describe(
35| 'If true, allow all Unix sockets (disables blocking on both platforms).',
36| ),
37| allowLocalBinding: z.boolean().optional(),
38| httpProxyPort: z.number().optional(),
39| socksProxyPort: z.number().optional(),
40| })
41| .optional(),
42| )
SandboxFilesystemConfigSchema
文件系统沙箱字段:
allowWrite/denyWrite— 额外读写路径,与 Edit(...) permission rules 合并denyRead/allowRead— deny 区域内 re-allow 读路径allowManagedReadPathsOnly— 企业策略:仅 managed policy 的 allowRead
设计原则:settings sandbox 路径与 permissions rules 合并,避免两套独立 ACL 打架。
运行时 sandbox 服务解析合并结果后下发 seccomp / Landlock / seatbelt(平台相关)。
源码引用: src/entrypoints/sandboxTypes.ts · 第 47–86 行(共 157 行)
47| export const SandboxFilesystemConfigSchema = lazySchema(() =>
48| z
49| .object({
50| allowWrite: z
51| .array(z.string())
52| .optional()
53| .describe(
54| 'Additional paths to allow writing within the sandbox. ' +
55| 'Merged with paths from Edit(...) allow permission rules.',
56| ),
57| denyWrite: z
58| .array(z.string())
59| .optional()
60| .describe(
61| 'Additional paths to deny writing within the sandbox. ' +
62| 'Merged with paths from Edit(...) deny permission rules.',
63| ),
64| denyRead: z
65| .array(z.string())
66| .optional()
67| .describe(
68| 'Additional paths to deny reading within the sandbox. ' +
69| 'Merged with paths from Read(...) deny permission rules.',
70| ),
71| allowRead: z
72| .array(z.string())
73| .optional()
74| .describe(
75| 'Paths to re-allow reading within denyRead regions. ' +
76| 'Takes precedence over denyRead for matching paths.',
77| ),
78| allowManagedReadPathsOnly: z
79| .boolean()
80| .optional()
81| .describe(
82| 'When true (set in managed settings), only allowRead paths from policySettings are used.',
83| ),
84| })
85| .optional(),
86| )
SandboxSettingsSchema 顶层
顶层 SandboxSettingsSchema 字段:
| 字段 | 说明 |
|---|---|
enabled | 是否启用沙箱 |
failIfUnavailable | enabled 但沙箱无法启动时是否 hard exit |
autoAllowBashIfSandboxed | 沙箱内 bash 是否自动 allow |
allowUnsandboxedCommands | 是否 honor dangerouslyDisableSandbox |
network | 嵌套 SandboxNetworkConfigSchema |
filesystem | 嵌套 SandboxFilesystemConfigSchema |
ignoreViolations | 按类别忽略违规 |
enableWeakerNestedSandbox | 嵌套 sandbox 降级 |
enableWeakerNetworkIsolation | macOS trustd.agent 等弱隔离 |
enabledPlatforms 注释:undocumented passthrough,NVIDIA 企业 rollout 仅 macOS 启用 sandbox 时使用 ["macos"]。
源码引用: src/entrypoints/sandboxTypes.ts · 第 91–130 行(共 157 行)
91| export const SandboxSettingsSchema = lazySchema(() =>
92| z
93| .object({
94| enabled: z.boolean().optional(),
95| failIfUnavailable: z
96| .boolean()
97| .optional()
98| .describe(
99| 'Exit with an error at startup if sandbox.enabled is true but the sandbox cannot start ' +
100| '(missing dependencies, unsupported platform, or platform not in enabledPlatforms). ' +
101| 'When false (default), a warning is shown and commands run unsandboxed. ' +
102| 'Intended for managed-settings deployments that require sandboxing as a hard gate.',
103| ),
104| // Note: enabledPlatforms is an undocumented setting read via .passthrough()
105| // It restricts sandboxing to specific platforms (e.g., ["macos"]).
106| //
107| // Added to unblock NVIDIA enterprise rollout: they want to enable
108| // autoAllowBashIfSandboxed but only on macOS initially, since Linux/WSL
109| // sandbox support is newer and less battle-tested. This allows them to
110| // set enabledPlatforms: ["macos"] to disable sandbox (and auto-allow)
111| // on other platforms until they're ready to expand.
112| autoAllowBashIfSandboxed: z.boolean().optional(),
113| allowUnsandboxedCommands: z
114| .boolean()
115| .optional()
116| .describe(
117| 'Allow commands to run outside the sandbox via the dangerouslyDisableSandbox parameter. ' +
118| 'When false, the dangerouslyDisableSandbox parameter is completely ignored and all commands must run sandboxed. ' +
119| 'Default: true.',
120| ),
121| network: SandboxNetworkConfigSchema(),
122| filesystem: SandboxFilesystemConfigSchema(),
123| ignoreViolations: z.record(z.string(), z.array(z.string())).optional(),
124| enableWeakerNestedSandbox: z.boolean().optional(),
125| enableWeakerNetworkIsolation: z
126| .boolean()
127| .optional()
128| .describe(
129| 'macOS only: Allow access to com.apple.trustd.agent in the sandbox. ' +
130| 'Needed for Go-based CLI tools (gh, gcloud, terraform, etc.) to verify TLS certificates ' +
源码引用: src/entrypoints/sandboxTypes.ts · 第 104–112 行(共 157 行)
104| // Note: enabledPlatforms is an undocumented setting read via .passthrough()
105| // It restricts sandboxing to specific platforms (e.g., ["macos"]).
106| //
107| // Added to unblock NVIDIA enterprise rollout: they want to enable
108| // autoAllowBashIfSandboxed but only on macOS initially, since Linux/WSL
109| // sandbox support is newer and less battle-tested. This allows them to
110| // set enabledPlatforms: ["macos"] to disable sandbox (and auto-allow)
111| // on other platforms until they're ready to expand.
112| autoAllowBashIfSandboxed: z.boolean().optional(),
lazySchema 模式
export const SandboxNetworkConfigSchema = lazySchema(() =>
z.object({ ... }).optional(),
)
lazySchema(utils/lazySchema.js)返回 getter,首次 .parse / .safeParse 时构建 Zod schema。
动机:
- 减少 CLI 冷启动时 Zod graph 节点分配
- 打破 settings ↔ sandbox ↔ permissions 潜在 circular import
SDK coreSchemas.ts 嵌入 sandbox schema 时使用相同 lazy 引用,保证 validate 行为一致。
源码引用: src/entrypoints/sandboxTypes.ts · 第 8–9 行(共 157 行)
8| import { z } from 'zod/v4'
9| import { lazySchema } from '../utils/lazySchema.js'
源码引用: src/utils/lazySchema.ts · 第 1–9 行(共 9 行)
1| /**
2| * Returns a memoized factory function that constructs the value on first call.
3| * Used to defer Zod schema construction from module init time to first access.
4| */
5| export function lazySchema<T>(factory: () => T): () => T {
6| let cached: T | undefined
7| return () => (cached ??= factory())
8| }
9|
coreSchemas 汇入与类型导出
coreTypes.ts 仅 re-export TypeScript 类型(infer from schema elsewhere):
export type {
SandboxFilesystemConfig,
SandboxIgnoreViolations,
SandboxNetworkConfig,
SandboxSettings,
} from '../sandboxTypes.js'
coreSchemas.ts 在更大 settings/SDK message schema 中 SandboxSettingsSchema() 引用(lazy invoke)。
Agent SDK 用户写 TypeScript 时 import SandboxSettings 类型;CLI settings.json 校验用同一 Zod 源,避免类型与校验 drift。
修改 sandbox 字段 checklist:
- 改 sandboxTypes.ts Zod + describe 文本
- 跑 generate-sdk-types(若影响 core message)
- 更新 sandbox 服务实现
- 更新 Doctor SandboxDoctorSection(若展示新字段)
源码引用: src/entrypoints/sdk/coreSchemas.ts · 第 1–30 行(共 1890 行)
1| /**
2| * SDK Core Schemas - Zod schemas for serializable SDK data types.
3| *
4| * These schemas are the single source of truth for SDK data types.
5| * TypeScript types are generated from these schemas and committed for IDE support.
6| *
7| * @see scripts/generate-sdk-types.ts for type generation
8| */
9|
10| import { z } from 'zod/v4'
11| import { lazySchema } from '../../utils/lazySchema.js'
12|
13| // ============================================================================
14| // Usage & Model Types
15| // ============================================================================
16|
17| export const ModelUsageSchema = lazySchema(() =>
18| z.object({
19| inputTokens: z.number(),
20| outputTokens: z.number(),
21| cacheReadInputTokens: z.number(),
22| cacheCreationInputTokens: z.number(),
23| webSearchRequests: z.number(),
24| costUSD: z.number(),
25| contextWindow: z.number(),
26| maxOutputTokens: z.number(),
27| }),
28| )
29|
30| // ============================================================================
源码引用: src/entrypoints/sandboxTypes.ts · 第 130–157 行(共 157 行)
130| 'Needed for Go-based CLI tools (gh, gcloud, terraform, etc.) to verify TLS certificates ' +
131| 'when using httpProxyPort with a MITM proxy and custom CA. ' +
132| '**Reduces security** — opens a potential data exfiltration vector through the trustd service. Default: false',
133| ),
134| excludedCommands: z.array(z.string()).optional(),
135| ripgrep: z
136| .object({
137| command: z.string(),
138| args: z.array(z.string()).optional(),
139| })
140| .optional()
141| .describe('Custom ripgrep configuration for bundled ripgrep support'),
142| })
143| .passthrough(),
144| )
145|
146| // Inferred types from schemas
147| export type SandboxSettings = z.infer<ReturnType<typeof SandboxSettingsSchema>>
148| export type SandboxNetworkConfig = NonNullable<
149| z.infer<ReturnType<typeof SandboxNetworkConfigSchema>>
150| >
151| export type SandboxFilesystemConfig = NonNullable<
152| z.infer<ReturnType<typeof SandboxFilesystemConfigSchema>>
153| >
154| export type SandboxIgnoreViolations = NonNullable<
155| SandboxSettings['ignoreViolations']
156| >
157|
autoAllowBashIfSandboxed 与 nested sandbox
autoAllowBashIfSandboxed — 沙箱内 bash 是否自动 permission allow,减少交互摩擦。
enableWeakerNestedSandbox / enableWeakerNetworkIsolation — 嵌套沙箱或 macOS trustd 弱隔离,enterprise 渐进 rollout 用。
enableWeakerNetworkIsolation 注释:macOS only,允许 com.apple.trustd.agent。
运行时 sandbox 服务读取合并后的 network+filesystem 规则,见 services/sandbox(非 entrypoints 层)。
源码引用: src/entrypoints/sandboxTypes.ts · 第 112–130 行(共 157 行)
112| autoAllowBashIfSandboxed: z.boolean().optional(),
113| allowUnsandboxedCommands: z
114| .boolean()
115| .optional()
116| .describe(
117| 'Allow commands to run outside the sandbox via the dangerouslyDisableSandbox parameter. ' +
118| 'When false, the dangerouslyDisableSandbox parameter is completely ignored and all commands must run sandboxed. ' +
119| 'Default: true.',
120| ),
121| network: SandboxNetworkConfigSchema(),
122| filesystem: SandboxFilesystemConfigSchema(),
123| ignoreViolations: z.record(z.string(), z.array(z.string())).optional(),
124| enableWeakerNestedSandbox: z.boolean().optional(),
125| enableWeakerNetworkIsolation: z
126| .boolean()
127| .optional()
128| .describe(
129| 'macOS only: Allow access to com.apple.trustd.agent in the sandbox. ' +
130| 'Needed for Go-based CLI tools (gh, gcloud, terraform, etc.) to verify TLS certificates ' +
ignoreViolations 与企业部署
ignoreViolations 允许按违规类别忽略 sandbox 告警。与 failIfUnavailable、allowManagedDomainsOnly 组合构成 enterprise 部署矩阵:必须沙箱、仅公司域名、禁止 dangerouslyDisableSandbox、macOS 先行 rollout 等。
Doctor SandboxDoctorSection 展示运行时违规;sandboxTypes 定义静态策略 shape。
与 REPL pendingSandboxRequest 的衔接
REPL 订阅 pendingSandboxRequest AppState(screens/REPL.tsx useAppState),在 tool 需要 sandbox 权限时展示 UI。
schema 层(sandboxTypes)定义静态配置;运行时层(services/sandbox)根据配置启动 sandbox;UI 层(REPL + permissions)处理动态 sandbox 权限请求。
allowUnsandboxedCommands: false 时用户无法在 Permission UI 选择「非沙箱运行」——settings 硬 gate。
failIfUnavailable: true 适合 managed-settings 部署:sandbox 必须可用否则拒绝启动 CLI。
源码引用: src/screens/REPL.tsx · 第 632–633 行(共 7050 行)
632| /** Transient status (v-for-editor progress). Notifications render inside
633| * PromptInput which isn't mounted in transcript — addNotification queues
源码引用: src/entrypoints/sandboxTypes.ts · 第 95–103 行(共 157 行)
95| failIfUnavailable: z
96| .boolean()
97| .optional()
98| .describe(
99| 'Exit with an error at startup if sandbox.enabled is true but the sandbox cannot start ' +
100| '(missing dependencies, unsupported platform, or platform not in enabledPlatforms). ' +
101| 'When false (default), a warning is shown and commands run unsandboxed. ' +
102| 'Intended for managed-settings deployments that require sandboxing as a hard gate.',
103| ),
本章小结与延伸
sandboxTypes = SDK/CLI 共享 Zod schema。改字段需同步 settings 文档与 sandbox 服务实现。ignoreViolations 与 failIfUnavailable 服务 enterprise 硬 gate 部署。 继续学习: