diff options
| author | tanaka takashi <isazaka@gmail.com> | 2026-08-12 05:44:54 +0900 |
|---|---|---|
| committer | tanaka takashi <isazaka@gmail.com> | 2026-08-12 05:44:54 +0900 |
| commit | b56614c814b904c224315a11f9686f0d47abd3d3 (patch) | |
| tree | e6ae4feb852ea4492bf947eabba1e11ab157686a /doc/Design.md | |
| parent | 98b6a2aeedd591058c1d81e401d24f3ded162926 (diff) | |
feat: revise sandbox usability around semantic policy and LPAC process trees
Rewrite the specification and design vocabulary around User Sandbox Configuration, Environment Resolution, Executable Approval, Effective Sandbox Policy, and Windows Enforcement. Move the Internal Tool catalog to the design without treating its count as a requirement, and update README, implementation planning, traceability, audit history, prompts, and the Python skill.
Introduce schema_version 1 profiles, workspaces, mounts, executable aliases, network modes, and resource presets. Add local override merging, resolution and approval stores with atomic user-only persistence, fail-closed fingerprints, localized diagnostics, and executable/sandbox management CLI commands.
Change Windows execution to LPAC entry approval with inherited descendant confinement. Separate read and execute ACLs, preserve protected OS DACLs, apply Job process/memory/timeout limits to the tree, enforce WFP network modes, prevent credential environment inheritance, disable out-of-tree MSBuild reuse, and harden transactional ACL/recovery cleanup.
Isolate planning prompts from execution instructions, reject split coding plans that cannot satisfy task-scoped evidence, preserve configured thinking, and prevent optional task_update failures from corrupting completion checks.
Add and update configuration, resolution, approval, LPAC, descendant, readonly/development, Registry/COM, WFP, recovery, .NET/Python/PowerShell process-tree, and Operational E2E coverage. Publish reproducible bundles while preserving deployment-local configuration, prompts, skills, logs, state, approvals, and resolutions.
Diffstat (limited to 'doc/Design.md')
| -rw-r--r-- | doc/Design.md | 249 |
1 files changed, 152 insertions, 97 deletions
diff --git a/doc/Design.md b/doc/Design.md index 9ad4ae3..8f76ca6 100644 --- a/doc/Design.md +++ b/doc/Design.md @@ -69,21 +69,35 @@ Agent Runtime ─── Session Store (memory) ├── Prompt Composer ── Skill Selector/Loader ├── Ollama Client ───── Ollama localhost ├── Token Planner ───── TaskGraph / PERT / CPM - └── Internal Tool Dispatcher - │ - ▼ - Policy Engine + └── Internal Tool Dispatcher + │ + ▼ + User Sandbox Configuration + │ + ▼ + Sandbox Environment Resolution + ├── Workspace / Mount / Reparse Resolution + ├── Executable Alias / Runtime Resolution + ├── Executable Approval Resolution + ├── Network Resolution + └── Resource Resolution + │ + ▼ + Effective Sandbox Policy + │ + ▼ + Policy Engine │ ▼ Sandbox Broker - ├── AppContainer + ├── Less Privileged AppContainer (LPAC) ├── NTFS ACL ├── Job Object ├── WFP └── Named Pipe │ ▼ - Sandboxed Process Tree + Sandbox Process Tree Audit Writer / Recovery Manager は各副作用境界を横断して記録・復旧する。 ``` ### 3.1 信頼境界 @@ -252,14 +266,14 @@ overrideはTask objectにcopyし、global configurationを変更しない。Sess - mime_type、Base64妥当性、設定上限size/countを事前検査する。 - 既定上限は4画像、1画像10 MiB、request合計20 MiBとする。 - model capability確認でVision非対応と判定した場合はOllama呼出し前にlocalized error。能力確認不能時は呼出しを行い、Ollama errorを正規化して返す。 -### 6.5 Tool calling -Ollamaに公開する現行Internal Tool catalogは次のとおりとする。個々のOS command (`grep.exe`等) をtoolとして増殖させない。catalogの構成は設計事項であり、仕様上の固定数として扱わない。 -| Tool | 責務 | 主なoperation | +### 6.5 Internal Tool calling +Ollamaに公開する現行Internal Tool catalogは次のとおりとする。個々のOS Executable (`grep.exe`等) をInternal Toolとして増殖させない。catalogの構成は設計事項であり、仕様上の固定数として扱わない。 +| Internal Tool | 責務 | 主なoperation | | --- | --- | --- | | file_search | 検索 | glob / name / text / regex / tail相当 | | file_read | 読取 | whole / range / metadata | | file_edit | 編集 | overwrite / patch / atomic_replace / delete | -| process_run | 承認済Process実行 | exe + args + cwd + timeout | +| process_run | Entry Process実行 | Executable + args + cwd + timeout | | task_update | TaskGraph更新 | add / dependency / estimate | | dir | ディレクトリ操作 | mkdir / rmdir / list | --- @@ -278,7 +292,7 @@ Ollamaに公開する現行Internal Tool catalogは次のとおりとする。å€ ``` - wholeはsize上限を超えた場合range利用を要求する。 - whole readの既定上限は1 MiBとする。 -- read前にcanonical pathとreparse pointを検査する。 +- read前にLogical Pathをreparse resolutionし、確認済みResolved PathとEffective Filesystem Policyを検査する。 ### 7.3 file_edit ```json { @@ -290,10 +304,10 @@ Ollamaに公開する現行Internal Tool catalogは次のとおりとする。å€ "new_path":"string|null" } ``` -- overwrite/patch/atomic_replaceはwrite permissionを要求する。 -- `patch` operationの`patch` fieldは、JSON文字列化した`{"old_text":"...","new_text":"..."}`を受け取る。unified diffは受け付けない。`old_text`は対象file内で正確に1回だけ一致しなければならない。不正形式または一致数不正は再試行可能なTool failureとする。 -- deleteはdelete permissionを要求する。 -- renameはsource/destination双方にwrite permissionを要求する。destinationが既に存在する場合は拒否する(overwrite不可)。cross-volume renameは不支持でTool failureとして返す。 +- overwrite/patch/atomic_replaceはwrite Filesystem Capabilityを要求する。 +- `patch` operationの`patch` fieldは、JSON文字列化した`{"old_text":"...","new_text":"..."}`を受け取る。unified diffは受け付けない。`old_text`は対象file内で正確に1回だけ一致しなければならない。不正形式または一致数不正は再試行可能なInternal Tool failureとする。 +- deleteはdelete Filesystem Capabilityを要求する。 +- renameはsource/destination双方にwrite Filesystem Capabilityを要求する。destinationが既に存在する場合は拒否する(overwrite不可)。cross-volume renameは不支持でInternal Tool failureとして返す。 - rename transaction: PREPARE(source/destination検査+journal) → APPLY(File.Move) → VERIFY(source不存在/destination存在/hash一致) → COMMIT。crash recoveryはdestination hashがjournal記録と一致する場合のみdestinationからsourceへ戻す。 - `expected_sha256` 指定時はoptimistic concurrency guardとして利用する。 ### 7.4 process_run @@ -306,10 +320,11 @@ Ollamaに公開する現行Internal Tool catalogは次のとおりとする。å€ "stdin":"string|null" } ``` -- shell command line 1本ではなくexeとargsを分離する。 -- executableはcanonical path + SHA-256 approval必須。 -- shell category disabled時はcmd/powershell/pwshを拒否する。 -- cwdはfilesystem policy内でなければならない。 +- Shell Command 1本ではなくExecutableとargsを分離する。 +- `executable`はApproved Entry Executable/ShellのAlias、Runtime ComponentのLogical/Resolved Path、またはdevelopment Workspace ArtifactのLogical/Resolved Pathとする。Alias以外のrelative Logical Pathは`cwd`を基準に解決する。Approved Entry ExecutableのResolved PathをAliasの代用として直接指定することはできない。 +- Approved Entry Executable/ShellはResolved Path + SHA-256のExecutable Approval必須。Runtime ComponentとWorkspace Artifactは分類rootによって判定する。 +- External Unknown ExecutableをEntry Processとして直接起動しない。Descendant Processは個別分類せずLPAC/ACL/WFP/Job confinementを継承する。 +- cwdはEffective Filesystem Policy内でなければならない。 ### 7.5 task_update ```json { @@ -334,13 +349,13 @@ PlannerがDAG、不変条件、completed immutable、max_tasksを再検査して - mkdir は Write capabilityを要求し、`Directory.CreateDirectory` で親ディレクトリも含めて作成する。 - rmdir は Delete capabilityを要求し、**空ディレクトリのみ**削除する。非空の場合は `ToolValidationException` で拒否する。内容復元の複雑さとMemoryBackupLimit超過リスクを排除するため、再帰削除は行わない。 - list は Read capabilityを要求し、直下のエントリ一覧を返す。外部効果ではない。 -- 既存の PathPolicy / CanonicalPath / TaskAclManager (root継承ACE) / TaskResourceJournal / RecoveryManager 枠組みを利用する。新規作成ディレクトリは親の継承ACEを自動取得するため追加ACL操作は不要。 +- 既存の `ResolvedPath` / `PathPolicy` / `TaskAclManager`(root継承ACE)/ `TaskResourceJournal` / `RecoveryManager` 枠組みを利用する。新規作成directoryは親の継承ACEを自動取得するため追加ACL操作は不要。 - mkdir後crash → ディレクトリ削除、rmdir後crash → 空ディレクトリ再作成、でRecoveryする。 -### 7.7 Tool error表現 -既存のTool resultへ、`error_code`、`error_category`、`target_path`、`required_permission`、`retry_allowed`、`resolution`をoptional fieldとして保持する。これは独立したerror体系ではなく、既存の`SandboxPolicyException`と`ToolExecutionResult`の分類情報を失わずRuntime、Audit、localized messageへ渡す表現である。内部messageと利用者向けlocalized messageは分離し、内部Tool名は利用者向け結果へ含めない。 +### 7.7 Internal Tool error表現 +既存のInternal Tool resultへ、`error_code`、`error_category`、`target_path`、`required_permission`、`retry_allowed`、`resolution`をoptional fieldとして保持する。これは独立したerror体系ではなく、既存の`SandboxPolicyException`と`ToolExecutionResult`の分類情報を失わずRuntime、Audit、localized messageへ渡す表現である。内部messageと利用者向けlocalized messageは分離し、Internal Tool名は利用者向け結果へ含めない。 ### 7.8 ToolUseGuard -Taskには `requires_external_effect` をPlanner内部属性として持たせる。**Planning フェーズで LLM structured output により Task ごとに判定・設定される**(keyword heuristic ではない)。trueのTaskで、当該iteration中のtool callが0かつ完了証拠がない場合、LLMへ「未実行」を示すsystem-generated observationを追加して再試行する。同一失敗fingerprintが5回に達したらTaskをfailedにする。ただし、Policy EngineのdenyおよびSandbox backendの`UnauthorizedAccessException`は`RetryAllowed=false`のterminal Tool resultへ変換する。Runtimeはobserverへ結果を1回記録した後、同一Tool呼出しへ再投入せず、§8.4の条件付きreplanへ遷移する。 +Taskには `requires_external_effect` をPlanner内部属性として持たせる。**Planning フェーズで LLM structured output により Task ごとに判定・設定される**(keyword heuristic ではない)。trueのTaskで、当該iteration中のInternal Tool Callが0かつ完了証拠がない場合、LLMへ「未実行」を示すsystem-generated observationを追加して再試行する。同一失敗fingerprintが5回に達したらTaskをfailedにする。ただし、Policy EngineのdenyおよびSandbox backendの`UnauthorizedAccessException`は`RetryAllowed=false`のterminal Internal Tool resultへ変換する。Runtimeはobserverへ結果を1回記録した後、同一Internal Tool Callへ再投入せず、§8.4の条件付きreplanへ遷移する。 --- ## 8. Token Planner設計 ### 8.1 Task model @@ -360,6 +375,8 @@ Task RequiredTools: set<Internal Tool name> ``` Taskは、完了に成功証跡が必要なTool名を`RequiredTools`として持つ。Planner structured outputの`required_tools`から構築し、Runtimeは集合内の全Toolが成功した場合だけTaskの操作を検証済みとする。read/search/list Taskは副作用不要でも対応Toolを持ち、純粋な説明Taskだけが空集合となる。`RequiresExternalEffect=true`では集合内の副作用Toolから外部効果も確認する。例えば`process_run`が必要なTask中の`file_edit`成功は完了根拠にしない。current Taskの集合に含まれない副作用ToolはBackendへdispatchせず、Task scope外のTool resultとしてLLMへ返してqueued Taskの先取りを決定的に防ぐ。scope外結果はAudit/LLM相関には残すが、次Taskのactive Execution Result contextへは引き継がない。 + +codingの編集・検証・失敗修正は同一Taskへまとめ、`file_edit`と`process_run`をRequiredToolsにする。両Toolを要求する検証Taskが、別の`file_edit` Taskへ直接または間接に依存するsplit planはこの規則に反するためPlanner validationで拒否し、具体的な理由を付けて1回だけ訂正させる。 ### 8.2 PERT計算 ```text ExpectedTokens = (O + 4*M + P) / 6.0 @@ -376,7 +393,7 @@ topological sort後にforward passで各Taskの累積expected token costを計ç® - 実績がPを超過しても即失敗にはせず、remaining Taskのestimate見直しをLLMへ要求できる。 - `max_tasks=32`超過提案は拒否し、既存Taskの統合をLLMへ求める。 - Budget Classは意味的Taskを分割する唯一の理由にしない。Taskが複数独立成果物を含む場合に分割する。 -- Policy denyは同一Tool呼出しへ再投入しない。許可済み能力だけで代替できる可能性がある場合、`running -> planning -> running` と遷移してreplanを最大3回まで試行できる。 +- Effective Sandbox Policy denyは同一Internal Tool Callへ再投入しない。許可済みcapabilityだけで代替できる可能性がある場合、`running -> planning -> running` と遷移してreplanを最大3回まで試行できる。 - completed TaskのID、状態、usageを保持する。failed Taskをdependency解決済みとして扱わない。 - 同一deny fingerprintの再発、計画未変更、実行可能Taskなし、structured replan失敗は即Failedとする。全Taskがcompletedの場合だけAgent Taskをcompletedにする。 - structured planが空または不正な場合は、設定された`think`を維持したまま訂正instruction付きで1回だけ再試行し、それでも失敗した場合はplanning failureとする。外部効果要否が不明なfallback graphは作成しない。 @@ -397,7 +414,7 @@ AgentSession CreatedAt / LastAccessAt ``` ### 9.2 Context assembly -順序を次に固定する。 +実行phaseの順序を次に固定する。 1. Fixed System Prompt 2. User System Prompt 3. locale instruction @@ -410,6 +427,8 @@ AgentSession 10. current Taskの`requires_external_effect`に基づく実行要件 11. recent Conversation +Planning/replanning phaseはread-onlyのTaskGraph生成契約を最初のSystem messageとして使用し、locale、Skill catalog、Sandbox capability summary、original MCP Task requestだけを組み立てる。file調査やInternal Tool実行を指示するFixed/User System PromptはPlanning契約と矛盾するため、このphaseへ混在させない。生成後のTask実行では上記1〜11の優先順位を適用する。 + 実行要件は、現在runningのTaskだけを実行してqueued Taskを先取りしないことをSystemおよび末尾のcurrent Task user messageで指示する。末尾messageにはoriginal MCP Task requestもexact値の参照元として併記する。外部効果が必要なTaskでは文章上の宣言、計画、JSON例を実行済みと扱わず、対応するInternal Toolを直ちに呼び出すよう指示する。成功済みのread結果はExecution Resultから再利用し、不要な再読込を避けてwrite/processへ進む。外部効果が不要なTaskにはToolを強制しない。未解決のTool失敗後にToolを呼ばない応答も同一失敗として数え、既定の同一失敗上限でfailedにする。 ### 9.3 Summary policy `num_ctx`に対する利用率が設定閾値を超えたとき、古いConversation/Execution Resultを要約する。利用率 = latest `prompt_eval_count` / `num_ctx`(累積 InputTokens ではない)。既定閾値は80%とする。次は削除・曖昧化してはならない。 @@ -422,7 +441,7 @@ AgentSession - 承認/Policyそのものではなく現在利用可能なcapability summary raw chain-of-thoughtは保存・要約対象としない。 --- -## 10. SandboxPolicy YAML設計 +## 10. User Sandbox Configuration・Resolution・Effective Policy設計 ### 10.1 schema概要 ```yaml schema_version: 1 @@ -453,21 +472,21 @@ ollama: planner: max_tasks: 32 sandbox: - filesystem: - read: [] - write: [] - execute: [] - delete: [] - process: - allow_shell: true - approvals: [] - max_processes: 16 + profile: development + workspaces: [] + mounts: [] + execution: + executables: [] + shells: [] network: - mode: deny - allow: [] + access: none + local_endpoints: [] + restricted_endpoints: [] resources: - memory_mb: 4096 - process_timeout_seconds: 1800 + profile: normal + memory_mb: + process_limit: + execution_timeout_seconds: file_edit: memory_backup_limit_mb: 16 limits: @@ -484,59 +503,90 @@ logging: directory: logs ``` base YAMLと同じdirectoryに`agent.local.yaml`が存在する場合、YAML nodeを読み取ってmapを再帰mergeし、scalarとsequenceはlocal nodeで置換してからtyped configurationへdeserializeする。unknown propertyを含むvalidationはmerge後に行い、全相対pathのbaseはbase YAMLのdirectoryとする。local file、そこから参照するUser System PromptおよびSkill directoryはRelease Bundleのpublish入力に含めない。 -### 10.2 Filesystem entry -各list itemはpath文字列とする。起動時に絶対canonical pathへ正規化して保持する。file/directoryは実在時に種別を記録し、未作成write targetは最も近い既存親directoryまで検査する。 -### 10.3 Process approval entry +### 10.2 Workspace・Mount・Profile +- `workspaces`はLogical Path文字列のsequenceとする。`readonly`はreadのみ、`development`はread/write/delete/Artifact executeへcompileする。 +- `mounts`は`path`と`access: read_only|read_write|read_write_delete`を持つ。readonly Profileではread_onlyだけを許可し、Mountにexecuteを付与しない。 +- relative Logical Pathはbase YAML directory基準。実在するlocal directoryだけを許可する。 +- 同一Resolved Rootはcapabilityを統合する。親の継承capabilityより狭いnested rootは拒否する。 +### 10.3 Executable Alias・Approval Store ```yaml -approvals: - - path: C:/Program Files/Git/cmd/git.exe - sha256: "<64 hex chars>" - - path: C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe - sha256: "<64 hex chars>" +execution: + executables: [python, git] + shells: [powershell] ``` -署名はaudit metadataとして取得可能だが、v1のallow判定はpath + SHA-256を必須条件とする。 +- AliasはApprovalではない。CLIが候補を提示し、人間が選択したResolved Executable PathとSHA-256をWindows user単位Storeへ固定する。 +- Store pathは`%LOCALAPPDATA%/AgentSandboxMcp/executable-approvals.json`。user-only DACL、WriteThrough、atomic replace、schema versionを持つ。 +- recordはAlias、Approved Entry Executable/Approved Shell Executable分類、Logical Path、Resolved Path、SHA-256、optional Runtime Root、承認日時を持つ。 +- Runtime RootはCLI提案後の明示確認対象とし、その配下のRuntime Componentは個別hashなしでEntry起動できる。 +- Aliasはcase-insensitiveに一意とし、Executable/Shell双方への重複指定を拒否する。ShellのResolved file nameは`cmd.exe|powershell.exe|pwsh.exe`だけを許可する。 ### 10.4 Network entry ```yaml network: - mode: allow - allow: + access: restricted + local_endpoints: [] + restricted_endpoints: - host: github.com ports: [443] - - host: api.github.com - ports: [443] ``` -`allow` modeでもlist外はdeny。`deny`ではlistを無視して全denyする。localhostも特別扱いしない。 +`none`は全deny、`local`は列挙portを`127.0.0.1`/`::1`へ展開、`restricted`はhostをTask開始時にIP snapshot化する。mode不一致または空endpointを拒否する。 +### 10.5 Resource Profile +`constrained=1024 MiB/4/300秒`、`normal=4096 MiB/16/1800秒`、`extended=8192 MiB/32/3600秒`とする。`memory_mb`、`process_limit`、`execution_timeout_seconds`の正数overrideはpreset値を置換する。 +### 10.6 Resolution Result +- Workspace/MountのLogical→Resolved mapping、config絶対path、semantic sandbox fingerprint、確認日時を`%LOCALAPPDATA%/AgentSandboxMcp/environment-resolutions/<config-path-hash>.json`へ保存する。 +- reparse chainを最終targetまで解決しcycle、missing target、非local filesystemを拒否する。確認後のfingerprintまたはResolved Path変化はserve/checkをfail-closedにする。 +- `sandbox resolve`はpreview、`sandbox confirm`だけがStoreを更新し、`sandbox show`はEffective Sandbox Policyをtext/JSON表示する。 + +### 10.7 Effective Sandbox Policy + +確認済みResolution Resultと現在のApproval Storeをcompileし、次を由来付きで保持する。 + +- Filesystem Root: `workspace`、`mount`、`approved_entry_executable`、`approved_shell_executable`、`runtime_root`、`os_runtime_root`の由来、Resolved Path、Filesystem Capability。 +- Entry Executable: Alias、分類、Resolved Path、SHA-256、optional Runtime Root。 +- Artifact RootとRuntime Root: Entry分類およびACL生成に使用するResolved Root。 +- Network: `none|local|restricted`とTask開始時にsnapshot化するendpoint。 +- Resource: Resource Profile名、override適用後のmemory/process/timeout。 +- baseline capability: 固定された`registryRead`と`lpacInstrumentation`。 + +同じResolved RootのFilesystem Capabilityは和集合にし、由来も併記する。親rootから継承するCapabilityより狭いnested rootは表現不能としてcompileを拒否する。`sandbox show`はこのcompile結果をtextまたはJSONで表示するが、Storeや設定を変更しない。 --- ## 11. Windows強制設計 -### 11.1 AppContainer +### 11.1 Less Privileged AppContainer - Application Profileを固定名で作成/取得する。 - 起動時にprofile SIDを解決する。 - Taskごとにprofileを作り直さない。 -- AppContainer外の通常user tokenに戻るbreakawayを許可しない。 +- standard `CreateProcess`の`PROC_THREAD_ATTRIBUTE_SECURITY_CAPABILITIES`に加え、`PROC_THREAD_ATTRIBUTE_ALL_APPLICATION_PACKAGES_POLICY=PROCESS_CREATION_ALL_APPLICATION_PACKAGES_OPT_OUT`を指定してLPAC tokenを生成する。 +- Experimental CreateProcessInSandbox、AppLocker、WDACへ依存しない。LPAC生成または互換性検査失敗時に通常AppContainerへfallbackしない。 +- baseline capabilityは`registryRead`と、PowerShell Runtimeが起動時のETW provider登録に必要とする`lpacInstrumentation`とする。Registry writeと`lpacCom`は付与しない。Network capabilityはEffective Network Policyが必要な場合だけ付与する。`lpacInstrumentation`追加後もRegistry writeとCOM activationの実拒否をWindows Security suiteで検証する。 +- AppContainer外の通常user tokenに戻るbreakawayを許可しない。DescendantはLPAC tokenを継承する。 +- `CreateProcess`へBrokerのenvironment blockをそのまま継承しない。Windows/runtime起動に必要なsystem/profile path、`ComSpec`、System32だけのPATH、Task `cwd`を指すTEMP/TMPと`DOTNET_CLI_HOME`、非対話かつnetwork非依存の.NET初回起動・telemetry・workload resolver値、Process Tree外の共有MSBuild server/node reuseを無効化する値から成る明示的なUnicode environment blockを渡し、任意のtoken、password、SSH/API credential環境変数を除外する。profile path自体はFilesystem Capabilityを付与しない。 ### 11.2 NTFS ACL -- Policy Engineが許可pathから必要ACEを導出する。 -- 許可pathがdirectoryの場合、そのrootへ`ContainerInherit | ObjectInherit`付きのApplication SID ACEを1件だけtransactionalに追加し、既存およびTask中に作成されたdescendantへ継承させる。descendantごとのDACL列挙・snapshot・明示ACE追加は行わない。 +- Effective Sandbox PolicyのFilesystem RootからApplication SID ACEを導出する。 +- read-only directoryはdirectory traverse/list/readとfile readを別ACEとして付与し、fileのExecuteFileを含めない。execute rootだけがfile read/execute ACEを取得する。 +- development Workspace/Artifact Rootはread/write/delete/execute、Runtime RootとResolved `%SystemRoot%/System32`はread/execute、Mountは指定accessのみを取得する。 +- 許可pathがdirectoryの場合、rootへのinheritance ACEで既存およびTask中に作成されたdescendantを覆い、descendantごとのDACL列挙は行わない。 - 許可pathがfileの場合は、そのfileだけへ継承なしACEを追加する。異なる権限を持つnested rootは別scopeとして逆順cleanupする。 - protected DACLを持つdescendantの継承保護は解除しない。そのpathはOS拒否のままとし、Sandbox権限を暗黙に拡張しない。 - rootの元security descriptorをRecovery Journalへ1件記録する。 - Task終了で追加分を除去し、元状態との整合を検査する。 ### 11.3 Job Object - TaskごとにJob Objectを1つ作成する。 -- root sandbox processをJobへ割り当てる。descendantを同一Jobへ継承させる。 +- Entry ProcessをJobへ割り当て、全Descendantを同一Job chainへ継承させる。 - breakawayを許可しない。 - process count / memory limitをJobへ設定する。 - `KILL_ON_JOB_CLOSE`相当を利用し、application終了時にprocess treeを残さない。 -### 11.4 Process approval -Sandbox Brokerは実行直前にcanonical pathを取得し、ファイルを開いた状態でSHA-256を計算し、approvalと一致確認してから起動する。TOCTOU低減のため、検証対象と実行対象のpath解決がずれないよう実装時にWin32のfile identity確認を追加する。具体API選択は実装時に確定する。 +### 11.4 Entry Process分類・Executable Approval +- AliasはApproval StoreのApproved Entry Executable/Shellへ解決し、起動直前とsuspended生成後・resume前にResolved PathとSHA-256を再検証する。 +- Runtime Componentは確認済みRuntime Root containment、Workspace Artifactはdevelopment Artifact Root containmentで分類する。MountおよびExternal Unknown Executableからの直接Entry起動は拒否する。 +- Descendant Processは個別分類・Approvalを行わず、LPAC/ACL/WFP/Job confinementをSecurity Boundaryとする。`PROCESS_CREATION_CHILD_PROCESS_RESTRICTED`は使用しない。 ### 11.5 WFP方針 WFP実装は複雑な汎用Firewallにしない。設計上の変換規則だけを固定する。 -1. `deny`ならApplication Profile/Task processに対するoutbound blockを作成する。 -2. `allow`ならdefault blockを置き、列挙hostをTask開始時にDNS解決する。 +1. `none`ならnetwork capabilityを付与せず、Application Profile/Sandbox Process Treeへoutbound blockを作成する。 +2. `local`は列挙portをIPv4/IPv6 Loopbackへ、`restricted`は列挙hostをTask開始時にIP解決する。 3. 解決したIP集合とportの組にだけallow filterを作成する。 4. Task実行中はそのIP snapshotを使用し、複雑な動的DNS追随は行わない。 5. DNS解決失敗はdeny。 6. Task終了でTask固有WFP filterを削除する。 -7. localhostはallow-listに明示されない限り許可しない。 +7. LoopbackもEffective Network Policyに明示されない限り許可しない。LANをlocalへ含めない。 具体的なWFP layer、sublayer、filter condition、transaction APIは実装時にCodexがWindows SDKを確認して決定し、Security Integration Testで仕様を検証する。 ### 11.6 Named Pipe Sandbox workerとのIPCが必要な場合はtask固有Named Pipeを使用し、DACLをApplication SIDとBrokerだけに限定する。TCP localhostを内部IPCに使わない。 @@ -546,7 +596,7 @@ Sandbox workerとのIPCが必要な場合はtask固有Named Pipeを使用し、D | 性質 | 本システムでの意味 | | --- | --- | | Atomicity | Task Resource適用が途中失敗した場合、適用済み変更をrollbackする。 | -| Consistency | SandboxPolicyとSecurity Invariantを満たす状態だけを実行可能状態とする。 | +| Consistency | Effective Sandbox PolicyとSecurity Invariantを満たす状態だけを実行可能状態とする。 | | Isolation | Task固有ResourceをTask IDで識別し、他Task cleanupで誤削除しない。 | | Durability | Task Resource自体の永続化ではなく、cleanupに必要なjournalをcrashに耐えて保持する。 | ### 12.2 状態機械 @@ -625,7 +675,7 @@ call ID、session ID、task ID、Planner Task ID、phase、iteration、replan番 ### 15.3 Audit JSONL Auditはappend-only JSONLを採用する。1 event = 1 line。 ```json -{"ts":"...","event":"process.start","session_id":"...","task_id":"...","exe":"...","sha256":"...","args":["..."],"decision":"allow"} +{"ts":"...","event":"process.start","session_id":"...","task_id":"...","exe":"...","sha256":"...","arguments":"redacted","argument_count":2,"decision":"allow"} {"ts":"...","event":"file.write","task_id":"...","path":"...","before_sha256":"...","after_sha256":"..."} {"ts":"...","event":"policy.deny","task_id":"...","kind":"network","target":"example.com:443","reason":"not_allowlisted"} ``` @@ -672,7 +722,7 @@ closed Sessionは再利用しない。プロセス再起動後に以前のSessio - locale baseline/placeholder - Ollama endpoint URI - Sandbox path canonicalization -- process approval path/hash format +- Executable Approval StoreのAlias/Logical Path/Resolved Path/hash format - network host/port syntax - resource limit range - Fixed/User prompt file state @@ -684,8 +734,8 @@ closed Sessionは再利用しない。プロセス再起動後に以前のSessio | TokenPERT | O<=M<=P<=budget、式のunit test | | TokenCPM | 既知DAGに対するcritical path unit test | | Filesystem | allow/deny/reparse point integration test | -| Process | hash mismatch、path mismatch、shell toggle | -| Network | deny loopback、allow-list host/port | +| Process | Alias不明、Approval不足、hash/Resolved Path変更、Entry分類拒否、LPAC不一致 | +| Network | noneのLoopback、local/restrictedのPolicy外address/port | | Recovery | 各transaction stateで強制crashして再起動cleanup | | MCP | stdio purity、Streamable HTTP loopback、GET 405 | | Localization | fallback、unknown key fatal、placeholder validation | @@ -693,26 +743,30 @@ closed Sessionは再利用しない。プロセス再起動後に以前のSessio ## 19. Security Test Matrix | ID | ケース | 期待 | | --- | --- | --- | -| ST-01 | read許可file | 成功 | -| ST-02 | read未許可file | ACCESS_DENIED | -| ST-03 | write許可file | 成功 | -| ST-04 | delete権限なしdelete | 拒否 | +| ST-01 | readonly Workspaceのread | 成功 | +| ST-02 | readonly Workspaceのwrite/delete/execute | すべて拒否 | +| ST-03 | development Workspaceのread/write/delete | 成功 | +| ST-04 | development Workspace ArtifactのEntry起動 | Approvalなしで成功 | | ST-05 | junctionで許可外へ脱出 | 拒否 | -| ST-06 | symlink chainで許可外へ脱出 | 拒否 | +| ST-06 | symlink chain/cycle | 許可外は拒否、cycleはfail-closed | | ST-07 | 承認exe/hash一致 | 成功 | | ST-08 | exe更新/hash不一致 | 拒否 | -| ST-09 | shell disabledでPowerShell | 拒否 | -| ST-10 | 子が未承認exe起動 | 拒否 | -| ST-11 | Job close | 全descendant終了 | -| ST-12 | network denyで127.0.0.1 | 拒否 | -| ST-13 | network allowで許可host:port | 成功 | -| ST-14 | network allowで未許可port | 拒否 | +| ST-09 | Approved Shell分類 | cmd.exe/powershell.exe/pwsh.exeだけ直接起動可 | +| ST-10 | Descendantが個別未承認Executableを起動 | 同じLPAC identity/Job内で成功 | +| ST-11 | Job close/breakaway/process/memory/timeout | breakaway不可、制限時は全Process Tree停止 | +| ST-12 | Network noneで127.0.0.1 | 拒否 | +| ST-13 | Network local/restrictedで許可address:port | 成功 | +| ST-14 | Network local/restrictedでPolicy外port | 拒否 | | ST-15 | MCPからpolicy変更試行 | schema/機能上不可能 | -| ST-16 | Ollama tool arg path脱出 | Policyで拒否 | +| ST-16 | Ollama Internal Tool CallのResolved Path脱出 | Policyで拒否 | | ST-17 | crash after ACL apply | 再起動cleanup | | ST-18 | crash after WFP apply | 再起動cleanup | -| ST-19 | malformed locale | 起動失敗 | -| ST-20 | non-loopback HTTP bind | 起動失敗 | +| ST-19 | LPAC baselineでRegistry read/writeとCOM | readのみ成功、write/COM拒否 | +| ST-20 | External Unknown/System32 Executableの直接Entry | Approvalなしでは拒否 | +| ST-21 | malformed locale | 起動失敗 | +| ST-22 | non-loopback HTTP bind | 起動失敗 | +| ST-23 | Approval/Resolution Store | user-only DACL、atomic replace、破損record拒否 | +| ST-24 | config fingerprint/Resolved Path/hash変更 | 再確認または再承認までfail-closed | --- ## 20. エラー分類 | Category | 例 | Task結果 | Retry | @@ -724,7 +778,7 @@ closed Sessionは再利用しない。プロセス再起動後に以前のSessio | tool_failure | process nonzero/patch mismatch | running→replan | 最大同一5 | | resource_limit | timeout/memory/process limit | failedまたはreplan | 原則No | | recovery_failure | ACL/WFP cleanup不能 | application fatal | No | -errorは内部codeとlocalized messageを分離し、ログ/auditにはcode、MCPにはlocalized textを返す。 +errorは内部codeとlocalized messageを分離し、ログ/auditにはcode、MCPにはlocalized textを返す。Sandbox Configuration/Resolution/Approvalの失敗は少なくとも`configuration.invalid`、`sandbox.resolution_unconfirmed`、`sandbox.resolution_changed`、`executable.approval_missing`、`executable.resolution_changed`、`executable.hash_changed`、`executable.shell_unsupported`、`process.lpac_unsupported`を既存分類へ統合し、category、対象、解決方法を保持する。 --- ## 21. 実装順序 | Phase | 実装 | 完了条件 | @@ -735,7 +789,7 @@ errorは内部codeとlocalized messageを分離し、ログ/auditにはcode、MC | 4 | Internal Tool dispatcher | tool schemaとToolUseGuard | | 5 | Filesystem/Process Sandbox | ACL/AppContainer/Job integration test | | 6 | Resource Transaction/Recovery | 強制crash recovery test | -| 7 | WFP | deny/allow-list integration test | +| 7 | WFP | none/local/restricted integration test | | 8 | Vision/Streamable HTTP | image optional、loopback HTTP | | 9 | Audit/Hardening | security matrix全PASS | | 10 | Release/Operational E2E | self-contained Bundle単独起動、stdio/HTTP実利用 | @@ -744,7 +798,7 @@ errorは内部codeとlocalized messageを分離し、ログ/auditにはcode、MC - `dotnet publish -c Release -r win-x64 --self-contained true` のfolder publishを配布元とする。 - Bundleはversion付きZIP、展開済みdirectory、file manifest、SHA-256 checksumから成る。 - 起動時の相対pathは実行ファイルdirectoryを基準に解決し、ソースツリーを参照しない。 -- 必須Gateはlocal Ollamaだけで実行し、cloud modelは任意互換試験に限定する。 +- 現行Operational E2Eは配布既定の`deepseek-v4-flash:cloud`を使用する。rate limit、接続失敗、model unavailableをapplication PASSとして扱わない。 --- ## 22. Codex実装制約 - 新規NuGet dependencyを勝手に追加しない。追加時は標準ライブラリで不能な理由を示す。 @@ -820,17 +874,18 @@ errorは内部codeとlocalized messageを分離し、ログ/auditにはcode、MC | ollama.options.* | typed runtime options | | ollama.extra_options.* | future passthrough options | | planner.max_tasks | 32 default | -| sandbox.filesystem.read | read allow-list | -| sandbox.filesystem.write | write allow-list | -| sandbox.filesystem.execute | execute path allow-list | -| sandbox.filesystem.delete | delete allow-list | -| sandbox.process.allow_shell | shell toggle | -| sandbox.process.approvals | path+sha256 approvals | -| sandbox.process.max_processes | Job process limit | -| sandbox.network.mode | deny/allow | -| sandbox.network.allow | host/port list | -| sandbox.resources.memory_mb | Job memory limit | -| sandbox.resources.process_timeout_seconds | process timeout | +| sandbox.profile | readonly/development Workspace preset | +| sandbox.workspaces | Workspace Logical Path list | +| sandbox.mounts | Mount Logical Path + semantic access | +| sandbox.execution.executables | Approved Entry Executable Alias list | +| sandbox.execution.shells | Approved Shell Executable Alias list | +| sandbox.network.access | none/local/restricted | +| sandbox.network.local_endpoints | Loopback port list | +| sandbox.network.restricted_endpoints | host/port list | +| sandbox.resources.profile | constrained/normal/extended | +| sandbox.resources.memory_mb | optional memory override | +| sandbox.resources.process_limit | optional Job process override | +| sandbox.resources.execution_timeout_seconds | optional execution timeout override | | file_edit.memory_backup_limit_mb | memory/temp threshold | | localization.directory | locale directory | | localization.fallback | en | @@ -875,7 +930,7 @@ errorは内部codeとlocalized messageを分離し、ログ/auditにはcode、MC - [ ] process hashは実行直前に再計算しているか。 - [ ] shell有効でもFilesystem/Network policyを迂回できないか。 - [ ] Job breakawayがないか。 -- [ ] Network allow-list外がdefault denyか。 +- [ ] Effective Network Policy外がdefault denyか。 - [ ] WFP/ACL変更前にjournalを書いているか。 - [ ] 起動時Recoveryがserveより前か。 - [ ] file rollback後にhash検証しているか。 |
