Skip to content

No Content-Security-Policy header anywhere — RSS entity decoding + third-party scripts leave XSS fully unmitigated #70

Description

@tg12

Summary

No Content-Security-Policy (CSP) header is set anywhere in the application. The app loads third-party scripts (TradingView widgets, MapLibre GL, Three.js) and renders unescaped HTML content from arbitrary RSS feed descriptions in the signal feed. Without a CSP, any XSS vulnerability in a third-party dependency or RSS feed injection immediately results in full script execution under the application's origin — which shares a domain with the Telegram notification and alert APIs.

Evidence

File: next.config.mjs — security headers set:

{ key: 'X-Content-Type-Options', value: 'nosniff' },
{ key: 'X-Frame-Options', value: 'SAMEORIGIN' },
{ key: 'X-XSS-Protection', value: '1; mode=block' },
// ← No Content-Security-Policy header anywhere

Third-party scripts loaded with no integrity checks:

  • TradingView widget: <script src="https://s3.tradingview.com/tv.js"> (external, no SRI hash)
  • MapLibre GL: loaded from CDN
  • Three.js: npm bundle but also globe.gl package which loads workers

RSS content parsed and rendered:

// src/app/api/signals/route.ts
const cleanTitle = title.replace(/<[^>]*>/g, "")  // strips tags but not all XSS vectors
  .replace(/&amp;/g, "&")                           // entity decode — can introduce chars
  .replace(/&lt;/g, "<")                            // ← decodes < — potential injection
  .replace(/&gt;/g, ">")

The entity decode step transforms &lt;script&gt;<script> in signal titles and summaries. If this decoded content is then rendered in a React component without proper escaping (or via dangerouslySetInnerHTML), it becomes XSS.

X-XSS-Protection: 1; mode=block is deprecated and ineffective in modern browsers. It is not a substitute for CSP.

Why this matters

Without a CSP:

  • A malicious RSS feed item containing encoded XSS payload (&lt;img src=x onerror=...&gt;) that survives the entity decode step will execute in the browser.
  • Any compromised third-party script (TradingView, CDN) executes without restriction.
  • XSS on this origin has access to the browser's push notification subscription, service worker registration, and any localStorage state.
  • The lack of CSP means there is no way to detect or block exfiltration of credentials or subscription data.

Root cause

Security headers were partially added (X-Frame-Options, X-Content-Type-Options) but CSP was omitted — likely because adding a correct CSP requires iterating on the script-src, connect-src, and worker-src directives to allow the legitimate third-party dependencies. This is effort, so it was skipped.

Recommended fix

Start with a report-only CSP to identify violations, then tighten:

// next.config.mjs
{
  key: 'Content-Security-Policy',
  value: [
    "default-src 'self'",
    "script-src 'self' 'unsafe-eval' https://s3.tradingview.com https://unpkg.com",
    "style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
    "img-src 'self' data: https:",
    "connect-src 'self' https://api.telegram.org https://*.tradingview.com wss:",
    "worker-src 'self' blob:",
    "frame-src 'self' https://www.tradingview.com https://www.marinetraffic.com",
    "report-uri /api/csp-report",
  ].join('; ')
}

Also: add Subresource Integrity (SRI) hashes to any externally loaded scripts.

Acceptance criteria

  • Content-Security-Policy header present on all responses.
  • CSP blocks inline script execution not explicitly permitted.
  • Third-party scripts have SRI hashes or are bundled locally.
  • Entity decoding in RSS parser does not produce injectable HTML output.
  • Deprecated X-XSS-Protection header removed.

Suggested labels

security, bug

Priority

P0

Severity

High — no CSP on an application that renders third-party scripts and decodes RSS HTML entities; any XSS is fully unmitigated.

Confidence

Confirmed — no CSP header present in next.config.mjs; entity decode pattern confirmed in src/app/api/signals/route.ts.


This issue was filed as part of the AI Slop Intelligence Dashboard Awareness Program.
Repo under review: https://github.com/OpenScanAI/GlobeNewsLive
Programme: https://labs.jamessawyer.co.uk/ai-slop-intelligence-dashboards/

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions