This release fixes issues for SREs watching stability and regressions.
✓ No known CVEs patched in this version
Topics
+9 more
Affected surfaces
Summary
AI summaryFixes broken WebSocket handshakes caused by silent CORS allowlist mutation in v0.1.1.
Changes in this release
| Type | Severity | Summary | CVE |
|---|---|---|---|
| Security | High |
Restricts SocketIO CORS origins to localhost after server bind, preventing cross-origin abuse Restricts SocketIO CORS origins to localhost after server bind, preventing cross-origin abuse Source: granite4.1:30b@2026-05-29-audit Confidence: low |
— |
| Feature | Low |
Adds boot log entry showing the final allowed SocketIO CORS origins Adds boot log entry showing the final allowed SocketIO CORS origins Source: granite4.1:30b@2026-05-29-audit Confidence: low |
— |
| Bugfix | Medium |
Fixes WebSocket handshake failures caused by silent CORS config error Fixes WebSocket handshake failures caused by silent CORS config error Source: llm_adapter@2026-05-29 Confidence: low |
— |
| Bugfix | Medium |
Fixes silent CORS configuration error causing all WebSocket handshakes to fail Fixes silent CORS configuration error causing all WebSocket handshakes to fail Source: granite4.1:30b@2026-05-29-audit Confidence: low |
— |
| Bugfix | Medium |
Removes silent exception handling around CORS origin restriction, surfacing failures as warnings Removes silent exception handling around CORS origin restriction, surfacing failures as warnings Source: granite4.1:30b@2026-05-29-audit Confidence: low |
— |
Full changelog
Required upgrade if you're on v0.1.1. v0.1.0 users can also upgrade straight to v0.1.2 — it includes everything from v0.1.1 (the CSRF + CORS hardening) plus this fix.
What this fixes
v0.1.1 set SocketIO's cors_allowed_origins=[] at module load time, planning to tighten it to localhost-only via register_security() once the bind port was known. The post-init mutation was wrapped in a silent except Exception: pass, so it failed quietly and the empty list rejected every WebSocket handshake — including the legitimate one from your own browser.
User-visible symptoms on v0.1.1:
- Browser console spam:
WebSocket connection ... failed: WebSocket is closed before the connection is established - Order placement times out at 10 seconds (
Error: Order placement timed out after 10 seconds) because the frontend was waiting for a fill event that never arrived over the broken WebSocket - Live price updates and position-card refreshes stop
The fix
- Initialize SocketIO with
cors_allowed_origins="*"at module load so legitimate connections fromhttp://127.0.0.1:<port>can hand-shake successfully - In
register_security(), narrow the allowlist to the actual localhost origin by setting bothsocketio.server.eio.cors_allowed_originsandsocketio.server.cors_allowed_origins(different python-socketio versions expose the attribute on different objects) — no silent except clauses - Boot log now prints
Security: SocketIO cors_allowed_origins locked to ['http://127.0.0.1:<port>', 'http://localhost:<port>']so you can verify which paths took effect - If the underlying library version doesn't expose either attribute, a loud
WARNINGis logged instead of silent failure
Verified
- WebSocket polling handshake from
http://127.0.0.1:<port>→ 200 with engine.io session ID - WebSocket polling handshake from
https://evil.example→ 400 "Not an accepted origin." - POST without CSRF token → 403 (v0.1.1 behavior preserved)
- POST with valid token + correct Origin → 200 (legitimate flow works)
How to upgrade
git pull
# launcher will pick up changes on next start
Restart the platform, refresh the browser tab so the new CSRF token loads, and orders should place + fill normally again.
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About calesthio/OptionsCanvas
All releases →Beta — feedback welcome: [email protected]