diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index 4de60e541..363c3875d 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -17841,7 +17841,7 @@ }, "publicRuntime": { "title": "Public / admin / API runtime config", - "body": "AWOOOI、AwoooP、IwoooS、任務媒合產品、股票研究平台、官方形象網站、藥局網站、直播角色網站 等公開、後台、API、callback、webhook 與 env runtime config 已新增變更證據驗收;目前只收 affected route、auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、desktop / mobile smoke、sensitive scan 與 rollback owner,不改 CORS、不改 route、不部署,也不得暴露 raw namespace、內部狀態碼或內部協作內容。" + "body": "AWOOOI、AwoooP、IwoooS、任務媒合產品、股票研究平台、官方形象網站、藥局網站、直播角色網站 等公開、後台、API、callback、webhook 與 env runtime config 已新增變更證據驗收;前台 source / messages 也已納入敏感資訊防洩漏 guard,掃 225 個檔案、12 類禁字、違規 0。目前只收 affected route、auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、desktop / mobile smoke、sensitive scan 與 rollback owner,不改 CORS、不改 route、不部署,也不得暴露 raw namespace、內部狀態碼或內部協作內容。" }, "agentBounty": { "title": "agent-bounty runtime / treasury", @@ -17920,7 +17920,7 @@ }, "coverage": { "label": "平均成熟度", - "detail": "owner response acceptance 帳本推進後平均控管成熟度為 69%。" + "detail": "owner response acceptance 與前台 source guard 推進後平均控管成熟度為 70%。" }, "runtimeGate": { "label": "執行期", diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index 4de60e541..363c3875d 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -17841,7 +17841,7 @@ }, "publicRuntime": { "title": "Public / admin / API runtime config", - "body": "AWOOOI、AwoooP、IwoooS、任務媒合產品、股票研究平台、官方形象網站、藥局網站、直播角色網站 等公開、後台、API、callback、webhook 與 env runtime config 已新增變更證據驗收;目前只收 affected route、auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、desktop / mobile smoke、sensitive scan 與 rollback owner,不改 CORS、不改 route、不部署,也不得暴露 raw namespace、內部狀態碼或內部協作內容。" + "body": "AWOOOI、AwoooP、IwoooS、任務媒合產品、股票研究平台、官方形象網站、藥局網站、直播角色網站 等公開、後台、API、callback、webhook 與 env runtime config 已新增變更證據驗收;前台 source / messages 也已納入敏感資訊防洩漏 guard,掃 225 個檔案、12 類禁字、違規 0。目前只收 affected route、auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、desktop / mobile smoke、sensitive scan 與 rollback owner,不改 CORS、不改 route、不部署,也不得暴露 raw namespace、內部狀態碼或內部協作內容。" }, "agentBounty": { "title": "agent-bounty runtime / treasury", @@ -17920,7 +17920,7 @@ }, "coverage": { "label": "平均成熟度", - "detail": "owner response acceptance 帳本推進後平均控管成熟度為 69%。" + "detail": "owner response acceptance 與前台 source guard 推進後平均控管成熟度為 70%。" }, "runtimeGate": { "label": "執行期", diff --git a/apps/web/src/app/[locale]/iwooos/page.tsx b/apps/web/src/app/[locale]/iwooos/page.tsx index 2b2fc09ec..7967fdb59 100644 --- a/apps/web/src/app/[locale]/iwooos/page.tsx +++ b/apps/web/src/app/[locale]/iwooos/page.tsx @@ -2087,7 +2087,7 @@ const highValueConfigOwnerPacketSummary = [ const highValueConfigControlCoverageSummary = [ { key: 'categories', value: '14', icon: ListChecks, tone: 'steady' }, { key: 'c0', value: '8', icon: AlertTriangle, tone: 'warn' }, - { key: 'coverage', value: '69%', icon: ShieldCheck, tone: 'warn' }, + { key: 'coverage', value: '70%', icon: ShieldCheck, tone: 'warn' }, { key: 'runtimeGate', value: '0', icon: Lock, tone: 'locked' }, ] as const @@ -2104,7 +2104,7 @@ const highValueConfigControlCoverageBoundaries = [ 'high_value_config_control_coverage_category_count=14', 'high_value_config_control_coverage_c0_category_count=8', 'high_value_config_control_coverage_c1_category_count=4', - 'high_value_config_control_coverage_average_percent=69', + 'high_value_config_control_coverage_average_percent=70', 'high_value_config_control_coverage_needs_live_evidence_count=10', 'high_value_config_control_coverage_owner_response_required_count=14', 'high_value_config_control_coverage_owner_response_received_count=0', @@ -2119,7 +2119,11 @@ const highValueConfigControlCoverageBoundaries = [ 'k8s_production_gitops_coverage_percent=64', 'secret_metadata_coverage_percent=68', 'gitea_workflow_runner_source_control_coverage_percent=72', - 'public_admin_api_runtime_config_coverage_percent=64', + 'public_admin_api_runtime_config_coverage_percent=66', + 'public_frontend_sensitive_surface_guard_file_count=225', + 'public_frontend_sensitive_surface_guard_forbidden_pattern_count=12', + 'public_frontend_sensitive_surface_guard_violation_count=0', + 'public_frontend_sensitive_surface_guard_runtime_gate_count=0', 'public_runtime_config_change_evidence_acceptance_candidate_count=6', 'public_runtime_config_change_evidence_acceptance_c0_candidate_count=5', 'public_runtime_config_change_evidence_acceptance_c1_candidate_count=1', @@ -2378,7 +2382,10 @@ const criticalConfigPriorityBoundaries = [ 'nginx_public_gateway_rendered_diff_accepted=false', 'nginx_public_gateway_rendered_diff_acceptance_candidate_count=3', 'nginx_public_gateway_nginx_test_evidence_count=0', - 'public_admin_api_runtime_config_coverage_percent=64', + 'public_admin_api_runtime_config_coverage_percent=66', + 'public_frontend_sensitive_surface_guard_file_count=225', + 'public_frontend_sensitive_surface_guard_forbidden_pattern_count=12', + 'public_frontend_sensitive_surface_guard_violation_count=0', 'public_runtime_config_change_evidence_acceptance_candidate_count=6', 'public_runtime_config_change_evidence_acceptance_c0_candidate_count=5', 'public_runtime_config_change_evidence_acceptance_write_capable_candidate_count=6', diff --git a/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md b/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md index e68946b37..64a736c4e 100644 --- a/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md +++ b/docs/security/HIGH-VALUE-CONFIG-CONTROL-COVERAGE.md @@ -52,6 +52,8 @@ 此帳本明確把 raw owner namespace、repo slug、內部狀態碼、內部協作文字、cookie、token、secret value、DSN value、raw payload 與未脫敏截圖列為拒收或隔離條件。前台可以顯示產品 / 專案脫敏名稱與控管狀態,但不得顯示個人 namespace、內部狀態碼、內部協作內容或抱怨語句。 +2026-06-15 再新增 `docs/security/public-frontend-sensitive-surface-guard.snapshot.json`,並將 `scripts/security/public-frontend-env-guard.py` 擴充為前台 source / messages 敏感資訊防洩漏 guard。固定 `public_surface_file_count=225`、`forbidden_pattern_count=12`、`allowlisted_match_count=2`、`violation_count=0`、`env_violation_count=0`、`runtime_gate_count=0`。此更新讓 `public_admin_api_runtime_config` 從 `64%` 推進到 `66%`,高價值配置平均只讀成熟度從 `69%` 推進到 `70%`;但 production bundle scan、desktop / mobile production smoke accepted、owner response、route / CORS / env / auth / webhook 變更、frontend / API deploy、production deploy 與 runtime gate 仍全部為 `0 / false`。 + ## 1.3 2026-06-14 agent-bounty-protocol owner request draft 已新增 `docs/security/AGENT-BOUNTY-OWNER-REQUEST-DRAFT.md` 與 `docs/security/agent-bounty-owner-request-draft.snapshot.json`,將 `agent-bounty-protocol` onboarding handoff 轉成 11 份 owner request draft。 @@ -103,7 +105,7 @@ | C1 類別 | `4` | 監控、Docker / systemd、SSH / network、AI provider | | C2 類別 | `1` | 產品 runtime route 與跨產品邊界 | | C3 類別 | `1` | security evidence / snapshot / guard tooling | -| 平均只讀控管成熟度 | `69%` | 僅代表框架 / evidence / owner packet / acceptance ledger 準備度,不代表 runtime 可執行 | +| 平均只讀控管成熟度 | `70%` | 僅代表框架 / evidence / owner packet / acceptance ledger / source guard 準備度,不代表 runtime 可執行 | | 需要 live / owner evidence 的類別 | `10` | 只能等 owner-provided redacted evidence 或維護窗口,不主動修改 workflow、secret、runner、route、CORS、env、備份或主機 | | owner response required | `14` | 每類都需要 owner response 才能往 accepted 前進 | | owner response received / accepted | `0 / 0` | 不得假性提高 | @@ -247,7 +249,7 @@ python3 scripts/security/iwooos-config-control-guard.py --root . | DNS / TLS / certbot owner response acceptance | `100%` | 已新增 `domain_tls_certbot_owner_response_acceptance_v1`,4 個 C0 candidate、13 個 owner 必填欄位、13 個 reviewer checks、7 條 outcome lanes、20 類 blocked action;成熟度 `74% -> 78%` | | Docker / systemd / host service owner response acceptance | `100%` | 已新增 `host_service_owner_response_acceptance_v1`,9 個 candidate、3 個 write-capable、21 個 reviewer checks、8 條 outcome lanes、27 類 blocked action;成熟度 `54% -> 58%` | | CD / Runner / Secret injection change evidence acceptance | `100%` | 已新增 `cd_runner_secret_injection_change_evidence_acceptance_v1`,5 個 candidate、4 個 C0、19 個 reviewer checks、8 條 outcome lanes、32 類 blocked action;secret metadata 成熟度 `66% -> 68%`,workflow / runner 成熟度 `70% -> 72%` | -| Public / Admin / API runtime config 變更證據驗收 | `100%` | 已新增 `public_runtime_config_change_evidence_acceptance_v1`,6 個 candidate、5 個 C0、21 個 reviewer checks、8 條 outcome lanes、32 類 blocked action;public/admin/API runtime config 成熟度 `62% -> 64%`,raw namespace / repo slug / 內部狀態碼 / 內部協作內容外洩列為拒收或隔離條件 | +| Public / Admin / API runtime config 變更證據驗收 | `100%` | 已新增 `public_runtime_config_change_evidence_acceptance_v1` 與前台 source / messages 防洩漏 guard;6 個 candidate、5 個 C0、21 個 reviewer checks、8 條 outcome lanes、32 類 blocked action,另掃 225 個前端檔案、12 類禁字、違規 0;public/admin/API runtime config 成熟度 `62% -> 66%`,raw namespace / repo slug / 內部狀態碼 / 內部協作內容外洩列為拒收或隔離條件 | | Backup / restore / escrow owner response acceptance backfill | `100%` | 已將 `backup_restore_owner_response_acceptance_v1` 補強為 38 個 candidate、27 個 write-capable、23 個 owner 必填欄位、22 個 reviewer checks、9 條 outcome lanes、31 類 blocked action;backup / restore / credential 成熟度 `62% -> 64%` | | owner response 收件 | `0%` | 尚未收到或接受任何 owner response | | live evidence collection | `0%` | 未 SSH、未 live probe、未 active scan | diff --git a/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md b/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md index 06f652dbe..3281909ed 100644 --- a/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md +++ b/docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md @@ -32,7 +32,7 @@ | 註冊配置類別 | `14` | 代表已進 Gate 分類,不代表已批准 | | C0 類別 | `8` | Nginx、DNS / TLS、K8s、secret、workflow / runner、runtime config、backup、agent-bounty runtime | | C1 類別 | `4` | 監控、Docker / systemd、SSH / network、AI provider | -| 平均只讀控管成熟度 | `69%` | 只代表框架 / evidence / owner packet / acceptance ledger 準備度 | +| 平均只讀控管成熟度 | `70%` | 只代表框架 / evidence / owner packet / acceptance ledger / source guard 準備度 | | 需要 live evidence 類別 | `10` | 只能等 owner-provided redacted evidence 或維護窗口,不主動 SSH、不改 route / CORS / env / backup | | owner response required | `14` | owner response received / accepted 仍 `0 / 0` | | runtime gate | `0` | 不提供執行按鈕 | @@ -77,6 +77,8 @@ 此帳本同時把 raw owner namespace、repo slug、內部狀態碼、內部協作文字、cookie、token、secret value、DSN value、raw payload 與未脫敏截圖列為拒收或隔離條件。AwoooP Tenants、IwoooS、Code Review 或其他公開頁只能顯示脫敏產品 / 專案名稱與控管狀態,不得顯示個人 namespace、內部狀態碼、內部協作內容或抱怨語句。 +2026-06-15 再新增 `public_frontend_sensitive_surface_guard_v1` snapshot,並將 `scripts/security/public-frontend-env-guard.py` 擴充為 source / messages 防洩漏 guard。固定掃描 `225` 個前端檔案、`12` 類禁字、`2` 個遮罩器 allowlist、`0` 個違規、`0` 個 env violation、`0` 個 runtime gate。此更新讓 Public / admin / API / frontend runtime config 類別成熟度從 `64%` 推進到 `66%`;但 production bundle scan accepted、desktop / mobile production smoke accepted、owner response received / accepted、route / CORS / env / auth / webhook 變更、frontend / API deploy、runtime gate 仍全部為 `0 / false`。 + `backup_restore_owner_request_draft_v1` 已把 backup、restore、offsite、credential escrow、retention、Velero、alert / health 與 DR runbook 的 38 個 surface 轉成人工送件前 owner request draft。固定 `drafts=38`、`write_capable=27`、`live_evidence_required=38`、`owner_fields=14`、`blocked_actions=18`,但 request sent、owner response received / accepted、live backup evidence、backup run、restore run、offsite sync、remote delete、escrow marker write、retention change、host write、runtime gate 仍全部為 `0 / false`。 此更新仍不是 live network truth:live firewall、sudoers、known_hosts、NetworkPolicy、NodePort、WireGuard evidence、network owner、maintenance window、rollback owner 與 owner response received / accepted 全部仍為 `0`,也不得執行 SSH、keyscan、sudo、firewall change、NetworkPolicy apply、NodePort change 或 WireGuard cutover。 @@ -259,7 +261,7 @@ Nginx 是目前必須最先資安控管的配置,原因是它同時控制公 | SSH / firewall / network owner response acceptance | `100%` | 已新增 `ssh_network_owner_response_acceptance_v1`,16 個 candidate、6 個 write-capable、15 個 reviewer checks、7 條 outcome lanes、22 類 blocked action;成熟度 `54% -> 58%` | | 端口 / 防火牆變更證據驗收 | `100%` | 已新增並強化 `port_firewall_change_evidence_acceptance_v1`,14 個 candidate、6 個 write-capable、21 個 reviewer checks、9 條 outcome lanes、28 類 blocked action;成熟度 `58% -> 62%` | | K8s / ArgoCD GitOps 變更證據驗收 | `100%` | 已新增 `k8s_argocd_change_evidence_acceptance_v1`,4 個 candidate、3 個 C0、4 個 write-capable、18 個 reviewer checks、8 條 outcome lanes、28 類 blocked action;成熟度 `62% -> 64%` | -| Public / Admin / API runtime config 變更證據驗收 | `100%` | 已新增 `public_runtime_config_change_evidence_acceptance_v1`,6 個 candidate、5 個 C0、21 個 reviewer checks、8 條 outcome lanes、32 類 blocked action;成熟度 `62% -> 64%`;raw namespace / repo slug / 內部狀態碼 / 內部協作內容外洩列為拒收或隔離條件 | +| Public / Admin / API runtime config 變更證據驗收 | `100%` | 已新增 `public_runtime_config_change_evidence_acceptance_v1` 與 `public_frontend_sensitive_surface_guard_v1`;6 個 candidate、5 個 C0、21 個 reviewer checks、8 條 outcome lanes、32 類 blocked action,另掃 225 個前端檔案、12 類禁字、違規 0;成熟度 `62% -> 66%`;raw namespace / repo slug / 內部狀態碼 / 內部協作內容外洩列為拒收或隔離條件 | | Package / Docker supply-chain repo-only baseline | `100%` | 已新增 `package_supply_chain_baseline_v1`,盤點 `package_json=6`、`pyproject=4`、`requirements=2`、`dockerfiles=2`、`compose=6`、`gaps=5`;不 install、不掃 CVE、不改 image、不部署 | | Package / Docker supply-chain owner policy gate | `100%` | 已新增 `package_supply_chain_owner_policy_gate_v1`,6 個 owner policy request、2 個 C0、8 個 owner 欄位、12 個 reviewer checks、20 類 blocked action;request_sent / received / accepted / runtime / action 仍為 `0 / false` | | Backup / restore / escrow owner request draft | `100%` | 已將 38 個 backup / restore / escrow surface 轉成 owner request draft;request sent / received / accepted、backup run、restore run、offsite sync、remote delete、escrow marker write、retention change 仍為 0 | @@ -276,7 +278,7 @@ Nginx 是目前必須最先資安控管的配置,原因是它同時控制公 2. P0:由 owner 提供脫敏 live Nginx conf 匯出檔,重跑 compare mode;不自動覆寫、不 reload。 3. P0:向 owner 收 DNS / TLS / certbot 脫敏 coverage metadata ref、expiry metadata ref、renewal owner、ACME route owner、maintenance window、rollback owner 與 validation plan;不做 DNS query、TLS probe、certbot renew 或 reload。 4. P0:把 workflow / runner / secret name owner response 與高價值配置 C0 gate 串成同一個 IwoooS 狀態。 -5. P0:收 public / admin / API runtime config 的脫敏變更證據,先補 affected route、auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、desktop / mobile smoke、sensitive string scan、rollback owner 與 post-check evidence;不改 route / CORS / env。 +5. P0:收 public / admin / API runtime config 的脫敏變更證據,先補 affected route、auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、desktop / mobile smoke、production bundle sensitive scan、rollback owner 與 post-check evidence;source / messages 防洩漏 guard 已固定違規 0,但仍不改 route / CORS / env。 6. P0:把 agent-bounty-protocol compose / MCP / A2A / treasury 高價值配置欄位接入同一個 owner packet queue;不啟用 runtime。 7. P1:向 owner 收 110 / 188 Docker Compose 與 systemd 脫敏 live hash metadata、maintenance / restart window、rollback owner、post-check plan、disable switch 與 no-secret-value evidence;不主動 SSH、不重啟、不跑 repair-bot。 7. P1:向 owner 收 SSH / firewall / WireGuard / NodePort 脫敏 live access state、allowed source CIDR、change / incident ref、actor、before / after state、cross-project sync、maintenance window、rollback owner 與 validation plan;不主動 keyscan、不改 firewall、不開關端口。 diff --git a/docs/security/IWOOOS-POSTURE-PROJECTION.md b/docs/security/IWOOOS-POSTURE-PROJECTION.md index 942902be3..5633c1a38 100644 --- a/docs/security/IWOOOS-POSTURE-PROJECTION.md +++ b/docs/security/IWOOOS-POSTURE-PROJECTION.md @@ -95,7 +95,8 @@ IwoooS 首版只讀取或對齊以下已提交 evidence: 51. 10 個 frontend surface reverse bridge statuses,顯示既有資安入口目前是 embedded bridge、direct bridge 或 AwoooP read-only candidate;這只是連接狀態,不代表 owner response、runtime authorization、Code Review blocker、Gitea/GitHub action 或任何執行控制。 52. 6 個 source control primary readiness items,顯示 GitHub primary 前置缺口:candidate repo inventory、primary ready counter、owner response validation、refs truth、workflow / secret name inventory、rollback ADR;這只是 readiness,不代表 repo 建立、visibility 變更、refs mutation、secret value collection、primary switch 或 Gitea 停用。 53. 4 個 rollout risk read-only items,顯示風險來源部署 marker、`AWOOOI_ROLLOUT_RISK=1`、ArgoCD `Degraded` / `OutOfSync`、API health / smoke 已通過與執行期閘門仍為 0;這只是部署風險可見性,不代表 ArgoCD sync、kubectl、主機重啟、修復、部署或 runtime gate 已授權。 -54. 14 類 high-value config control coverage statuses,顯示 Nginx、DNS / TLS、K8s、機密、工作流程、執行器、backup、agent-bounty runtime、monitoring、Docker / systemd、SSH / network、AI provider、產品 route 與 security evidence 的全域配置控管覆蓋矩陣;平均只讀成熟度 `69%`、C0 類別 `8`、需 live / owner evidence 類別 `10`、owner response received / accepted 與 runtime gate 仍為 `0`,不代表 reload、sync、scan、secret rotation、payout 或主機操作授權。 +54. 14 類 high-value config control coverage statuses,顯示 Nginx、DNS / TLS、K8s、機密、工作流程、執行器、backup、agent-bounty runtime、monitoring、Docker / systemd、SSH / network、AI provider、產品 route 與 security evidence 的全域配置控管覆蓋矩陣;平均只讀成熟度 `70%`、C0 類別 `8`、需 live / owner evidence 類別 `10`、owner response received / accepted 與 runtime gate 仍為 `0`,不代表 reload、sync、scan、secret rotation、payout 或主機操作授權。 +54a. 前台 source / messages 敏感資訊防洩漏 guard 已固定 `public_surface_file_count=225`、`forbidden_pattern_count=12`、`allowlisted_match_count=2`、`violation_count=0`、`runtime_gate_count=0`,讓 `public_admin_api_runtime_config` 從 `64%` 推進到 `66%`;這只代表 source-control 防洩漏 gate,仍不是 production bundle scan accepted、desktop / mobile production smoke accepted、owner response accepted 或 runtime gate。 55. 9 個 host-service config repo-only inventory surfaces,顯示 Docker Compose、systemd / repair-bot、Ansible service role 與 host config backup capture 的第一層清冊;write-capable surface `3`、repair-bot whitelist `2`、systemd restart surface `1`,owner response、live evidence、restart window、rollback owner、runtime gate 與 action button 仍全部為 `0`,不代表 `docker compose`、`systemctl`、repair-bot 或 Ansible apply 已授權。 56. 16 個 SSH / network access repo-only inventory surfaces、owner response acceptance 與端口 / 防火牆變更證據驗收只讀帳本,顯示 SSH target、known_hosts workflow、CI deploy SSH、monitoring SSH、backup SSH capture、sudoers wrapper、NetworkPolicy、NodePort、WireGuard runbook 與 alert SSH action catalog 的第一層清冊;write-capable surface `6`、NetworkPolicy `2`、NodePort `2`、sudoers `1`、WireGuard `1`,acceptance candidate `16`、change evidence candidate `14`、reviewer check `21`、outcome lane `9`、blocked action `28`,讓 SSH / network 類別成熟度從 `58%` 推進到 `62%`;owner response、change evidence、actor、before / after state、service health impact、operator notification、cross-project sync、post-check evidence、maintenance window、rollback owner、runtime gate 與 action button 仍全部為 `0`,不代表 SSH、sudo、firewall、port close / open、NetworkPolicy、NodePort、WireGuard、route smoke 或 known_hosts patch 已授權。 56a. 4 個 K8s / ArgoCD GitOps 變更證據驗收候選,顯示 production manifests、ArgoCD app、Velero、monitoring manifests 的 proposed commit、rendered manifest diff、ArgoCD app / sync revision、health before / after、rollout、route smoke、metrics / alert、secret metadata parity、blast radius、maintenance window、rollback revision 與 postcheck owner 收件規則;C0 candidate `3`、write-capable candidate `4`、reviewer check `18`、outcome lane `8`、blocked action `28`,讓 K8s / ArgoCD 類別成熟度從 `62%` 推進到 `64%`;change evidence、runtime approval package、ArgoCD API read、ArgoCD sync、kubectl action、Helm upgrade、NetworkPolicy / NodePort / RBAC change、production write、runtime gate 與 action button 仍全部為 `0`。 diff --git a/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md b/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md index d42533444..8093657ec 100644 --- a/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md +++ b/docs/security/SECURITY-SUPPLY-CHAIN-PROGRESS.md @@ -3,11 +3,11 @@ | 項目 | 內容 | |------|------| | 日期 | 2026-06-15 | -| 狀態 | IwoooS 64% 只讀治理推進中;高價值配置集中 guard、Package / Docker 供應鏈 repo-only baseline 與 Package / Docker 供應鏈 owner policy gate 已完成;Backup / Restore / Escrow owner response acceptance backfill、Monitoring / Alerting / Observability owner response acceptance、CD / Runner / Secret 注入變更證據驗收與 Public / Admin / API runtime config 變更證據驗收只讀帳本已本地完成;端口 / 防火牆變更證據驗收、主機服務事故回補與 K8s / ArgoCD GitOps 變更證據驗收已正式部署驗證;S4.9 owner response gate 仍是第一優先 | +| 狀態 | IwoooS 64% 只讀治理推進中;高價值配置集中 guard、Package / Docker 供應鏈 repo-only baseline 與 Package / Docker 供應鏈 owner policy gate 已完成;Frontend public sensitive surface guard、Backup / Restore / Escrow owner response acceptance backfill、Monitoring / Alerting / Observability owner response acceptance、CD / Runner / Secret 注入變更證據驗收與 Public / Admin / API runtime config 變更證據驗收只讀帳本已本地完成;端口 / 防火牆變更證據驗收、主機服務事故回補與 K8s / ArgoCD GitOps 變更證據驗收已正式部署驗證;S4.9 owner response gate 仍是第一優先 | | 本階段完成 | 資安供應鏈 contract manifest + Source Control Approval Board + Draft Reconcile Plan + Ref Detail Diff + Ref Truth Classification + Source Control Ref Truth Owner Response 收件包 + GitHub Primary Readiness Gate + GitHub Primary Rollback ADR + GitHub Target Owner Decision Response 收件包 + Gitea 認證清冊匯出請求 + Gitea 認證清冊匯入驗收契約 + Gitea 清冊覆蓋 Owner Attestation + Gitea Owner Attestation Approval Lane 對齊 + Gitea Owner Attestation Response 收件包 + Workflow / Secret Name Inventory + Workflow / Secret Name Local Evidence + Workflow / Secret Name Redacted Export Request + Workflow / Secret Name Owner Response 收件包 + Source Control Owner Response Validation Rollup + Kali 112 live integration status + Security Finding contract + Kali scan scope approval package + Security Approval Queue + S3 人工批准 Gate + S3 人工決策紀錄 + S3 人工審查封包 + S3 人工決策狀態轉移 + S3 後續 runtime gate 準備契約 + 鏡像 readiness index + 鏡像接收計畫 + 鏡像事件信封 + 鏡像路由矩陣 + 鏡像驗收契約 + 鏡像隔離契約 + 鏡像 dry-run 報告契約 + 鏡像狀態彙整契約 + IwoooS 前端態勢入口 + IwoooS posture projection contract + IwoooS 既有前端資安頁面整合 + IwoooS 覆蓋與邊界矩陣 + IwoooS 只讀資安處理旅程 + IwoooS owner evidence readiness board + IwoooS host coverage view + IwoooS host action gate matrix + IwoooS host evidence readiness board + IwoooS host evidence collection order + IwoooS host evidence intake preflight + IwoooS host evidence review outcome lanes + IwoooS host evidence review handoff packets + IwoooS host evidence reviewer checklist + IwoooS host evidence reviewer outcome lanes + IwoooS host owner decision candidate packets + IwoooS host owner decision review checklist + IwoooS host owner decision review outcome lanes + IwoooS host owner decision record draft packets + IwoooS host owner decision record draft review checklist + IwoooS host owner decision record draft review outcome lanes + IwoooS host owner decision record write-up packets + IwoooS host owner decision record write-up review checklist + IwoooS host owner decision record write-up review outcome lanes + IwoooS host owner decision record formal candidate packets + IwoooS host owner decision record formal candidate review checklist + IwoooS host owner decision record formal candidate review outcome lanes + IwoooS host owner decision record formal record queue packets + IwoooS host owner decision record formal record queue review checklist + IwoooS host owner decision record formal record queue review outcome lanes + IwoooS host owner decision record human handoff readiness packets + IwoooS host owner decision record human handoff readiness review checklist + IwoooS host owner decision record human handoff readiness review outcome lanes + IwoooS host owner decision record human record owner review candidate packets + IwoooS host owner decision record human record owner review candidate checklist + IwoooS host owner decision record human record owner review candidate outcome lanes + IwoooS host owner decision record human record owner review preparation packets + IwoooS host owner decision record human record owner review preparation checklist + IwoooS progress acceleration lanes + IwoooS owner response next-action focus + IwoooS S4.9 owner response preflight + IwoooS S4.9 owner response request templates + IwoooS progress hold movement gates + IwoooS AwoooP read-only landing readiness + IwoooS AwoooP cross-session handoff packets + AwoooP 首頁 IwoooS 資安鏡像候選 + AwoooP 工作鏈路 IwoooS 資安鏡像候選 + AwoooP 審批佇列 IwoooS owner response 只讀焦點 | | 本階段追加 | AwoooP 合約儀表板 IwoooS 資安契約只讀候選 + AwoooP 租戶管理 IwoooS 資安租戶範圍只讀候選 + AwoooP 執行監控 IwoooS 執行狀態只讀候選 + 既有安全 / 合規頁面 IwoooS 只讀反向橋接 + 告警 / 錯誤 / 授權 / 治理頁面 IwoooS 只讀反向橋接 + 稽核 / 工程審查頁面 IwoooS 深色只讀反向橋接 + IwoooS 前端資安頁面連接狀態板 + IwoooS GitHub 主要來源就緒度只讀狀態板 + AwoooP 工作鏈路 GitHub 主要來源就緒度只讀工作項 + AwoooP 合約儀表板 GitHub 主要來源就緒度合約只讀候選 + AwoooP 審批佇列 GitHub 主要來源就緒度審批邊界 + AwoooP 首頁 GitHub 主要來源就緒度只讀摘要 + AwoooP 租戶管理 GitHub 主要來源就緒度租戶範圍 + AwoooP 執行監控 GitHub 主要來源就緒度執行邊界 + IwoooS / AwoooP 資安可視區塊繁體中文呈現防護檢查 + AwoooP 執行詳情 / 審批詳情繁體中文呈現防護檢查 + AwoooP 首頁負責人回覆驗收總覽 + AwoooP 工作鏈路負責人回覆驗收只讀工作項 + AwoooP 合約儀表板負責人回覆驗收契約只讀候選 + AwoooP 審批佇列負責人回覆驗收只讀審查邊界 + AwoooP 租戶管理負責人回覆驗收租戶範圍 + AwoooP 執行監控負責人回覆驗收執行邊界 + AwoooP 執行詳情負責人回覆驗收詳情邊界 + AwoooP 審批決策負責人回覆驗收審批邊界 + IwoooS AwoooP 資安入口覆蓋狀態板 + IwoooS 階段式資安收斂節奏圖 + IwoooS 下一步人工收件作戰板 + IwoooS 人工回覆安全驗收閘道 + IwoooS 人工回覆審查結果分流 + IwoooS 人工決策準備佇列 + IwoooS 人工決策紀錄草稿防誤用 + IwoooS 人工決策正式紀錄負責人指派確認準備包 + IwoooS 人工決策正式紀錄負責人指派確認清單 + IwoooS 人工決策正式紀錄負責人指派確認結果分流 + IwoooS 人工決策正式紀錄負責人指派決策準備包 + IwoooS 人工決策正式紀錄負責人指派決策檢查清單 + IwoooS S4.9 負責人回覆封套欄位 + IwoooS S4.9 負責人回覆封套送件前檢查 + IwoooS S4.9 負責人回覆封套送件前結果分流 + IwoooS S4.9 負責人回覆送件請求草稿 + IwoooS S4.9 負責人回覆送件鏈路摘要 + IwoooS 低摩擦分階段收斂主控 + IwoooS 低摩擦下一步行動邊界 + IwoooS 64% 進度移動訊號驗收條 + IwoooS 第一個進度解鎖路徑 + IwoooS 第一解鎖證據包 + IwoooS 第一解鎖證據包預檢分流 + IwoooS 第一解鎖證據包補件路徑 + IwoooS 第一解鎖證據包補件送審前檢查 + IwoooS 第一解鎖證據包補件送審結果分流 + IwoooS 第一解鎖證據包 reviewer 指派準備包 + IwoooS 第一解鎖證據包 reviewer 指派前檢查 + IwoooS 第一解鎖證據包 reviewer 指派前檢查結果分流 + IwoooS 正式只讀 landing 與 Kali 112 只讀證據進度重估 | | 本階段追加補充 | IwoooS 目前具體工作地圖 + IwoooS 目前具體交付清單 + IwoooS 目前阻塞與解除條件 + IwoooS 三軸進度與全產品套用範圍 + IwoooS 全產品分階段套用台帳 + IwoooS 全產品 rollout 波次驗收門檻 + IwoooS 全產品 rollout 驗收結果分流 + IwoooS 全產品證據接線地圖 + IwoooS 全產品證據接線預檢 + IwoooS 全產品證據接線預檢結果分流 + IwoooS 全產品預檢補件回收台帳 + IwoooS 全產品補件重試門檻 + IwoooS 全產品重試結果分流 + IwoooS 全產品人工審查候選準備 + IwoooS 全產品人工審查候選預檢 + IwoooS 全產品人工審查候選預檢結果分流 + IwoooS 全產品人工審查候選預檢補件回收台帳 + IwoooS 全產品人工審查候選預檢補件重試門檻 + IwoooS 全產品只讀套用快照 + P2-145 owner response acceptance gate 正式驗證完成 | -| P0 追加 | IwoooS P0 配置控管優先序前台正式驗證完成;Nginx public gateway、DNS / TLS / certbot、K8s / ArgoCD / production manifests、Workflow / runner / secret metadata、Public / admin / API runtime config、agent-bounty runtime / treasury 六類先列為即時風險配置;高價值配置 Gate 已補上 `k8s/nginx/**`、`scripts/ops/**/*cert*`、`scripts/ops/**/*tls*`,sample 從 `matched=0 / C0=0` 收斂到 `matched=3 / C0=2`;Gate 預設工作樹 preflight 已可讀取 staged / unstaged / untracked,本地 smoke 對臨時 `k8s/nginx/*` 檔命中 C0;Owner Packet snapshot 已同步為 `packets=3 / c0=2`,Coverage snapshot 已同步最新 patterns;IwoooS / AwoooP 前台 Owner Packet 摘要已正式驗證 `packet=3 / c0=2`,feature commit `e999c16b`、deploy marker `16c6b983`、Gitea code-review `2973` / CD `2972` success;IwoooS posture projection snapshot / schema / guard 已同步 `packet=3 / c0=2`,不再保留舊 `1 / 0` 口徑;高價值配置 Owner Packet 收件預檢已新增 `checks=9 / lanes=5 / required_fields=27 / blocked_requests=16`;高價值配置 Owner Request 草稿包已新增 `drafts=3 / handoff_fields=11 / forbidden_payloads=12 / sent=0`;Public Gateway live conf 匯出請求包已新增 `requests=3 / c0=2 / redaction_rules=8 / received=0`;Public Gateway redacted export 收件預檢已新增 `candidates=3 / c0=2 / checks=10 / rejection_guards=12 / received=0 / accepted=0`;Public Gateway rendered diff / nginx gate 草稿已新增 `candidates=3 / c0=2 / stages=7 / blocked=14 / rendered_diff=0 / runtime=0`;Public Gateway owner response acceptance 只讀帳本已新增 `candidates=3 / c0=2 / fields=33 / checks=22 / lanes=8 / blocked=28 / accepted=0 / runtime=0`,並補上手動 / 緊急 gateway 變更的 intent、approval / break-glass、route health、rollback validation 與 post-change monitoring 必填 ref;DNS / TLS / certbot Owner Confirmation Request 已新增 `requests=4 / c0=4 / fields=9 / questions=5 / guards=12 / received=0 / accepted=0`;K8s / ArgoCD manifest repo-only 清冊已新增 `files=49 / c0=36 / yaml=45 / kinds=20 / blocked=13 / runtime=0`;K8s / ArgoCD Owner Request Draft 已新增 `drafts=4 / c0=3 / fields=11 / sent=0 / runtime=0`;K8s / ArgoCD owner response acceptance 只讀帳本已新增 `candidates=4 / c0=3 / fields=11 / checks=12 / lanes=7 / blocked=18 / accepted=0 / runtime=0`;K8s / ArgoCD GitOps 變更證據驗收已新增 `candidates=4 / c0=3 / write_capable=4 / evidence_fields=18 / checks=18 / lanes=8 / blocked=28 / accepted=0 / runtime=0`;CD / Runner / Secret 注入變更證據驗收已新增 `candidates=5 / c0=4 / write_capable=5 / workflow_files=33 / secret_names=42 / runner_labels=5 / evidence_fields=19 / checks=19 / lanes=8 / blocked=32 / accepted=0 / runtime=0`;Public / Admin / API runtime config 變更證據驗收已新增 `candidates=6 / c0=5 / write_capable=6 / source_refs=20 / evidence_fields=21 / checks=21 / lanes=8 / blocked=32 / accepted=0 / runtime=0`,並把 raw namespace、repo slug、內部狀態碼與內部協作內容外洩列為拒收 / 隔離;Backup / Restore / Escrow owner response acceptance 只讀帳本已更新為 `candidates=38 / write_capable=27 / fields=33 / owner_fields=23 / reviewer_checks=22 / lanes=9 / blocked=31 / accepted=0 / runtime=0`;SSH / Firewall / Network Access owner response acceptance 只讀帳本已新增 `candidates=16 / write_capable=6 / fields=13 / checks=15 / lanes=7 / blocked=22 / accepted=0 / runtime=0`;端口 / 防火牆變更證據驗收只讀帳本已新增 `candidates=14 / write_capable=6 / policy_or_exposure=5 / evidence_fields=16 / checks=16 / lanes=8 / blocked=24 / accepted=0 / runtime=0`;owner response / live evidence / runtime gate / action buttons 仍全部為 0 | +| P0 追加 | IwoooS P0 配置控管優先序前台正式驗證完成;Nginx public gateway、DNS / TLS / certbot、K8s / ArgoCD / production manifests、Workflow / runner / secret metadata、Public / admin / API runtime config、agent-bounty runtime / treasury 六類先列為即時風險配置;高價值配置 Gate 已補上 `k8s/nginx/**`、`scripts/ops/**/*cert*`、`scripts/ops/**/*tls*`,sample 從 `matched=0 / C0=0` 收斂到 `matched=3 / C0=2`;Gate 預設工作樹 preflight 已可讀取 staged / unstaged / untracked,本地 smoke 對臨時 `k8s/nginx/*` 檔命中 C0;Owner Packet snapshot 已同步為 `packets=3 / c0=2`,Coverage snapshot 已同步最新 patterns;IwoooS / AwoooP 前台 Owner Packet 摘要已正式驗證 `packet=3 / c0=2`,feature commit `e999c16b`、deploy marker `16c6b983`、Gitea code-review `2973` / CD `2972` success;IwoooS posture projection snapshot / schema / guard 已同步 `packet=3 / c0=2`,不再保留舊 `1 / 0` 口徑;高價值配置 Owner Packet 收件預檢已新增 `checks=9 / lanes=5 / required_fields=27 / blocked_requests=16`;高價值配置 Owner Request 草稿包已新增 `drafts=3 / handoff_fields=11 / forbidden_payloads=12 / sent=0`;Public Gateway live conf 匯出請求包已新增 `requests=3 / c0=2 / redaction_rules=8 / received=0`;Public Gateway redacted export 收件預檢已新增 `candidates=3 / c0=2 / checks=10 / rejection_guards=12 / received=0 / accepted=0`;Public Gateway rendered diff / nginx gate 草稿已新增 `candidates=3 / c0=2 / stages=7 / blocked=14 / rendered_diff=0 / runtime=0`;Public Gateway owner response acceptance 只讀帳本已新增 `candidates=3 / c0=2 / fields=33 / checks=22 / lanes=8 / blocked=28 / accepted=0 / runtime=0`,並補上手動 / 緊急 gateway 變更的 intent、approval / break-glass、route health、rollback validation 與 post-change monitoring 必填 ref;DNS / TLS / certbot Owner Confirmation Request 已新增 `requests=4 / c0=4 / fields=9 / questions=5 / guards=12 / received=0 / accepted=0`;K8s / ArgoCD manifest repo-only 清冊已新增 `files=49 / c0=36 / yaml=45 / kinds=20 / blocked=13 / runtime=0`;K8s / ArgoCD Owner Request Draft 已新增 `drafts=4 / c0=3 / fields=11 / sent=0 / runtime=0`;K8s / ArgoCD owner response acceptance 只讀帳本已新增 `candidates=4 / c0=3 / fields=11 / checks=12 / lanes=7 / blocked=18 / accepted=0 / runtime=0`;K8s / ArgoCD GitOps 變更證據驗收已新增 `candidates=4 / c0=3 / write_capable=4 / evidence_fields=18 / checks=18 / lanes=8 / blocked=28 / accepted=0 / runtime=0`;CD / Runner / Secret 注入變更證據驗收已新增 `candidates=5 / c0=4 / write_capable=5 / workflow_files=33 / secret_names=42 / runner_labels=5 / evidence_fields=19 / checks=19 / lanes=8 / blocked=32 / accepted=0 / runtime=0`;Public / Admin / API runtime config 變更證據驗收已新增 `candidates=6 / c0=5 / write_capable=6 / source_refs=20 / evidence_fields=21 / checks=21 / lanes=8 / blocked=32 / accepted=0 / runtime=0`,並把 raw namespace、repo slug、內部狀態碼與內部協作內容外洩列為拒收 / 隔離;Frontend public sensitive surface guard 已新增 `files=225 / patterns=12 / allowlisted=2 / violations=0 / runtime=0`,讓 public runtime config 成熟度 `64% -> 66%`、高價值配置平均 `69% -> 70%`;Backup / Restore / Escrow owner response acceptance 只讀帳本已更新為 `candidates=38 / write_capable=27 / fields=33 / owner_fields=23 / reviewer_checks=22 / lanes=9 / blocked=31 / accepted=0 / runtime=0`;SSH / Firewall / Network Access owner response acceptance 只讀帳本已新增 `candidates=16 / write_capable=6 / fields=13 / checks=15 / lanes=7 / blocked=22 / accepted=0 / runtime=0`;端口 / 防火牆變更證據驗收只讀帳本已新增 `candidates=14 / write_capable=6 / policy_or_exposure=5 / evidence_fields=16 / checks=16 / lanes=8 / blocked=24 / accepted=0 / runtime=0`;owner response / live evidence / runtime gate / action buttons 仍全部為 0 | | P0 agent-bounty 追加 | agent-bounty-protocol Owner Request Draft 已新增 `drafts=11 / control=4 / surface=7 / write_capable=8 / treasury=4 / mcp_a2a=5 / fields=22 / forbidden_inputs=25 / blocked=28 / sent=0 / runtime=0`;這是 repo / refs、deployment、data classification、MCP / A2A、cron / daemon、admin / treasury、webhook / traffic 的人工送件前草稿,不是 owner response、repo push、refs sync、workflow 修改、secret 收集、deploy、compose restart、DB migration、claim / submit、payout / withdrawal、cron / daemon、external send、host write 或 runtime gate | | P1 追加 | Docker / systemd / Host Service Owner Request Draft 已新增 `drafts=9 / write_capable=3 / fields=12 / blocked=14 / sent=0 / runtime=0`;Docker / systemd / Host Service Owner Response Acceptance 已更新為 `candidates=9 / write_capable=3 / live_evidence_required=8 / fields=34 / owner_fields=18 / reviewer_checks=21 / lanes=8 / blocked=27 / accepted=0 / runtime=0`;SSH / Firewall / Network Access Owner Request Draft 已新增 `drafts=16 / write_capable=6 / fields=13 / blocked=16 / sent=0 / runtime=0`;Backup / Restore / Escrow Owner Request Draft 已新增 `drafts=38 / write_capable=27 / fields=14 / blocked=18 / sent=0 / runtime=0`;Backup / Restore / Escrow Owner Response Acceptance 已更新為 `candidates=38 / write_capable=27 / owner_fields=23 / reviewer_checks=22 / lanes=9 / blocked=31 / accepted=0 / runtime=0`;Monitoring / Alerting / Observability Owner Request Draft 已新增 `drafts=60 / write_capable=11 / fields=14 / blocked=24 / sent=0 / runtime=0`;Monitoring / Alerting / Observability Owner Response Acceptance 已新增 `candidates=60 / write_capable=11 / live_evidence_required=60 / fields=30 / owner_fields=14 / reviewer_checks=15 / lanes=7 / blocked=28 / accepted=0 / runtime=0`;上述全部仍是人工送件前草稿或只讀 acceptance 帳本,不是 owner response、live evidence、reload、restart、backup、restore、Telegram send、alert smoke、host write 或 runtime gate | | P2 供應鏈追加 | Package / Docker 供應鏈 repo-only baseline 已新增 `package_json=6 / pyproject=4 / requirements=2 / dockerfiles=2 / compose=6 / gaps=5 / runtime=0`;Package / Docker 供應鏈 owner policy gate 已新增 `requests=6 / c0=2 / fields=8 / checks=12 / blocked=20 / sent=0 / accepted=0 / runtime=0`;缺口為 Python lockfile 缺席、requirements 未 pin、Docker base image 未全數 digest pinning、Docker `COPY --from` 外部 image 未 digest pinning、compose image 未 digest pinning,以及 CVE / license / SBOM window 未定;目前尚未列入 36 個正式 AwoooP 消費 contract,後續若要前台消費需同步 manifest / readiness / route / rollup / dry-run / posture projection / guard count;本輪不 install、不 upgrade、不跑 CVE、不 pull / build / push image、不改 tag、不登入 registry、不部署 | @@ -26,6 +26,8 @@ 同步邊界:IwoooS headline 維持 `64%`,active runtime gate 維持 `0`;raw owner namespace、repo slug、內部狀態碼、內部協作文字、cookie、token、secret value、DSN value、raw payload 與未脫敏截圖均為拒收或隔離條件。前台只能顯示脫敏產品 / 專案名稱與控管狀態,不得顯示個人 namespace、內部協作內容或抱怨語句。本段只更新文件、snapshot、guard、覆蓋矩陣與前端 marker,不改 route、不改 CORS、不改 env、不部署、不碰主機。 +2026-06-15 追加 Frontend public sensitive surface guard:`public_frontend_sensitive_surface_guard_v1` 固定掃描 `files=225`、`patterns=12`、`allowlisted=2`、`violations=0`、`env_violation=0`、`runtime=0`,並接入 `security-mirror-progress-guard.py`。此更新讓 `public_admin_api_runtime_config` 只讀治理成熟度 `64% -> 66%`,高價值配置平均成熟度 `69% -> 70%`;仍不是 production bundle scan accepted、desktop / mobile production smoke accepted、owner response accepted、route / CORS / env / auth / webhook 變更、frontend / API deploy 或 runtime gate。 + ## 0.00aaaa 2026-06-15 CD / Runner / Secret 注入變更證據驗收 本輪把 CD pipeline、程式碼審查、部署通知、執行器證明與 repository secret name parity / injection owner 從 workflow / secret name owner response 再補一層變更證據驗收只讀帳本:`cd_runner_secret_injection_change_evidence_acceptance_v1` 固定 `candidates=5`、`c0=4`、`c1=1`、`write_capable=5`、`workflow_files=33`、`referenced_secret_names=42`、`runner_labels=5`、`required_evidence_fields=19`、`reviewer_checks=19`、`outcome_lanes=8`、`blocked_actions=32`,並讓 `secret_metadata` 只讀治理成熟度 `66% -> 68%`、`gitea_workflow_runner_source_control` 只讀治理成熟度 `70% -> 72%`,高價值配置平均只讀成熟度仍維持 `68%`。這是 metadata-only 收件驗收,不是 workflow diff accepted、runner attestation accepted、secret parity accepted、secret injection route accepted、deploy marker readback accepted、guard result accepted、post-check accepted、runtime approval package、workflow modification、runner change、repo secret change、secret rotation、Gitea action dispatch、production deploy 或 runtime gate。 diff --git a/docs/security/high-value-config-control-coverage.snapshot.json b/docs/security/high-value-config-control-coverage.snapshot.json index 2973b764a..217716e40 100644 --- a/docs/security/high-value-config-control-coverage.snapshot.json +++ b/docs/security/high-value-config-control-coverage.snapshot.json @@ -214,17 +214,18 @@ "action_buttons_allowed": false, "category_id": "public_admin_api_runtime_config", "control_tier": "C0", - "coverage_percent": 64, - "coverage_status": "change_evidence_acceptance_ready_needs_runtime_config_owner_evidence", - "current_gap": "已固定 Public / Admin / API runtime config 變更證據驗收只讀帳本;affected route、admin/auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、webhook owner、desktop/mobile smoke、sensitive string scan、rollback 與 post-check evidence 仍全部為 0。", + "coverage_percent": 66, + "coverage_status": "frontend_sensitive_surface_guard_ready_needs_runtime_config_owner_evidence", + "current_gap": "已固定 Public / Admin / API runtime config 變更證據驗收只讀帳本,並新增前台 source / messages 敏感資訊防洩漏 guard;affected route、admin/auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、webhook owner、desktop/mobile production smoke、bundle scan、rollback 與 post-check evidence 仍全部為 0。", "evidence_refs": [ "docs/HARD_RULES.md", "docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md", "docs/security/PUBLIC-RUNTIME-CONFIG-CHANGE-EVIDENCE-ACCEPTANCE.md", - "docs/security/public-runtime-config-change-evidence-acceptance.snapshot.json" + "docs/security/public-runtime-config-change-evidence-acceptance.snapshot.json", + "docs/security/public-frontend-sensitive-surface-guard.snapshot.json" ], "label": "Public / admin / API / frontend runtime config", - "next_owner_action": "補 affected route refs、admin/auth boundary、API contract readback、CORS origin diff、frontend env diff、i18n redaction review、webhook/callback owner、desktop/mobile smoke、sensitive string scan、rollback owner 與 post-check evidence。", + "next_owner_action": "補 affected route refs、admin/auth boundary、API contract readback、CORS origin diff、frontend env diff、i18n redaction review、webhook/callback owner、desktop/mobile production smoke、bundle sensitive scan、rollback owner 與 post-check evidence。", "owner_response_accepted": false, "owner_response_received": false, "owner_response_required": true, @@ -634,8 +635,8 @@ "websocket_route_change_authorized": false, "workflow_modification_authorized": false }, - "generated_at": "2026-06-15T15:35:00+08:00", - "git_commit": "51de5fe6", + "generated_at": "2026-06-15T16:40:00+08:00", + "git_commit": "b16f4c73", "lowest_coverage_categories": [ { "category_id": "docker_compose_systemd_host_config", @@ -690,7 +691,7 @@ "status": "coverage_matrix_ready", "summary": { "action_button_count": 0, - "average_coverage_percent": 69, + "average_coverage_percent": 70, "c0_category_count": 8, "c1_category_count": 4, "c2_category_count": 1, diff --git a/docs/security/iwooos-posture-projection.snapshot.json b/docs/security/iwooos-posture-projection.snapshot.json index 59bc1af49..9651674bd 100644 --- a/docs/security/iwooos-posture-projection.snapshot.json +++ b/docs/security/iwooos-posture-projection.snapshot.json @@ -8419,7 +8419,8 @@ "docs/security/K8S-ARGOCD-CHANGE-EVIDENCE-ACCEPTANCE.md", "docs/security/k8s-argocd-change-evidence-acceptance.snapshot.json", "docs/security/CD-RUNNER-SECRET-INJECTION-CHANGE-EVIDENCE-ACCEPTANCE.md", - "docs/security/cd-runner-secret-injection-change-evidence-acceptance.snapshot.json" + "docs/security/cd-runner-secret-injection-change-evidence-acceptance.snapshot.json", + "docs/security/public-frontend-sensitive-surface-guard.snapshot.json" ], "status": "draft", "summary": { @@ -8611,7 +8612,7 @@ "global_security_mesh_matrix_read_only_count": 9, "global_security_mesh_matrix_runtime_gate_count": 0, "high_value_config_control_coverage_action_button_count": 0, - "high_value_config_control_coverage_average_percent": 69, + "high_value_config_control_coverage_average_percent": 70, "high_value_config_control_coverage_c0_category_count": 8, "high_value_config_control_coverage_c1_category_count": 4, "high_value_config_control_coverage_category_count": 14, @@ -8780,33 +8781,6 @@ "port_firewall_change_evidence_acceptance_runtime_gate_count": 0, "port_firewall_change_evidence_acceptance_service_health_impact_accepted_count": 0, "port_firewall_change_evidence_acceptance_write_capable_candidate_count": 6, - "public_runtime_config_change_evidence_acceptance_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_action_button_count": 0, - "public_runtime_config_change_evidence_acceptance_admin_auth_boundary_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_api_contract_readback_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_blocked_action_count": 32, - "public_runtime_config_change_evidence_acceptance_c0_candidate_count": 5, - "public_runtime_config_change_evidence_acceptance_c1_candidate_count": 1, - "public_runtime_config_change_evidence_acceptance_candidate_count": 6, - "public_runtime_config_change_evidence_acceptance_cors_origin_diff_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_coverage_percent_after_acceptance": 64, - "public_runtime_config_change_evidence_acceptance_coverage_percent_before_acceptance": 62, - "public_runtime_config_change_evidence_acceptance_desktop_mobile_smoke_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_first_layer": true, - "public_runtime_config_change_evidence_acceptance_frontend_env_diff_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_i18n_redaction_review_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_outcome_lane_count": 8, - "public_runtime_config_change_evidence_acceptance_postcheck_evidence_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_received_count": 0, - "public_runtime_config_change_evidence_acceptance_required_evidence_field_count": 21, - "public_runtime_config_change_evidence_acceptance_reviewer_check_count": 21, - "public_runtime_config_change_evidence_acceptance_route_scope_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_runtime_approval_package_ready_count": 0, - "public_runtime_config_change_evidence_acceptance_runtime_gate_count": 0, - "public_runtime_config_change_evidence_acceptance_sensitive_string_scan_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_source_ref_count": 20, - "public_runtime_config_change_evidence_acceptance_webhook_callback_owner_accepted_count": 0, - "public_runtime_config_change_evidence_acceptance_write_capable_candidate_count": 6, "professional_security_experience_asset_heat_cell_count": 9, "professional_security_experience_attack_path_node_count": 6, "professional_security_experience_default_visible": false, @@ -8831,6 +8805,12 @@ "progress_integrity_ribbon_read_only_scope_count": 9, "progress_integrity_ribbon_runtime_gate_count": 0, "progress_integrity_ribbon_signal_count": 3, + "public_admin_api_runtime_config_coverage_percent": 66, + "public_frontend_sensitive_surface_guard_allowlisted_match_count": 2, + "public_frontend_sensitive_surface_guard_file_count": 225, + "public_frontend_sensitive_surface_guard_forbidden_pattern_count": 12, + "public_frontend_sensitive_surface_guard_runtime_gate_count": 0, + "public_frontend_sensitive_surface_guard_violation_count": 0, "public_gateway_preflight_acme_challenge_domain_count": 7, "public_gateway_preflight_action_button_count": 0, "public_gateway_preflight_admin_route_domain_count": 1, @@ -8860,6 +8840,33 @@ "public_gateway_preflight_tls_certificate_path_count": 10, "public_gateway_preflight_unique_upstream_count": 14, "public_gateway_preflight_websocket_route_domain_count": 6, + "public_runtime_config_change_evidence_acceptance_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_action_button_count": 0, + "public_runtime_config_change_evidence_acceptance_admin_auth_boundary_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_api_contract_readback_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_blocked_action_count": 32, + "public_runtime_config_change_evidence_acceptance_c0_candidate_count": 5, + "public_runtime_config_change_evidence_acceptance_c1_candidate_count": 1, + "public_runtime_config_change_evidence_acceptance_candidate_count": 6, + "public_runtime_config_change_evidence_acceptance_cors_origin_diff_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_coverage_percent_after_acceptance": 64, + "public_runtime_config_change_evidence_acceptance_coverage_percent_before_acceptance": 62, + "public_runtime_config_change_evidence_acceptance_desktop_mobile_smoke_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_first_layer": true, + "public_runtime_config_change_evidence_acceptance_frontend_env_diff_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_i18n_redaction_review_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_outcome_lane_count": 8, + "public_runtime_config_change_evidence_acceptance_postcheck_evidence_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_received_count": 0, + "public_runtime_config_change_evidence_acceptance_required_evidence_field_count": 21, + "public_runtime_config_change_evidence_acceptance_reviewer_check_count": 21, + "public_runtime_config_change_evidence_acceptance_route_scope_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_runtime_approval_package_ready_count": 0, + "public_runtime_config_change_evidence_acceptance_runtime_gate_count": 0, + "public_runtime_config_change_evidence_acceptance_sensitive_string_scan_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_source_ref_count": 20, + "public_runtime_config_change_evidence_acceptance_webhook_callback_owner_accepted_count": 0, + "public_runtime_config_change_evidence_acceptance_write_capable_candidate_count": 6, "rollout_risk_api_health_passed": true, "rollout_risk_argocd_health": "Degraded", "rollout_risk_awoooi_rollout_risk": 1, diff --git a/docs/security/public-frontend-sensitive-surface-guard.snapshot.json b/docs/security/public-frontend-sensitive-surface-guard.snapshot.json new file mode 100644 index 000000000..3103f4f86 --- /dev/null +++ b/docs/security/public-frontend-sensitive-surface-guard.snapshot.json @@ -0,0 +1,81 @@ +{ + "allowed_matches": [ + { + "path": "apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx", + "pattern_id": "work_window_transcript" + }, + { + "path": "apps/web/src/lib/api-client.ts", + "pattern_id": "work_window_transcript" + } + ], + "env_example_paths": [ + "apps/web/.env.example" + ], + "execution_boundaries": { + "action_buttons_allowed": false, + "frontend_deploy_authorized": false, + "internal_ip_public_display_allowed": false, + "internal_namespace_public_display_allowed": false, + "not_authorization": true, + "production_deploy_authorized": false, + "raw_payload_storage_allowed": false, + "runtime_execution_authorized": false, + "secret_value_collection_allowed": false, + "work_window_transcript_public_display_allowed": false + }, + "forbidden_patterns": [ + "raw_personal_owner_namespace", + "raw_external_owner_namespace", + "raw_blocked_waiting_state", + "raw_blockers_counter", + "codex_delegation_payload", + "codex_source_thread_id", + "approval_chat_phrase", + "work_window_plaintext", + "in_app_browser_transcript", + "codex_request_transcript", + "work_window_transcript", + "internal_rfc1918_ip" + ], + "generated_at": "2026-06-15T16:40:00+08:00", + "git_commit": "b16f4c73", + "guarded_paths": [ + "apps/web/src", + "apps/web/messages" + ], + "mode": "repo_source_scan_no_runtime_no_secret_collection", + "operator_interpretation": [ + "此 guard 只掃描 repo 內前端 source / messages 與 env example,不讀 production bundle、不部署、不收 secret。", + "遮罩器中的 banned phrase 測試 pattern 允許列在 allowlist;產品文案、表格、API payload 與 i18n 不允許顯示 raw namespace、工作視窗逐字內容、raw blocker 狀態或內網 IP。", + "violation_count 維持 0 才能視為 source-control 防洩漏檢查通過;仍不代表 production smoke、runtime approval 或 owner response accepted。" + ], + "public_surface_matches": [ + { + "excerpt": "[/work window transcript/gi, '已遮罩逐字稿'],", + "line": 203, + "path": "apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx", + "pattern_id": "work_window_transcript" + }, + { + "excerpt": "[/work window transcript/gi, '已遮罩逐字稿'],", + "line": 64, + "path": "apps/web/src/lib/api-client.ts", + "pattern_id": "work_window_transcript" + } + ], + "public_surface_violations": [], + "schema_version": "public_frontend_sensitive_surface_guard_v1", + "status": "pass", + "summary": { + "action_button_count": 0, + "allowlisted_match_count": 2, + "env_example_file_count": 1, + "env_violation_count": 0, + "forbidden_pattern_count": 12, + "public_surface_file_count": 225, + "raw_match_count": 2, + "runtime_gate_count": 0, + "violation_count": 0 + } +} diff --git a/scripts/security/high-value-config-control-coverage.py b/scripts/security/high-value-config-control-coverage.py index 4fe911361..47ae103f0 100644 --- a/scripts/security/high-value-config-control-coverage.py +++ b/scripts/security/high-value-config-control-coverage.py @@ -101,16 +101,17 @@ CONTROL_STATUS_BY_CATEGORY = { "next_owner_action": "補 workflow diff ref、runner owner attestation、secret name parity ref、Gitea run readback、guard result、maintenance window、rollback owner 與 post-check evidence。", }, "public_admin_api_runtime_config": { - "coverage_status": "change_evidence_acceptance_ready_needs_runtime_config_owner_evidence", - "coverage_percent": 64, + "coverage_status": "frontend_sensitive_surface_guard_ready_needs_runtime_config_owner_evidence", + "coverage_percent": 66, "evidence_refs": [ "docs/HARD_RULES.md", "docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md", "docs/security/PUBLIC-RUNTIME-CONFIG-CHANGE-EVIDENCE-ACCEPTANCE.md", "docs/security/public-runtime-config-change-evidence-acceptance.snapshot.json", + "docs/security/public-frontend-sensitive-surface-guard.snapshot.json", ], - "current_gap": "已固定 Public / Admin / API runtime config 變更證據驗收只讀帳本;affected route、admin/auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、webhook owner、desktop/mobile smoke、sensitive string scan、rollback 與 post-check evidence 仍全部為 0。", - "next_owner_action": "補 affected route refs、admin/auth boundary、API contract readback、CORS origin diff、frontend env diff、i18n redaction review、webhook/callback owner、desktop/mobile smoke、sensitive string scan、rollback owner 與 post-check evidence。", + "current_gap": "已固定 Public / Admin / API runtime config 變更證據驗收只讀帳本,並新增前台 source / messages 敏感資訊防洩漏 guard;affected route、admin/auth boundary、API readback、CORS diff、frontend env diff、i18n redaction、webhook owner、desktop/mobile production smoke、bundle scan、rollback 與 post-check evidence 仍全部為 0。", + "next_owner_action": "補 affected route refs、admin/auth boundary、API contract readback、CORS origin diff、frontend env diff、i18n redaction review、webhook/callback owner、desktop/mobile production smoke、bundle sensitive scan、rollback owner 與 post-check evidence。", }, "backup_restore_credential": { "coverage_status": "restore_recovery_backfill_ready_needs_owner_live_evidence", @@ -376,6 +377,7 @@ def build_report(root: Path, generated_at: str | None) -> dict[str, Any]: "secret_injection_change_evidence_acceptance_ready_needs_owner_evidence", "cd_runner_secret_injection_change_evidence_acceptance_ready_needs_owner_evidence", "change_evidence_acceptance_ready_needs_runtime_config_owner_evidence", + "frontend_sensitive_surface_guard_ready_needs_runtime_config_owner_evidence", "owner_response_acceptance_ledger_ready_needs_restore_drill_owner", "restore_recovery_backfill_ready_needs_owner_live_evidence", "owner_response_acceptance_ledger_ready_needs_network_owner", diff --git a/scripts/security/iwooos-config-control-guard.py b/scripts/security/iwooos-config-control-guard.py index 147e42797..47e82cf43 100644 --- a/scripts/security/iwooos-config-control-guard.py +++ b/scripts/security/iwooos-config-control-guard.py @@ -22,7 +22,7 @@ EXPECTED_CATEGORIES = { "k8s_production_gitops": 64, "secret_metadata": 68, "gitea_workflow_runner_source_control": 72, - "public_admin_api_runtime_config": 64, + "public_admin_api_runtime_config": 66, "backup_restore_credential": 64, "agent_bounty_protocol_runtime": 68, "monitoring_alerting_observability": 66, diff --git a/scripts/security/public-frontend-env-guard.py b/scripts/security/public-frontend-env-guard.py index aee95e073..78364dbdc 100644 --- a/scripts/security/public-frontend-env-guard.py +++ b/scripts/security/public-frontend-env-guard.py @@ -1,16 +1,21 @@ #!/usr/bin/env python3 -"""檢查公開前端 env 範例不可洩漏內網拓樸。""" +"""檢查公開前端不可洩漏內網拓樸、原始 namespace 或工作視窗內容。""" from __future__ import annotations import argparse +import json import re +import subprocess +from datetime import datetime, timedelta, timezone from pathlib import Path +from typing import Any PRIVATE_IP_PATTERN = re.compile( r"\b(?:10(?:\.\d{1,3}){3}|192\.168(?:\.\d{1,3}){2}|172\.(?:1[6-9]|2\d|3[01])(?:\.\d{1,3}){2})\b" ) +TAIPEI = timezone(timedelta(hours=8)) RETIRED_PUBLIC_TOPOLOGY_KEYS = { "NEXT_PUBLIC_HOST_IPS", @@ -21,6 +26,38 @@ ENV_EXAMPLE_PATHS = ( Path("apps/web/.env.example"), ) +PUBLIC_SURFACE_ROOTS = ( + Path("apps/web/src"), + Path("apps/web/messages"), +) + +PUBLIC_SURFACE_SUFFIXES = { + ".json", + ".mdx", + ".ts", + ".tsx", +} + +PUBLIC_SURFACE_FORBIDDEN_PATTERNS: tuple[tuple[str, re.Pattern[str]], ...] = ( + ("raw_personal_owner_namespace", re.compile(r"\bowenhytsai\b", re.IGNORECASE)), + ("raw_external_owner_namespace", re.compile(r"\bnexu-io\b", re.IGNORECASE)), + ("raw_blocked_waiting_state", re.compile(r"\bblocked_waiting_[A-Za-z0-9_]+\b")), + ("raw_blockers_counter", re.compile(r"\bblockers=\d+\b")), + ("codex_delegation_payload", re.compile(r"\bcodex_delegation\b", re.IGNORECASE)), + ("codex_source_thread_id", re.compile(r"\bsource_thread_id\b", re.IGNORECASE)), + ("approval_chat_phrase", re.compile(r"批准!")), + ("work_window_plaintext", re.compile(r"工作視窗")), + ("in_app_browser_transcript", re.compile(r"\bIn app browser\b", re.IGNORECASE)), + ("codex_request_transcript", re.compile(r"\bMy request for Codex\b", re.IGNORECASE)), + ("work_window_transcript", re.compile(r"\bwork window transcript\b", re.IGNORECASE)), + ("internal_rfc1918_ip", PRIVATE_IP_PATTERN), +) + +ALLOWED_PUBLIC_SURFACE_MATCHES: set[tuple[str, str]] = { + ("apps/web/src/lib/api-client.ts", "work_window_transcript"), + ("apps/web/src/app/[locale]/governance/tabs/automation-inventory-tab.tsx", "work_window_transcript"), +} + def _active_assignment(line: str) -> tuple[str, str] | None: stripped = line.strip() @@ -30,8 +67,47 @@ def _active_assignment(line: str) -> tuple[str, str] | None: return key.strip(), value.strip() -def validate(root: Path) -> None: +def _git_short_sha(root: Path) -> str: + try: + result = subprocess.run( + ["git", "rev-parse", "--short", "HEAD"], + cwd=root, + check=True, + capture_output=True, + text=True, + ) + return result.stdout.strip() + except Exception: + return "unknown" + + +def _iter_public_surface_files(root: Path) -> list[Path]: + files: list[Path] = [] + for surface_root in PUBLIC_SURFACE_ROOTS: + absolute_root = root / surface_root + if not absolute_root.exists(): + continue + for path in absolute_root.rglob("*"): + if path.is_file() and path.suffix in PUBLIC_SURFACE_SUFFIXES: + files.append(path) + return sorted(files) + + +def _line_excerpt(line: str, start: int, end: int) -> str: + prefix_start = max(start - 36, 0) + suffix_end = min(end + 36, len(line)) + excerpt = line[prefix_start:suffix_end].strip() + return excerpt if len(excerpt) <= 120 else excerpt[:117] + "..." + + +def build_report(root: Path, generated_at: str | None = None) -> dict[str, Any]: + generated = generated_at or datetime.now(TAIPEI).isoformat(timespec="seconds") errors: list[str] = [] + env_violation_count = 0 + public_surface_files = _iter_public_surface_files(root) + public_surface_matches: list[dict[str, Any]] = [] + public_surface_violations: list[dict[str, Any]] = [] + allowlisted_match_count = 0 for relative_path in ENV_EXAMPLE_PATHS: path = root / relative_path @@ -46,21 +122,116 @@ def validate(root: Path) -> None: key, value = assignment if key in RETIRED_PUBLIC_TOPOLOGY_KEYS: errors.append(f"{relative_path}:{line_number}: 已停用公開前端拓樸 env key:{key}") + env_violation_count += 1 if PRIVATE_IP_PATTERN.search(value): errors.append(f"{relative_path}:{line_number}: env 範例不得包含內網 IP:{key}") + env_violation_count += 1 if key.startswith("NEXT_PUBLIC_") and not value: errors.append(f"{relative_path}:{line_number}: NEXT_PUBLIC_* 範例需明確使用公網入口或安全預設值:{key}") + env_violation_count += 1 + + for path in public_surface_files: + relative_path = path.relative_to(root).as_posix() + text = path.read_text(encoding="utf-8", errors="replace") + for line_number, line in enumerate(text.splitlines(), start=1): + for pattern_id, pattern in PUBLIC_SURFACE_FORBIDDEN_PATTERNS: + for match in pattern.finditer(line): + item = { + "path": relative_path, + "line": line_number, + "pattern_id": pattern_id, + "excerpt": _line_excerpt(line, match.start(), match.end()), + } + public_surface_matches.append(item) + if (relative_path, pattern_id) in ALLOWED_PUBLIC_SURFACE_MATCHES: + allowlisted_match_count += 1 + continue + public_surface_violations.append(item) + errors.append( + f"{relative_path}:{line_number}: 前台敏感資訊命中 {pattern_id},需改成脫敏名稱或遮罩器例外" + ) + + return { + "schema_version": "public_frontend_sensitive_surface_guard_v1", + "generated_at": generated, + "git_commit": _git_short_sha(root), + "status": "pass" if not errors else "blocked", + "mode": "repo_source_scan_no_runtime_no_secret_collection", + "guarded_paths": [path.as_posix() for path in PUBLIC_SURFACE_ROOTS], + "env_example_paths": [path.as_posix() for path in ENV_EXAMPLE_PATHS], + "forbidden_patterns": [pattern_id for pattern_id, _ in PUBLIC_SURFACE_FORBIDDEN_PATTERNS], + "allowed_matches": [ + {"path": path, "pattern_id": pattern_id} + for path, pattern_id in sorted(ALLOWED_PUBLIC_SURFACE_MATCHES) + ], + "summary": { + "env_example_file_count": sum(1 for path in ENV_EXAMPLE_PATHS if (root / path).exists()), + "public_surface_file_count": len(public_surface_files), + "forbidden_pattern_count": len(PUBLIC_SURFACE_FORBIDDEN_PATTERNS), + "raw_match_count": len(public_surface_matches), + "allowlisted_match_count": allowlisted_match_count, + "violation_count": len(public_surface_violations), + "env_violation_count": env_violation_count, + "runtime_gate_count": 0, + "action_button_count": 0, + }, + "execution_boundaries": { + "runtime_execution_authorized": False, + "frontend_deploy_authorized": False, + "production_deploy_authorized": False, + "secret_value_collection_allowed": False, + "raw_payload_storage_allowed": False, + "internal_namespace_public_display_allowed": False, + "work_window_transcript_public_display_allowed": False, + "internal_ip_public_display_allowed": False, + "action_buttons_allowed": False, + "not_authorization": True, + }, + "public_surface_matches": public_surface_matches, + "public_surface_violations": public_surface_violations, + "operator_interpretation": [ + "此 guard 只掃描 repo 內前端 source / messages 與 env example,不讀 production bundle、不部署、不收 secret。", + "遮罩器中的 banned phrase 測試 pattern 允許列在 allowlist;產品文案、表格、API payload 與 i18n 不允許顯示 raw namespace、工作視窗逐字內容、raw blocker 狀態或內網 IP。", + "violation_count 維持 0 才能視為 source-control 防洩漏檢查通過;仍不代表 production smoke、runtime approval 或 owner response accepted。", + ], + } + + +def validate(root: Path) -> None: + report = build_report(root) + errors = [ + f"{item['path']}:{item['line']}: 前台敏感資訊命中 {item['pattern_id']},需改成脫敏名稱或遮罩器例外" + for item in report["public_surface_violations"] + ] + if report["summary"]["env_violation_count"]: + errors.append(f"env_violation_count={report['summary']['env_violation_count']}") if errors: - raise SystemExit("BLOCKED public frontend env guard:\n" + "\n".join(f"- {error}" for error in errors)) + raise SystemExit("BLOCKED public frontend sensitive surface guard:\n" + "\n".join(f"- {error}" for error in errors)) def main() -> None: - parser = argparse.ArgumentParser(description="檢查公開前端 env 範例不可洩漏內網拓樸") + parser = argparse.ArgumentParser(description="檢查公開前端不可洩漏內網拓樸、原始 namespace 或工作視窗內容") parser.add_argument("--root", default=".", help="repository root") + parser.add_argument("--output", help="寫出 JSON 報告") + parser.add_argument("--generated-at", help="固定報告時間,供 committed snapshot 使用") args = parser.parse_args() - validate(Path(args.root).resolve()) - print("OK public frontend env guard") + root = Path(args.root).resolve() + report = build_report(root, args.generated_at) + if args.output: + output = Path(args.output) + output.parent.mkdir(parents=True, exist_ok=True) + output.write_text(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n", encoding="utf-8") + validate(root) + summary = report["summary"] + print( + "OK public frontend sensitive surface guard " + f"files={summary['public_surface_file_count']} " + f"patterns={summary['forbidden_pattern_count']} " + f"allowlisted={summary['allowlisted_match_count']} " + f"violations={summary['violation_count']} " + f"runtime_gate={summary['runtime_gate_count']}" + ) if __name__ == "__main__": diff --git a/scripts/security/security-mirror-progress-guard.py b/scripts/security/security-mirror-progress-guard.py index 40c6e1347..62c7ed904 100755 --- a/scripts/security/security-mirror-progress-guard.py +++ b/scripts/security/security-mirror-progress-guard.py @@ -87,6 +87,39 @@ def validate(root: Path) -> None: str(root / "scripts" / "security" / "public-frontend-env-guard.py") ) public_frontend_env_guard["validate"](root) + public_frontend_sensitive_surface = load_json( + security_dir / "public-frontend-sensitive-surface-guard.snapshot.json" + ) + assert_equal( + "public_frontend_sensitive_surface.schema_version", + public_frontend_sensitive_surface["schema_version"], + "public_frontend_sensitive_surface_guard_v1", + ) + assert_equal( + "public_frontend_sensitive_surface.summary.public_surface_file_count", + public_frontend_sensitive_surface["summary"]["public_surface_file_count"], + 225, + ) + assert_equal( + "public_frontend_sensitive_surface.summary.forbidden_pattern_count", + public_frontend_sensitive_surface["summary"]["forbidden_pattern_count"], + 12, + ) + assert_equal( + "public_frontend_sensitive_surface.summary.allowlisted_match_count", + public_frontend_sensitive_surface["summary"]["allowlisted_match_count"], + 2, + ) + assert_equal( + "public_frontend_sensitive_surface.summary.violation_count", + public_frontend_sensitive_surface["summary"]["violation_count"], + 0, + ) + assert_equal( + "public_frontend_sensitive_surface.summary.runtime_gate_count", + public_frontend_sensitive_surface["summary"]["runtime_gate_count"], + 0, + ) manifest = load_json(security_dir / "security-supply-chain-contract-manifest.snapshot.json") readiness = load_json(security_dir / "security-mirror-readiness.snapshot.json") @@ -2714,7 +2747,7 @@ def validate(root: Path) -> None: assert_equal( "high_value_config_coverage.summary.average_coverage_percent", high_value_config_coverage["summary"]["average_coverage_percent"], - 69, + 70, ) assert_equal( "high_value_config_coverage.summary.needs_live_evidence_count", @@ -3104,18 +3137,19 @@ def validate(root: Path) -> None: assert_equal( "high_value_config_coverage.coverage_categories.public_runtime_config.coverage_percent", public_runtime_config_category["coverage_percent"], - 64, + 66, ) assert_equal( "high_value_config_coverage.coverage_categories.public_runtime_config.coverage_status", public_runtime_config_category["coverage_status"], - "change_evidence_acceptance_ready_needs_runtime_config_owner_evidence", + "frontend_sensitive_surface_guard_ready_needs_runtime_config_owner_evidence", ) for evidence_ref in [ "docs/HARD_RULES.md", "docs/security/IWOOOS-CONFIG-CONTROL-INVENTORY.md", "docs/security/PUBLIC-RUNTIME-CONFIG-CHANGE-EVIDENCE-ACCEPTANCE.md", "docs/security/public-runtime-config-change-evidence-acceptance.snapshot.json", + "docs/security/public-frontend-sensitive-surface-guard.snapshot.json", ]: assert_contains( "high_value_config_coverage.coverage_categories.public_runtime_config.evidence_refs", @@ -6346,6 +6380,7 @@ def validate(root: Path) -> None: "docs/schemas/monitoring_alerting_observability_inventory_v1.schema.json", "docs/security/public-runtime-config-change-evidence-acceptance.snapshot.json", "docs/security/PUBLIC-RUNTIME-CONFIG-CHANGE-EVIDENCE-ACCEPTANCE.md", + "docs/security/public-frontend-sensitive-surface-guard.snapshot.json", ]: assert_contains( "iwooos_projection.source_paths.config_inventory", @@ -6370,7 +6405,7 @@ def validate(root: Path) -> None: "high_value_config_control_coverage_category_count": 14, "high_value_config_control_coverage_c0_category_count": 8, "high_value_config_control_coverage_c1_category_count": 4, - "high_value_config_control_coverage_average_percent": 69, + "high_value_config_control_coverage_average_percent": 70, "high_value_config_control_coverage_needs_live_evidence_count": 10, "high_value_config_control_coverage_owner_response_required_count": 14, "high_value_config_control_coverage_owner_response_received_count": 0, @@ -6378,6 +6413,12 @@ def validate(root: Path) -> None: "high_value_config_control_coverage_runtime_gate_count": 0, "high_value_config_control_coverage_action_button_count": 0, "high_value_config_control_coverage_lowest_category_count": 4, + "public_admin_api_runtime_config_coverage_percent": 66, + "public_frontend_sensitive_surface_guard_file_count": 225, + "public_frontend_sensitive_surface_guard_forbidden_pattern_count": 12, + "public_frontend_sensitive_surface_guard_allowlisted_match_count": 2, + "public_frontend_sensitive_surface_guard_violation_count": 0, + "public_frontend_sensitive_surface_guard_runtime_gate_count": 0, } for key, expected in expected_high_value_config_coverage_summary.items(): assert_equal( @@ -16286,7 +16327,7 @@ def validate(root: Path) -> None: "high_value_config_control_coverage_category_count=14", "high_value_config_control_coverage_c0_category_count=8", "high_value_config_control_coverage_c1_category_count=4", - "high_value_config_control_coverage_average_percent=69", + "high_value_config_control_coverage_average_percent=70", "high_value_config_control_coverage_needs_live_evidence_count=10", "high_value_config_control_coverage_owner_response_required_count=14", "high_value_config_control_coverage_owner_response_received_count=0", @@ -16301,7 +16342,11 @@ def validate(root: Path) -> None: "k8s_production_gitops_coverage_percent=64", "secret_metadata_coverage_percent=68", "gitea_workflow_runner_source_control_coverage_percent=72", - "public_admin_api_runtime_config_coverage_percent=64", + "public_admin_api_runtime_config_coverage_percent=66", + "public_frontend_sensitive_surface_guard_file_count=225", + "public_frontend_sensitive_surface_guard_forbidden_pattern_count=12", + "public_frontend_sensitive_surface_guard_violation_count=0", + "public_frontend_sensitive_surface_guard_runtime_gate_count=0", "public_runtime_config_change_evidence_acceptance_candidate_count=6", "public_runtime_config_change_evidence_acceptance_c0_candidate_count=5", "public_runtime_config_change_evidence_acceptance_c1_candidate_count=1", @@ -16578,7 +16623,10 @@ def validate(root: Path) -> None: "nginx_public_gateway_nginx_test_evidence_count=0", "secret_metadata_coverage_percent=68", "gitea_workflow_runner_source_control_coverage_percent=72", - "public_admin_api_runtime_config_coverage_percent=64", + "public_admin_api_runtime_config_coverage_percent=66", + "public_frontend_sensitive_surface_guard_file_count=225", + "public_frontend_sensitive_surface_guard_forbidden_pattern_count=12", + "public_frontend_sensitive_surface_guard_violation_count=0", "public_runtime_config_change_evidence_acceptance_candidate_count=6", "public_runtime_config_change_evidence_acceptance_c0_candidate_count=5", "public_runtime_config_change_evidence_acceptance_write_capable_candidate_count=6",