feat(security): automate governance review and access controls

This commit is contained in:
ogt
2026-07-10 18:49:32 +08:00
parent cd12e48505
commit 6b8bd8bb05
26 changed files with 1977 additions and 99 deletions

View File

@@ -3,10 +3,13 @@
從 app.py + utils/validators.py 整併的單一權威來源。純驗證邏輯,無 Flask 依賴。
舊的 utils/validators.py 已 deprecate僅保留 re-export 不破壞既有 import。
"""
import ipaddress
import os
import re
import socket
import unicodedata
from pathlib import Path
from urllib.parse import urlparse
import pandas as pd
@@ -15,6 +18,41 @@ from utils.logger_manager import SystemLogger
_log = SystemLogger("Security").get_logger()
def validate_public_http_url(value):
"""Validate an outbound URL and reject SSRF targets before any request."""
candidate = str(value or '').strip()
parsed = urlparse(candidate)
if parsed.scheme not in {'http', 'https'} or not parsed.hostname:
raise ValueError('只允許完整的 HTTP/HTTPS 網址')
if parsed.username or parsed.password:
raise ValueError('網址不可包含帳號或密碼')
if parsed.port not in {None, 80, 443}:
raise ValueError('只允許標準 HTTP/HTTPS 連接埠')
try:
addresses = {
info[4][0]
for info in socket.getaddrinfo(
parsed.hostname,
parsed.port or (443 if parsed.scheme == 'https' else 80),
type=socket.SOCK_STREAM,
)
}
except OSError as exc:
raise ValueError('網址主機無法解析') from exc
if not addresses:
raise ValueError('網址主機沒有可用位址')
for address in addresses:
try:
ip = ipaddress.ip_address(address.split('%', 1)[0])
except ValueError as exc:
raise ValueError('網址主機位址無效') from exc
if not ip.is_global:
raise ValueError('禁止連線至內網、loopback、link-local 或保留位址')
return candidate
# ────────────────────────────────────────────────────────────────────────
# SQL Injection 防護
# ────────────────────────────────────────────────────────────────────────