diff options
| author | tanaka takashi <isazaka@gmail.com> | 2026-08-13 18:20:33 +0900 |
|---|---|---|
| committer | tanaka takashi <isazaka@gmail.com> | 2026-08-13 18:20:33 +0900 |
| commit | 76fdcb43585a4c4d288c1026d318a0ddbe3e26ab (patch) | |
| tree | f58296832d37b035d3e787e0f270c77b59c89d77 /doc | |
| parent | 78fe349073e3a2e89f0bf14b134ae0955aa7182a (diff) | |
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.
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/AuditReport.md | 12 | ||||
| -rw-r--r-- | doc/Design.md | 19 |
2 files changed, 30 insertions, 1 deletions
diff --git a/doc/AuditReport.md b/doc/AuditReport.md index 47ee218..b176260 100644 --- a/doc/AuditReport.md +++ b/doc/AuditReport.md @@ -12,6 +12,18 @@ commit `37386b8`に対する2026-08-11の再監査結果は履歴として以下 - Entry ProcessだけをApproval対象とし、Descendant Processは個別Approvalなしで同じLPAC identity、ACL、WFP、Job confinementを継承する。 - 2026-08-12の最終working-tree検証でRelease buildはwarning 0/error 0、Core 103件、Planner 10件、Windows Security/Recovery 53件がすべてPASS、skip 0。`deepseek-v4-flash:cloud` + `think:true` + Python 3.14.3によるstdio、HTTP IPv4、HTTP IPv6 Operational E2EもすべてPASSし、各経路で複雑なPython実装、子Python、独立unittestを完走した。Task終了後のJournal、backup、published process残留は0。証跡は`artifacts/evidence/sandbox-usability-final-working-tree-2/`に保存した。 +## 2026-08-13 LPAC Descendant互換性再監査 + +`cmd.exe`から`curl.exe`を起動できない事象をEntry×Descendantで再調査した。最初のmatrixは`%ComSpec%`や`%SystemRoot%\System32\curl.exe`などドライブ修飾絶対pathを使用しており、その失敗をcmdのDescendant生成拒否と誤認していた。追加調査では、LPAC上のcmdから`cmd.exe /d /c exit 0`と`curl.exe --version`が成功した。絶対pathの場合はcmdが子Process生成前に`GetVolumeInformationW("C:\")`を呼び、そのアクセスが拒否されていた。したがって、cmdおよびLPAC/no-breakaway Process Tree一般の非互換性ではない。 + +MicrosoftのAppContainer資料は、unpackaged Win32 processをAppContainerで起動する方法と子のtoken継承を説明するが、任意のWin32 Executable組合せの動作互換性までは保証していない。LPACは`ALL APPLICATION PACKAGES`由来accessをopt-outするため、必要capabilityを明示選定する必要がある([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-))。またJob Objectではbreakawayを許可しない構成がProcess Tree監視を維持する方式であり、breakawayを許可すると子がJob外になる([Job Objects](https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects)、[Process Creation Flags](https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags))。 + +`lpacAppExperience`はMicrosoft Learn/Windows SDKで権限範囲を確認できないため採用しない。限定実験の変更も撤回した。Job breakaway、通常AppContainer fallback、System32 protected DACL解除はいずれもSecurity Boundaryを弱めるため採用していない。 + +是正として、誤ったcmd専用エラー分類と失敗を期待するtestを撤回し、protected DACLとの両立規則、capability採用基準、Entry×Descendant×System32 utilityの組合せmatrixをDesignへ追加した。cmdのtestはPATH解決名またはWorkspace相対pathで実際のDescendant起動とNetwork通信を検証する。また、HTTP MCP実動作でSystem32 rootを除外しても配下のApproved `cmd.exe` fileへ個別ACLを適用していた実装漏れを検出したため、OS Runtime Root配下全体をDACL変更対象外とした。Network capabilityなし/ありの両条件ではRegistry read、Registry write拒否、COM拒否、Broker secret非継承も組合せ検証した。 + +是正後はREADME/CLI/Windows operational suite 19件とAgent.Windows全75件が管理者・skip 0でPASSした。最新publish BundleのHTTP MCP `agent_run`もcompleted 3/3となり、cmdから非修飾`cmd.exe`、非修飾`curl.exe`、Workspace相対`C:\tmp\.venv` Pythonを起動し、Network `none`の遮断と`CMD_HTTP_MCP_OK`を確認した。全9組の子Process自身によるLPAC SID/Job個別記録は未実施のため、対応するTraceability項目だけはPARTIALとして残す。 + ## 確認した矛盾と是正 | 観点 | 監査時の状態 | 是正 | 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 | |
