From 76fdcb43585a4c4d288c1026d318a0ddbe3e26ab Mon Sep 17 00:00:00 2001 From: tanaka takashi Date: Thu, 13 Aug 2026 18:20:33 +0900 Subject: fix(sandbox): correct cmd descendant handling and protected ACL policy Replace the earlier cmd-wide descendant incompatibility diagnosis with the verified distinction between drive-qualified paths and PATH/workspace-relative invocation. Document the cmd YAML configuration, executable resolution, --no-runtime approval flow, and safe descendant invocation examples in the user README. Keep the System32 protected DACL intact for both the OS Runtime Root and approved entry files nested below it. Skip redundant file-level ACL rewrites for approved System32 executables while retaining LPAC confinement, resolved-path checks, SHA-256 approval, WFP policy, and Job Object enforcement. Expand Windows coverage with capability positive/negative matrices, protected-DACL regression tests, cmd/PowerShell/venv Python script execution, nine Entry-to-Descendant combinations, network none/local probes, and randomized ACL round-trip testing. Add read-only CLI/README verification and published HTTP MCP agent_run verification scripts. Update Design, Audit Report, and Requirement Traceability with the corrected root cause, current evidence, withdrawn diagnostic conclusions, and the remaining partial item for per-combination descendant self-recorded LPAC SID/Job evidence. Verified: Release build 0 warnings/errors; Core 103 PASS; Planner 10 PASS; Windows 75 PASS with skip 0; README operational suite 19 PASS; published HTTP MCP agent_run completed 3/3 with cmd, curl, C:\tmp\.venv Python, network-none enforcement, ACL restoration, and CMD_HTTP_MCP_OK. --- doc/Design.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'doc/Design.md') diff --git a/doc/Design.md b/doc/Design.md index 8f76ca6..d4920a0 100644 --- a/doc/Design.md +++ b/doc/Design.md @@ -557,6 +557,18 @@ network: - 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で検証する。 +- capabilityはExecutable互換性の一般的なスイッチとして追加しない。採用には、(1) Microsoft公開資料またはWindows SDKで意味とSecurity Boundaryが確認できること、(2) 必要な正方向ケースが追加前に失敗し追加後に成功すること、(3) Filesystem/Registry/COM/Network/Process Treeの負方向matrixが追加後も成功すること、(4) 名称、SID、由来、適用条件をAuditへ記録できること、をすべて要求する。意味が公開されていないcapabilityは実験結果だけでbaselineへ昇格させない。 +- `registryRead`は全Profileで必要なRegistry readだけに使用する。`lpacInstrumentation`はPowerShell起動互換性のための既存baselineであり、公開された意味の不足を負方向testで補う暫定互換capabilityとして扱う。`internetClient`/`privateNetworkClientServer` SIDはNetworkが`local|restricted`の場合だけ付与し、到達先はWFP hard permitでさらに制限する。`lpacCom`はv1で禁止する。`lpacAppExperience`は公開された権限範囲を確認できないため採用しない。 + +| capability | 根拠と用途 | 適用条件 | 必須の負方向検証 | +| --- | --- | --- | --- | +| `registryRead` | MicrosoftのLPAC起動手順に従い明示SIDとして付与し、Windows/runtimeのreadに限定 | 全Profileの固定baseline | Registry write、Broker credential環境の非継承 | +| `lpacInstrumentation` | PowerShellのETW provider登録失敗を解消した実測根拠。公開された権限範囲が不足するため暫定扱い | 全Profileの固定baseline。削除可能性を継続評価 | Registry write、COM activation、Policy外Filesystem/Network | +| `internetClient` / `privateNetworkClientServer` | Windows capability SID。WFPだけではLPAC token側のnetwork gateを通らないため使用 | Effective Network Policyが`local|restricted`のTaskだけ | `none`全deny、Policy外address/port deny、終了後WFP残留0 | +| `lpacCom` | v1がCOMを明示deny | 付与禁止 | COM activation拒否 | +| `lpacAppExperience` | 公開された権限範囲を確認できない | 付与禁止 | capability catalog/auditに出現しないこと | + +根拠資料はMicrosoftの[Launch an AppContainer](https://learn.microsoft.com/en-us/windows/win32/secauthz/implementing-an-appcontainer)、[AppContainer for legacy applications](https://learn.microsoft.com/en-us/windows/win32/secauthz/appcontainer-for-legacy-applications-)、[UpdateProcThreadAttribute](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute)を正本とする。名称からSIDを導出できることだけを権限範囲の根拠にしてはならない。 - 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 @@ -565,7 +577,9 @@ network: - 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権限を暗黙に拡張しない。 +- protected DACLを持つrootまたはdescendantの継承保護は解除せず、所有権変更やDACL全体の置換も行わない。Application SID ACEをそのobjectへ安全に追加できない場合はOS拒否を維持してfail-closedにする。 +- OS Runtime Root (`%SystemRoot%/System32`) はOSが管理するprotected DACLとの両立を優先し、BrokerがApplication SID ACEを追加しない。OS Runtime Root配下のApproved Entry Executable fileにも個別ACEを追加しない。LPACから観測される既存のOS accessだけを利用し、Effective Sandbox Policyの`os_runtime_root: read/execute`はDACL変更命令ではなく許容上限を表す。実際のExecutable互換性はEntry/Descendant組合せtestで確認する。 +- Workspace、Mount、Runtime Rootではrootの現在のSecurity DescriptorをJournalへ保存した後、protected状態を維持したまま追加ACEを適用できる場合だけleaseを成立させる。cleanup後は元Security Descriptorとのbyte-level一致を検証する。nested protected DACLがrootの継承ACEを遮る場合、そのobjectを自動走査して保護解除せず、必要accessが得られなければその組合せを拒否する。 - rootの元security descriptorをRecovery Journalへ1件記録する。 - Task終了で追加分を除去し、元状態との整合を検査する。 ### 11.3 Job Object @@ -767,6 +781,9 @@ closed Sessionは再利用しない。プロセス再起動後に以前のSessio | 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 | +| ST-25 | Entry (`PowerShell`/Python/.NET/`cmd`) × Descendant (`cmd`/PowerShell/Python/.NET/System32 utility) | 個別Approvalなしで起動し、Descendantが同じLPAC SID/Jobに残る。cmd内からはPATH解決名またはWorkspace相対pathを使用する | +| ST-26 | protected DACL root/descendantと通常DACL rootのread/write/execute | protected bitを解除せず、許可ケースだけ成功。適用不能ケースは拒否し、cleanup後Security Descriptorが完全一致 | +| ST-27 | baseline/Network capabilityの追加前後 | 必要な正方向ケースに加えFilesystem、Registry write、COM、Policy外Network、Job breakawayの負方向集合をすべて検証 | --- ## 20. エラー分類 | Category | 例 | Task結果 | Retry | -- cgit v1.2.3