Skip to content

fix(weather): allow open-meteo origins in CSP connect-src (#1668) - #1669

Merged
jaylfc merged 1 commit into
devfrom
fix/1668-weather-csp-open-meteo
Jul 6, 2026
Merged

fix(weather): allow open-meteo origins in CSP connect-src (#1668)#1669
jaylfc merged 1 commit into
devfrom
fix/1668-weather-csp-open-meteo

Conversation

@jaylfc

@jaylfc jaylfc commented Jul 6, 2026

Copy link
Copy Markdown
Owner

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 global SecurityHeadersMiddleware sets connect-src 'self' ws: wss: data: on every response, so default-src 'self' blocked every request to open-meteo.com. searchLocations catches 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.com and https://api.open-meteo.com to connect-src. These are the only two origins the built-in Weather app needs; nothing else is widened.

Test

test_csp_allows_weather_open_meteo_origins asserts both origins are present in the served CSP. Full tests/test_security_headers.py: 8 passed.

Takes effect on a controller update (backend middleware header) - no SPA rebuild needed.

Summary by CodeRabbit

  • Bug Fixes
    • Updated security headers so the app can connect directly to Open-Meteo services without being blocked by the browser.
    • Fixed an issue affecting weather-related requests on the health endpoint.
    • Added a regression test to help prevent Content Security Policy connection issues from returning.

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-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The 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.

Changes

CSP Open-Meteo Allowlist

Layer / File(s) Summary
Extend connect-src and add regression test
tinyagentos/middleware/security_headers.py, tests/test_security_headers.py
_build_csp() now appends geocoding-api.open-meteo.com and api.open-meteo.com to connect-src; a new async test asserts both origins appear in the CSP header returned by /api/health, referencing regression issue #1668.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Related issues: #1668 (Weather location search non-functional due to CSP blocking direct requests to Open-Meteo APIs)

Suggested labels: bug, security, weather

Suggested reviewers: jaylfc

🐰 A hop, a fetch, a CSP tweak,
Open-Meteo's gates no longer creak,
Weather search can roam once more,
Through connect-src's open door. 🌤️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: allowing Open-Meteo origins in the Weather app CSP for issue #1668.
Linked Issues check ✅ Passed The CSP update and regression test address the location search failure by allowing the Open-Meteo requests blocked in #1668.
Out of Scope Changes check ✅ Passed The changes stay focused on the CSP fix and its regression test, with no unrelated code introduced.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/1668-weather-csp-open-meteo

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kilo-code-bot

kilo-code-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (2 files)
  • tinyagentos/middleware/security_headers.py
  • tests/test_security_headers.py

Reviewed by minimax-m3 · Input: 20.5K · Output: 1.4K · Cached: 135.9K

@gitar-bot

gitar-bot Bot commented Jul 6, 2026

Copy link
Copy Markdown

Important

You are using the Gitar free plan. Upgrade to unlock code review, CI analysis, auto-apply, custom automations, and more.

Gitar

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5dea7c7 and f229551.

📒 Files selected for processing (2)
  • tests/test_security_headers.py
  • tinyagentos/middleware/security_headers.py

Comment on lines +35 to +37
csp = resp.headers.get("content-security-policy", "")
assert "https://geocoding-api.open-meteo.com" in csp
assert "https://api.open-meteo.com" in csp

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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.

Suggested change
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.

@jaylfc
jaylfc merged commit 24b5ea3 into dev Jul 6, 2026
11 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to Done in TinyAgentOS Roadmap Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Development

Successfully merging this pull request may close these issues.

1 participant