fix(weather): allow open-meteo origins in CSP connect-src (#1668) - #1669
Conversation
The built-in Weather app fetches the open-meteo geocoding (city search) and forecast APIs directly from the browser, but the global CSP connect-src was 'self' ws: wss: data: only. default-src 'self' therefore blocked every lookup, and searchLocations swallows the error into an empty result, so the search field looked completely dead with no visible error. Add both open-meteo origins to connect-src. Regression test asserts they are present.
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
📝 WalkthroughWalkthroughThe Content-Security-Policy builder in the security headers middleware is updated to add two Open-Meteo API origins to the connect-src directive. A regression test is added verifying the CSP header on /api/health includes these origins. ChangesCSP Open-Meteo Allowlist
Estimated code review effort: 1 (Trivial) | ~5 minutes Related issues: Suggested labels: bug, security, weather Suggested reviewers: jaylfc 🐰 A hop, a fetch, a CSP tweak, 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Files Reviewed (2 files)
Reviewed by minimax-m3 · Input: 20.5K · Output: 1.4K · Cached: 135.9K |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_security_headers.py`:
- Around line 35-37: The security header test is too loose because it only
checks that the Open-Meteo origins appear somewhere in the CSP string. Tighten
the assertions in test_security_headers.py so they specifically verify the
content-security-policy’s connect-src directive includes
https://geocoding-api.open-meteo.com and https://api.open-meteo.com, using the
existing resp and csp checks to locate the directive rather than matching the
full header text.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: b5962502-1f0e-4117-bc78-049cc0b626b5
📒 Files selected for processing (2)
tests/test_security_headers.pytinyagentos/middleware/security_headers.py
| csp = resp.headers.get("content-security-policy", "") | ||
| assert "https://geocoding-api.open-meteo.com" in csp | ||
| assert "https://api.open-meteo.com" in csp |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Assert the origins are in connect-src, not just somewhere in the CSP.
This can pass if the URLs are accidentally added to another directive, while Weather fetches remain blocked.
Proposed test tightening
resp = await client.get("/api/health")
csp = resp.headers.get("content-security-policy", "")
- assert "https://geocoding-api.open-meteo.com" in csp
- assert "https://api.open-meteo.com" in csp
+ directives = {
+ directive.strip().split(" ", 1)[0]: directive.strip().split(" ")[1:]
+ for directive in csp.split(";")
+ if directive.strip()
+ }
+ connect_src = directives.get("connect-src", [])
+ assert "https://geocoding-api.open-meteo.com" in connect_src
+ assert "https://api.open-meteo.com" in connect_src📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| csp = resp.headers.get("content-security-policy", "") | |
| assert "https://geocoding-api.open-meteo.com" in csp | |
| assert "https://api.open-meteo.com" in csp | |
| resp = await client.get("/api/health") | |
| csp = resp.headers.get("content-security-policy", "") | |
| directives = { | |
| directive.strip().split(" ", 1)[0]: directive.strip().split(" ")[1:] | |
| for directive in csp.split(";") | |
| if directive.strip() | |
| } | |
| connect_src = directives.get("connect-src", []) | |
| assert "https://geocoding-api.open-meteo.com" in connect_src | |
| assert "https://api.open-meteo.com" in connect_src |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/test_security_headers.py` around lines 35 - 37, The security header
test is too loose because it only checks that the Open-Meteo origins appear
somewhere in the CSP string. Tighten the assertions in test_security_headers.py
so they specifically verify the content-security-policy’s connect-src directive
includes https://geocoding-api.open-meteo.com and https://api.open-meteo.com,
using the existing resp and csp checks to locate the directive rather than
matching the full header text.
Fixes #1668.
Root cause
The built-in Weather app (
WeatherApp.tsx,WeatherWidget.tsx) fetches the open-meteo geocoding (city search) and forecast APIs directly from the browser. The globalSecurityHeadersMiddlewaresetsconnect-src 'self' ws: wss: data:on every response, sodefault-src 'self'blocked every request toopen-meteo.com.searchLocationscatches the CSP error and returns[], so the search field looks completely dead - no results, no error - exactly as reported.This is why it reproduces on a fresh desktop install (current CSP enforced) but can appear to work on an installed mobile PWA serving a cached shell from before the CSP was tightened.
Fix
Add
https://geocoding-api.open-meteo.comandhttps://api.open-meteo.comtoconnect-src. These are the only two origins the built-in Weather app needs; nothing else is widened.Test
test_csp_allows_weather_open_meteo_originsasserts both origins are present in the served CSP. Fulltests/test_security_headers.py: 8 passed.Takes effect on a controller update (backend middleware header) - no SPA rebuild needed.
Summary by CodeRabbit