Found something? Open an issue, or email the address on my GitHub profile. This is a personal project with no SLA, but credential-exposure issues will be handled promptly.
The asset worth protecting is a metered third-party API credential (Xweather client id + secret). Compromise means quota exhaustion and, on a paid plan, financial cost. There is no user data, no PII, and no authentication system.
Secondary concern: this is safety-adjacent software. A wrong or stale reading is a real risk, so availability and correctness are treated as security properties, not just features.
Credentials are entered in Settings and held in localStorage.
- ✅ Fine on a device you control
- ❌ Stored in plaintext — inherent to any keyed client-side app
- ❌ Never host this file publicly with credentials saved. Anyone loading the page gets your key from their own browser's storage after first save, and any XSS would expose it
The Cloudflare Worker holds credentials and the browser reads computed state as JSON.
- ✅ Secrets set via
wrangler secret put, encrypted at rest, never in source or git - ✅ Client never receives the credential
- ✅ Server-side fetch also resolves CORS restrictions
⚠️ Read endpoint is unauthenticated — see residual risks
| Area | Control |
|---|---|
| Credential isolation | Worker secrets via wrangler secret put; wrangler.toml git-ignored; .example template ships instead |
| Output encoding | All user-controlled strings (site names) pass an HTML-entity encoder before any innerHTML write |
| URL construction | encodeURIComponent on every interpolated value |
| Input validation | Coordinates rejected unless isFinite; numeric inputs bounded by min/max with fallback defaults on every parse |
| Pre-flight validation | Site sets exceeding the API's 100 km radius are rejected before a request that would silently return incomplete data |
| Response validation | success flag checked; warn_no_data distinguished from real errors so "clear skies" is never mistaken for failure |
| Spend limiting | Monthly cap enforced before request dispatch; prevents runaway loops draining the tier |
| Fail-safe degradation | try/catch around storage with in-memory fallback; .catch() on every network call; a failed push can't break the polling loop |
| Link hygiene | External links rel="noopener"; iframes lazy-loaded |
Listed because undisclosed weaknesses are worse than disclosed ones.
- Plaintext client-side credential storage in local-only mode. Unavoidable for a keyed browser app. Mitigation: use the Worker; never host the raw file publicly.
- Unauthenticated Worker read endpoint. Anyone with the URL sees site status. Low sensitivity (public weather), but it is an open endpoint. Fix: add a shared-secret header or Cloudflare Access.
- ntfy topics are public by design. Security rests on an unguessable topic name — that's obscurity, not authentication. Mitigation: use a long random topic. Fix: self-host ntfy with auth.
- No Content-Security-Policy. The client loads Leaflet from a CDN without SRI. Fix: add SRI hashes and a CSP header, or vendor Leaflet locally.
- No automated test suite. Rule-engine logic was validated against 9 timer edge cases and the heat-index math against 8 published NWS reference values, but manually rather than in CI.
- Third-party availability. Radar, WBGT, and observations come from external services with no SLA. The app degrades rather than failing, but data can go stale silently.
- Revoke it in the Xweather dashboard immediately
- Generate a replacement
- If it was committed, rewrite history — deleting the file is not enough:
Assume anything pushed to a public repo was scraped within minutes. Rotate regardless.
git filter-repo --path <file> --invert-paths # or BFG Repo-Cleaner git push --force
This software is provided without warranty. It reads detected lightning; many facilities use predictive systems that trigger earlier. Modelled WBGT runs cooler than field measurement and does not satisfy on-site measurement requirements such as Florida's Zachary Martin Act.
Never use this as the sole basis for a decision affecting anyone's safety.