diff --git a/scripts/utils/start_web_conditionally.py b/scripts/utils/start_web_conditionally.py index b8f6e351..b3c3c99d 100644 --- a/scripts/utils/start_web_conditionally.py +++ b/scripts/utils/start_web_conditionally.py @@ -111,7 +111,7 @@ def main(): # Ensure PYTHONPATH is set correctly if web_interface.py has relative imports to src # The WorkingDirectory in systemd service should handle this for web_interface.py print(f"Launching web interface v3: {sys.executable} {WEB_INTERFACE_SCRIPT}") - os.execvp(sys.executable, [sys.executable, WEB_INTERFACE_SCRIPT]) + os.execvp(sys.executable, [sys.executable, WEB_INTERFACE_SCRIPT]) # nosec B606 - both args are fixed constants except Exception as e: print(f"Failed to exec web interface: {e}") sys.exit(1) # Failed to start diff --git a/src/cache/disk_cache.py b/src/cache/disk_cache.py index 8a9d6da2..13992dfc 100644 --- a/src/cache/disk_cache.py +++ b/src/cache/disk_cache.py @@ -183,7 +183,7 @@ class DiskCache: os.replace(tmp_path, cache_path) # Set proper permissions: 660 (rw-rw----) for group-readable cache files try: - os.chmod(cache_path, 0o660) + os.chmod(cache_path, 0o660) # nosec B103 - intentional; web UI and service share a group except OSError: pass # Non-critical if chmod fails finally: @@ -201,7 +201,7 @@ class DiskCache: os.fsync(cache_file.fileno()) # Set proper permissions: 660 (rw-rw----) for group-readable cache files try: - os.chmod(cache_path, 0o660) + os.chmod(cache_path, 0o660) # nosec B103 - intentional; web UI and service share a group except OSError: pass # Non-critical if chmod fails self.logger.debug("Wrote cache for %s directly (non-atomic)", key) @@ -227,7 +227,7 @@ class DiskCache: json.dump(data, tmp_file, indent=4, cls=DateTimeEncoder) # Set proper permissions: 660 (rw-rw----) for group-readable cache files try: - os.chmod(fallback_path, 0o660) + os.chmod(fallback_path, 0o660) # nosec B103 - intentional; web UI and service share a group except OSError: pass # Non-critical if chmod fails self.logger.debug("Cache wrote to fallback location: %s", fallback_path) diff --git a/src/font_manager.py b/src/font_manager.py index 6372fd6c..76dc7ec5 100644 --- a/src/font_manager.py +++ b/src/font_manager.py @@ -267,7 +267,7 @@ class FontManager: # Download font logger.info(f"Downloading font from {url}") - urllib.request.urlretrieve(url, cache_path) + urllib.request.urlretrieve(url, cache_path) # nosec B310 - URL from user's own config file on local device # Handle zip files if url.endswith('.zip'): diff --git a/src/wifi_manager.py b/src/wifi_manager.py index 21b87035..09e1f3a5 100644 --- a/src/wifi_manager.py +++ b/src/wifi_manager.py @@ -937,7 +937,7 @@ class WiFiManager: pass try: import urllib.request as _ureq - _ureq.urlopen("http://connectivity-check.ubuntu.com/", timeout=timeout) + _ureq.urlopen("http://connectivity-check.ubuntu.com/", timeout=timeout) # nosec B310 - hardcoded URL, no user input logger.debug("Internet connectivity confirmed via HTTP check") return True except OSError: diff --git a/web_interface/app.py b/web_interface/app.py index 4b02232d..393fef17 100644 --- a/web_interface/app.py +++ b/web_interface/app.py @@ -737,6 +737,9 @@ def check_health_monitor(): _threading.Thread(target=_run_startup_reconciliation, daemon=True).start() if __name__ == '__main__': + import os as _os # threaded=True is Flask's default since 1.0 but stated explicitly so that # long-lived /api/v3/stream/* SSE connections don't starve other requests. - app.run(host='0.0.0.0', port=5000, debug=True, threaded=True) + # Debug mode is off by default; opt in with FLASK_DEBUG=1 in the environment. + _debug = _os.environ.get('FLASK_DEBUG', '0') == '1' + app.run(host='0.0.0.0', port=5000, debug=_debug, threaded=True)