security: harden exception exposure, SSL config, and Pulse response parsing
Lint / Python (flake8) (push) Failing after 42s
Lint / JS (eslint) (push) Successful in 7s
Security / Python Security (bandit) (push) Successful in 1m22s
Test / Python Tests (pytest) (push) Failing after 1m23s
Lint / Notify on failure (push) Successful in 3s
Lint / Deploy (push) Has been skipped
Lint / Python (flake8) (push) Failing after 42s
Lint / JS (eslint) (push) Successful in 7s
Security / Python Security (bandit) (push) Successful in 1m22s
Test / Python Tests (pytest) (push) Failing after 1m23s
Lint / Notify on failure (push) Successful in 3s
Lint / Deploy (push) Has been skipped
- app.py: replace raw str(e) in diagnostic _run() with generic client message; log internally only - app.py: /health endpoint no longer leaks exception strings to unauthenticated callers; errors logged server-side - monitor.py: UniFi SSL verification now defaults True, configurable via config.json unifi.verify_ssl; urllib3 warning suppression scoped to verify=False only (removed global disable) - monitor.py: Pulse execution_id extracted with .get() + explicit None check to avoid KeyError on malformed response - monitor.py: interface name regex drops '@' (not a valid kernel interface char) to match app.py and fix inconsistency Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -451,7 +451,7 @@ def api_diagnose_start():
|
||||
result = runner.run(host_ip, server_name, matched_iface, port_data)
|
||||
except Exception as e:
|
||||
logger.error(f'Diagnostic job {job_id} failed: {e}', exc_info=True)
|
||||
result = {'status': 'error', 'error': str(e)}
|
||||
result = {'status': 'error', 'error': 'Diagnostic failed; check server logs.'}
|
||||
with _diag_lock:
|
||||
if job_id in _diag_jobs:
|
||||
_diag_jobs[job_id]['status'] = 'done'
|
||||
@@ -563,7 +563,8 @@ def health():
|
||||
db.get_state('last_check')
|
||||
checks['db'] = 'ok'
|
||||
except Exception as e:
|
||||
checks['db'] = f'error: {e}'
|
||||
logger.error(f'Health check db error: {e}')
|
||||
checks['db'] = 'error'
|
||||
overall = 'degraded'
|
||||
|
||||
# Monitor freshness: fail if last_check is older than 20 minutes
|
||||
@@ -580,7 +581,8 @@ def health():
|
||||
else:
|
||||
checks['monitor'] = 'no data yet'
|
||||
except Exception as e:
|
||||
checks['monitor'] = f'error: {e}'
|
||||
logger.error(f'Health check monitor error: {e}')
|
||||
checks['monitor'] = 'error'
|
||||
overall = 'degraded'
|
||||
|
||||
status_code = 200 if overall == 'ok' else 503
|
||||
|
||||
+8
-4
@@ -20,7 +20,6 @@ from urllib3.exceptions import InsecureRequestWarning
|
||||
|
||||
import db
|
||||
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
@@ -90,7 +89,9 @@ class UnifiClient:
|
||||
self.base_url = cfg['controller']
|
||||
self.site_id = cfg.get('site_id', 'default')
|
||||
self.session = requests.Session()
|
||||
self.session.verify = False
|
||||
self.session.verify = cfg.get('verify_ssl', True)
|
||||
if not self.session.verify:
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
self.headers = {
|
||||
'X-API-KEY': cfg['api_key'],
|
||||
'Accept': 'application/json',
|
||||
@@ -262,7 +263,10 @@ class PulseClient:
|
||||
timeout=10,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
execution_id = resp.json()['execution_id']
|
||||
execution_id = resp.json().get('execution_id')
|
||||
if not execution_id:
|
||||
logger.error('Pulse submit response missing execution_id')
|
||||
return None
|
||||
self.last_execution_id = execution_id
|
||||
except Exception as e:
|
||||
logger.error(f'Pulse command submit failed: {e}')
|
||||
@@ -352,7 +356,7 @@ class LinkStatsCollector:
|
||||
return {}
|
||||
|
||||
# Validate interface names (kernel names only contain [a-zA-Z0-9_.-])
|
||||
safe_ifaces = [i for i in ifaces if re.match(r'^[a-zA-Z0-9_.@-]+$', i)]
|
||||
safe_ifaces = [i for i in ifaces if re.match(r'^[a-zA-Z0-9_.-]+$', i)]
|
||||
if not safe_ifaces:
|
||||
return {}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user