chore(hooks): momo-db 守門 9 PoC 強化(vuln-verifier 補丁)
All checks were successful
CD Pipeline / deploy (push) Successful in 1m8s
All checks were successful
CD Pipeline / deploy (push) Successful in 1m8s
回應 vuln-verifier 對前版規則 3e 的 8/9 PoC 繞過警告。 新增/強化擋點: - psql -f / heredoc / 重定向:hook 看不到 SQL 內容 → 一律擋 - multi-statement: ; 後接內容(去 -- 與 /* */ 註解後判斷)→ 擋 - writable CTE: WITH ... DELETE/INSERT/UPDATE → 擋 - /run/secrets, /proc/*/environ → 擋 - pg_read_file / pg_read_binary_file / lo_export / lo_import → 擋 - COPY ... FROM PROGRAM → 擋 - VACUUM FULL / REINDEX / REFRESH MATERIALIZED / CLUSTER 加入寫入黑名單 - env 加 (?!\\s+\\w+=) lookahead,避免誤殺 env VAR=value - alias/function 包裝 docker exec:警告(無法靜態判斷後續呼叫) - 白名單 prefix 不收 WITH(防 writable CTE 漏網),改收 SELECT/EXPLAIN/SHOW/VALUES/TABLE settings.json: 累積本輪 session 的 read-only 工具放行(py_compile、python3)。
This commit is contained in:
@@ -78,6 +78,77 @@ process.stdin.on('end', () => {
|
||||
warn('docker prune 類指令,已記錄稽核日誌');
|
||||
}
|
||||
|
||||
// 3e. momo-db / momo-postgres 細粒度政策(SQL / env / dump / cp)
|
||||
// 規則:read-only SELECT / EXPLAIN / SHOW / \d* 放行
|
||||
// 寫入 SQL(INSERT/UPDATE/DELETE/DROP/TRUNCATE/ALTER/CREATE/GRANT/REVOKE)一律阻擋
|
||||
// env / printenv 一律阻擋(避免洩漏 DATABASE_URL 等敏感)
|
||||
// pg_dump / pg_dumpall 一律阻擋(資料外洩防線)
|
||||
// docker cp momo-db:* / momo-postgres:* 一律阻擋(繞過 SQL 直接搬檔)
|
||||
const isDbExec = /docker\s+exec\s+[^|;&]*\b(momo-db|momo-postgres)\b/.test(cmd);
|
||||
const isDbCp = /docker\s+cp\s+[^|;&]*\b(momo-db|momo-postgres):/i.test(cmd);
|
||||
|
||||
if (isDbCp) {
|
||||
block('docker cp momo-db/momo-postgres 已阻擋(資料外洩防線,請走 SQL 查詢)');
|
||||
}
|
||||
|
||||
if (/\bpg_dump(all)?\b/i.test(cmd)) {
|
||||
block('pg_dump / pg_dumpall 已阻擋(資料外洩防線;備份請走每日 daily_backup 排程)');
|
||||
}
|
||||
|
||||
// psql -f / 重定向 / heredoc:hook 看不到 SQL 內容 → 一律擋
|
||||
if (isDbExec && /\bpsql\b[^|;&]*(\s-f\s+\S+|\s+<\s+\S+\.sql|<<-?\s*['"]?\w+)/i.test(cmd)) {
|
||||
block('momo-db psql 透過 -f / heredoc / 重定向載入 SQL,hook 無法靜態檢驗,已阻擋');
|
||||
}
|
||||
|
||||
// alias / function 包裝 docker exec:警告
|
||||
if (isDbExec && /(alias|function)\s+\w+\s*=?[^|;&]*docker\s+exec[^|;&]*momo-db/i.test(cmd)) {
|
||||
warn('偵測到 alias/function 包裝 docker exec momo-db,後續呼叫可能繞過 SQL 檢查');
|
||||
}
|
||||
|
||||
if (isDbExec) {
|
||||
// env / printenv:一律擋(排除 env VAR=value 的賦值用法)
|
||||
if (/\b(env|printenv)\b(?!\s+\w+=)/.test(cmd) && !/\bgrep\b.*\b(POSTGRES_DB|POSTGRES_USER)\b/.test(cmd)) {
|
||||
block('docker exec momo-db env/printenv 已阻擋(避免洩漏 DATABASE_URL/密碼)');
|
||||
}
|
||||
|
||||
// /run/secrets, /proc/*/environ:擋
|
||||
if (/\/(run\/secrets|proc\/[\d\w*]+\/environ)/.test(cmd)) {
|
||||
block('docker exec momo-db 讀取 /run/secrets 或 /proc/*/environ 已阻擋');
|
||||
}
|
||||
|
||||
// PG 內建檔案讀寫 / COPY FROM PROGRAM
|
||||
if (/\b(pg_read_file|pg_read_binary_file|lo_export|lo_import)\b/i.test(cmd) ||
|
||||
/\bCOPY\b[\s\S]*?\bFROM\s+PROGRAM\b/i.test(cmd)) {
|
||||
block('momo-db PG 檔案系統函式 / COPY FROM PROGRAM 已阻擋');
|
||||
}
|
||||
|
||||
// 寫入類 SQL(含 VACUUM FULL / REINDEX / REFRESH MATERIALIZED)
|
||||
const writeSqlRe = /\b(INSERT\s+INTO|UPDATE\s+\w+\s+SET|DELETE\s+FROM|DROP\s+(TABLE|DATABASE|SCHEMA|INDEX|VIEW)|TRUNCATE|ALTER\s+(TABLE|DATABASE|SCHEMA|ROLE|USER)|CREATE\s+(TABLE|DATABASE|SCHEMA|ROLE|USER|INDEX)|GRANT\b|REVOKE\b|VACUUM\s+FULL|REINDEX|REFRESH\s+MATERIALIZED|CLUSTER)\b/i;
|
||||
if (writeSqlRe.test(cmd)) {
|
||||
block('momo-db 寫入類 SQL 已阻擋(INSERT/UPDATE/DELETE/DROP/TRUNCATE/ALTER/CREATE/GRANT/REVOKE/VACUUM FULL)');
|
||||
}
|
||||
|
||||
// psql -c:白/黑名單雙閘 + multi-statement + writable CTE
|
||||
const psqlCmdMatch = cmd.match(/psql[^|]*\s(?:-c|--command(?:=|\s+))\s*(['"])([\s\S]+?)\1/);
|
||||
if (psqlCmdMatch) {
|
||||
const sql = psqlCmdMatch[2].trim();
|
||||
// writable CTE:WITH ... DELETE/INSERT/UPDATE
|
||||
if (/^\s*WITH\b/i.test(sql) && /\b(DELETE|INSERT|UPDATE)\b/i.test(sql)) {
|
||||
block('momo-db psql writable CTE(WITH ... DELETE/INSERT/UPDATE)已阻擋');
|
||||
}
|
||||
// multi-statement:; 後還有非空白非註解內容(去掉 -- 與 /* */ 後判斷)
|
||||
const stripped = sql.replace(/--[^\n]*/g, '').replace(/\/\*[\s\S]*?\*\//g, '');
|
||||
if (/;\s*\S/.test(stripped)) {
|
||||
block('momo-db psql 多語句(; 後接內容)已阻擋,請拆成單句');
|
||||
}
|
||||
// 白名單 prefix(不收 WITH,避免 writable CTE 漏網)
|
||||
const isReadOnly = /^\s*(SELECT|EXPLAIN|SHOW|VALUES|TABLE\s+\w|\\d|\\l|\\dt|\\du|\\df|\\?)\b/i.test(sql);
|
||||
if (!isReadOnly) {
|
||||
block(`momo-db psql -c 非 read-only SQL 已阻擋: ${sql.substring(0, 80)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3d. 稽核所有 SSH 生產指令
|
||||
fs.appendFileSync(logPath, `[${ts}] SSH-PROD | ${cmd.substring(0, 300)}\n`);
|
||||
}
|
||||
|
||||
@@ -29,12 +29,18 @@
|
||||
"Bash(python -c \"from services.ai_orchestrator import AIOrchestrator; print\\('import OK'\\)\")",
|
||||
"Bash(python3 -c \"import sqlalchemy; print\\(sqlalchemy.__version__\\)\")",
|
||||
"Bash(./bin/python3 -c \"import sqlalchemy; print\\('sqlalchemy', sqlalchemy.__version__\\)\")",
|
||||
"Bash(python3 -c \"import ast; [ast.parse\\(open\\(f\\).read\\(\\)\\) for f in ['services/ai_orchestrator.py','services/hermes_analyst_service.py','services/nemoton_dispatcher_service.py','services/openclaw_strategist_service.py','telegram_ai_integration.py']]; print\\('syntax OK'\\)\")"
|
||||
"Bash(python3 -c \"import ast; [ast.parse\\(open\\(f\\).read\\(\\)\\) for f in ['services/ai_orchestrator.py','services/hermes_analyst_service.py','services/nemoton_dispatcher_service.py','services/openclaw_strategist_service.py','telegram_ai_integration.py']]; print\\('syntax OK'\\)\")",
|
||||
"Read(//Users/ooo/**)",
|
||||
"Bash(mkdir -p ~/Code)",
|
||||
"Bash(python3)",
|
||||
"Bash(python3 -c \"import py_compile; py_compile.compile\\('routes/daily_sales_routes.py', doraise=True\\); print\\('SYNTAX OK'\\)\")",
|
||||
"Bash(python3 -c \"import py_compile; py_compile.compile\\('services/daily_sales_service.py', doraise=True\\); py_compile.compile\\('utils/df_helpers.py', doraise=True\\); print\\('ALL SYNTAX OK'\\)\")"
|
||||
],
|
||||
"defaultMode": "bypassPermissions",
|
||||
"additionalDirectories": [
|
||||
"/tmp",
|
||||
"/Users/ooo/Library/Mobile Documents/com~apple~CloudDocs/momo-pro-system/.claude/hooks"
|
||||
"/Users/ooo/Library/Mobile Documents/com~apple~CloudDocs/momo-pro-system/.claude/hooks",
|
||||
"/Users/ooo/Code/momo-pro-system"
|
||||
]
|
||||
},
|
||||
"hooks": {
|
||||
|
||||
Reference in New Issue
Block a user