From 1cc64cba6af7d12c414e756787c8dd0e8caa59c5 Mon Sep 17 00:00:00 2001 From: Shine Date: Thu, 8 Oct 2026 17:01:44 +0800 Subject: [PATCH 1/4] security(socket): define explicit development browser origins --- inference/socket_policy.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 inference/socket_policy.py diff --git a/inference/socket_policy.py b/inference/socket_policy.py new file mode 100644 index 0000000..cc59e9f --- /dev/null +++ b/inference/socket_policy.py @@ -0,0 +1,10 @@ +"""Allowed browser origins for CropLens' localhost-only Socket.IO demo. + +This is origin-based defense-in-depth, not authentication. Keep the +inference server on loopback; never treat this as a public access policy. +""" + +LOCAL_VITE_ORIGINS = ( + "http://localhost:8100", + "http://127.0.0.1:8100", +) From fa9383efb63c1493ac8831a61a401a15dd49d6da Mon Sep 17 00:00:00 2001 From: Shine Date: Thu, 8 Oct 2026 17:01:55 +0800 Subject: [PATCH 2/4] security(socket): restrict browser connections to local Vite origins --- inference/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inference/main.py b/inference/main.py index 7cd2511..3d62977 100644 --- a/inference/main.py +++ b/inference/main.py @@ -8,6 +8,7 @@ from predict import predictImg from input_validation import resolve_weight_file, validate_local_media_url from image_requests import process_image +from socket_policy import LOCAL_VITE_ORIGINS from flask_socketio import SocketIO, emit @@ -16,7 +17,7 @@ class VideoProcessingApp: def __init__(self, host='127.0.0.1', port=5000): """初始化 Flask 应用并设置路由""" self.app = Flask(__name__) - self.socketio = SocketIO(self.app, cors_allowed_origins="*") # 初始化 SocketIO + self.socketio = SocketIO(self.app, cors_allowed_origins=list(LOCAL_VITE_ORIGINS)) self.host = host self.port = port self.setup_routes() From 14750f7f54af2734fa4a0ec19f284a319e285a10 Mon Sep 17 00:00:00 2001 From: Shine Date: Thu, 8 Oct 2026 17:02:05 +0800 Subject: [PATCH 3/4] test(socket): guard against restoring wildcard CORS origins --- inference/tests/test_socket_policy.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 inference/tests/test_socket_policy.py diff --git a/inference/tests/test_socket_policy.py b/inference/tests/test_socket_policy.py new file mode 100644 index 0000000..f113a4a --- /dev/null +++ b/inference/tests/test_socket_policy.py @@ -0,0 +1,22 @@ +"""Regression guardrails for the local demo's websocket Origin allowlist.""" +import unittest + +from socket_policy import LOCAL_VITE_ORIGINS + + +class SocketOriginPolicyTests(unittest.TestCase): + def test_only_local_vite_origins_are_allowed(self): + self.assertEqual( + set(LOCAL_VITE_ORIGINS), + {"http://localhost:8100", "http://127.0.0.1:8100"}, + ) + + def test_no_wildcard_or_remote_origin(self): + for origin in LOCAL_VITE_ORIGINS: + self.assertNotIn("*", origin) + self.assertNotIn("0.0.0.0", origin) + self.assertNotIn("https://", origin) + + +if __name__ == "__main__": + unittest.main() From 976468804c4ec7b611fb55b1d5d4870e717f97d3 Mon Sep 17 00:00:00 2001 From: Shine Date: Thu, 8 Oct 2026 17:02:15 +0800 Subject: [PATCH 4/4] docs(socket): explain local websocket origin restrictions --- docs/CONFIGURATION.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index c684f64..1861761 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -59,3 +59,7 @@ This intentionally changes the previous ability to pass arbitrary remote URLs. T The local Spring Boot `/files/upload` and `/files/editor/upload` endpoints now discard directory components from browser-supplied filenames, reject empty/control-character/oversized names with HTTP 400, and stream upload bytes into the configured local `backend/files/` directory instead of loading whole files into memory. Returned upload URLs encode the stored filename. Downloads match either the exact generated filename or the generated UUID followed by an underscore, avoiding arbitrary substring matches. **Scope:** This is path and memory hygiene for a local prototype, **not** user authentication or upload content validation. Limit public access, review content-type restrictions, enforce quotas and scan untrusted files before production use. Existing previously uploaded files are not renamed. + +## Local video progress WebSocket + +The Flask-SocketIO progress channel accepts browser origins only from `http://localhost:8100` and `http://127.0.0.1:8100`; wildcard CORS has been removed. This matches the loopback-only Vite development server. If you use a different frontend origin, do **not** remove the restriction by setting `*`; implement a deployment-specific authenticated origin and access policy instead. An allowed browser Origin is not proof of a trusted user.