Skip to content

fix: add Content Security Policy and security headers to hosting (#578) - #762

Open
saurabhhhcodes wants to merge 1 commit into
roshankumar0036singh:mainfrom
saurabhhhcodes:fix/578-content-security-policy
Open

fix: add Content Security Policy and security headers to hosting (#578)#762
saurabhhhcodes wants to merge 1 commit into
roshankumar0036singh:mainfrom
saurabhhhcodes:fix/578-content-security-policy

Conversation

@saurabhhhcodes

@saurabhhhcodes saurabhhhcodes commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Closes #578

Problem

Web deployment shipped with no CSP or hardening headers — inline XSS payloads would execute and the app could be framed by malicious sites.

Fix

Added a headers block to the hosting section of firebase.json:

  • CSP: default-src 'self'; scripts from self only; 'unsafe-inline' for styles only (React Native Web renders inline style attributes); https: for connect-src (Firestore, functions, Firebase Auth); blob/data sources for images; frame-ancestors 'none'; object-src 'none'.
  • X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin, Permissions-Policy (camera/mic/geolocation blocked).

Verification

firebase.json parses as valid JSON (python3 -m json.tool).

Summary by CodeRabbit

  • Security Enhancements
    • Added security-focused HTTP headers across all hosted routes.
    • Improved protection against framing, MIME-type sniffing, referrer leakage, and unauthorized browser feature access.
    • Added a Content Security Policy to help restrict unsafe resource loading.

…hankumar0036singh#578)

Web deployment shipped no CSP or hardening headers, leaving the app
open to XSS and clickjacking.

Adds to the hosting section of firebase.json:
- CSP: default-src 'self', scripts from self only, inline styles allowed
  (React Native Web injects style attributes), https: for connect-src
  (Firestore/functions/Auth), blob/data for images, no framing, no
  object-src.
- X-Frame-Options: DENY, X-Content-Type-Options: nosniff,
  Referrer-Policy: strict-origin-when-cross-origin,
  Permissions-Policy restricting camera/mic/geolocation.

Verified: firebase.json parses as valid JSON.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Firebase Hosting now serves Content Security Policy and additional browser security headers for all routes.

Changes

Hosting security headers

Layer / File(s) Summary
Configure catch-all security headers
firebase.json
The Hosting configuration adds Content-Security-Policy, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, and Permissions-Policy headers.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 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 identifies the addition of Content Security Policy and security headers to Firebase Hosting.
Linked Issues check ✅ Passed The Firebase Hosting security headers address issue #578 by adding CSP and protections against XSS-related risks.
Out of Scope Changes check ✅ Passed The changes are limited to the Firebase Hosting configuration and directly support issue #578.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@sonarqubecloud

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@firebase.json`:
- Around line 16-17: Update the Content-Security-Policy value in firebase.json
to replace scheme-wide connect-src https: and wss: permissions with an explicit
allowlist of the Firebase, Render, EmailJS, Google, and other service origins
used by the web app. Also restrict img-src https: to approved image hosts unless
arbitrary HTTPS images are required.
- Around line 16-17: Update the Content-Security-Policy value in firebase.json
to permit the external font origins used by EventDetail.js: add
https://fonts.googleapis.com to style-src and https://fonts.gstatic.com to
font-src, or replace those external font dependencies with self-hosted assets
while preserving the existing CSP restrictions.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 271558e9-c9eb-489c-87cf-4453319cba9a

📥 Commits

Reviewing files that changed from the base of the PR and between 5e6135e and 9ffd90e.

📒 Files selected for processing (1)
  • firebase.json

Comment thread firebase.json
Comment on lines +16 to +17
"key": "Content-Security-Policy",
"value": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https:; font-src 'self' data:; connect-src 'self' https: wss:; frame-ancestors 'none'; object-src 'none'; base-uri 'self'; form-action 'self'"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- firebase.json ---'
cat -n firebase.json
printf '%s\n' '--- relevant source and configuration files ---'
git ls-files | rg '(^|/)(firebase\.json|package\.json|vite\.config\..*|next\.config\..*|angular\.json|src/|public/|\.env[^/]*)' | head -200
printf '%s\n' '--- explicit external origins and CSP-related references ---'
rg -n --hidden -g '!node_modules' -g '!dist' -g '!build' \
  'https?://|wss?://|Content-Security-Policy|connect-src|img-src|script-src|frame-ancestors|firebase' . \
  | head -300

Repository: roshankumar0036singh/Uni-Event

Length of output: 37329


🏁 Script executed:

#!/bin/bash
set -e
python3 - <<'PY'
import json
from pathlib import Path

p = Path("firebase.json")
data = json.loads(p.read_text())
print(json.dumps(data, indent=2))
PY

Repository: roshankumar0036singh/Uni-Event

Length of output: 2014


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- application configuration ---'
for f in app/package.json app/.env.example app/src/lib/config.js app/src/lib/firebaseConfig.js app/src/lib/EmailService.js app/src/lib/notificationService.js app/src/lib/usePushNotifications.js; do
  if [ -f "$f" ]; then
    printf '\n--- %s ---\n' "$f"
    cat -n "$f"
  fi
done
printf '%s\n' '--- network-related call sites and URL literals ---'
rg -n --glob '!package-lock.json' --glob '!comments.txt' --glob '!*.map' \
  '(fetch\s*\(|axios|httpsCallable|connectFirestoreEmulator|connectDatabaseEmulator|connectStorageEmulator|initializeApp|storageBucket|firebaseio\.com|googleapis\.com|emailjs|wss?://|https?://)' \
  app/src app/public app/.env.example cloud-functions/.env.example \
  | head -400

Repository: roshankumar0036singh/Uni-Event

Length of output: 38904


🏁 Script executed:

#!/bin/bash
set -e
python3 - <<'PY'
import json, re
from pathlib import Path
from urllib.parse import urlsplit

files = []
for root in ("app/src", "app/public"):
    p = Path(root)
    if p.exists():
        files.extend(x for x in p.rglob("*") if x.is_file())

url_re = re.compile(r"""https?://[^\s"'`);,]+|wss?://[^\s"'`);,]+""")
origins = {}
for path in files:
    text = path.read_text(errors="ignore")
    for raw in url_re.findall(text):
        u = urlsplit(raw.rstrip("]}>"))
        if u.scheme and u.netloc:
            origins.setdefault(f"{u.scheme}://{u.netloc}", set()).add(str(path))

for origin in sorted(origins):
    print(origin)
    for path in sorted(origins[origin]):
        print(f"  {path}")

firebase = json.loads(Path("firebase.json").read_text())
csp = next(
    h["value"] for rule in firebase["hosting"]["headers"]
    for h in rule["headers"] if h["key"] == "Content-Security-Policy"
)
print("\nCSP source tokens:")
for directive in csp.split(";"):
    name, *sources = directive.strip().split()
    if name in {"img-src", "connect-src"}:
        print(f"{name}: {sources}")
PY

Repository: roshankumar0036singh/Uni-Event

Length of output: 2032


🏁 Script executed:

#!/bin/bash
set -e
python3 - <<'PY'
from urllib.parse import urlsplit

def matches_scheme_source(source, url):
    s = urlsplit(source)
    u = urlsplit(url)
    return bool(s.scheme and u.scheme.lower() == s.scheme.lower())

tests = [
    ("https:", "https://api.emailjs.com/api/v1.0/email/send"),
    ("https:", "https://attacker.example/upload"),
    ("https:", "http://attacker.example/upload"),
    ("wss:", "wss://attacker.example/socket"),
    ("wss:", "ws://attacker.example/socket"),
]
for source, url in tests:
    print(f"{source:7} {url:55} -> {matches_scheme_source(source, url)}")
PY

Repository: roshankumar0036singh/Uni-Event

Length of output: 530


Restrict CSP network sources to approved origins.

connect-src https: wss: permits requests and WebSocket connections to any HTTPS or WSS origin. Replace these scheme-wide sources with the Firebase, Render, EmailJS, Google, and other service origins required by the web app.

Keep img-src https: only if users must load images from arbitrary HTTPS hosts. Otherwise, replace it with an explicit image-host allowlist.

🤖 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 `@firebase.json` around lines 16 - 17, Update the Content-Security-Policy value
in firebase.json to replace scheme-wide connect-src https: and wss: permissions
with an explicit allowlist of the Firebase, Render, EmailJS, Google, and other
service origins used by the web app. Also restrict img-src https: to approved
image hosts unless arbitrary HTTPS images are required.

Source: MCP tools


🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n --glob '!firebase.json' --glob '!package-lock.json' \
  'https?://|wss?://|<script|stylesheet|action=' .

Repository: roshankumar0036singh/Uni-Event

Length of output: 26551


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- tracked configuration and web-entry candidates ---'
git ls-files | rg '(^|/)(firebase\.json|package\.json|app\.json|app\.config\.(js|ts)|index\.(html|js|tsx?)|manifest\.json|webpack|vite|metro|public/|src/)' | head -200

printf '%s\n' '--- firebase.json ---'
cat -n firebase.json

printf '%s\n' '--- app package and configuration ---'
for f in app/package.json app/app.json app/app.config.js app/app.config.ts app/index.html app/public/index.html; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    cat -n "$f"
  fi
done

printf '%s\n' '--- browser-facing source references ---'
rg -n --glob 'app/**' --glob '!app/package-lock.json' \
  'firebase-messaging|importScripts|GoogleAuthProvider|signInWith|fetch\(|XMLHttpRequest|WebSocket|new URL|window\.location|location\.assign|<form|action=|`@import`|fonts\.googleapis|gstatic|accounts\.google|oauth2\.googleapis|api\.emailjs|images\.unsplash|via\.placeholder|ui-avatars|dummyimage' .

Repository: roshankumar0036singh/Uni-Event

Length of output: 50387


🏁 Script executed:

#!/bin/bash
set -euo pipefail

log=/tmp/coderabbit-shell-logs/shell-output-3MW8de

printf '%s\n' '--- log beginning: tracked candidates and configuration ---'
sed -n '1,260p' "$log"

printf '%s\n' '--- tracked web files (excluding generated bundle internals) ---'
git ls-files app | rg '(^|/)(index\.html|app\.json|app\.config\.(js|ts)|package\.json|firebase-messaging-sw|manifest\.json|web-build/[^/]+$|web-build/.*/[^/]+\.html$)' | head -200

printf '%s\n' '--- firebase hosting configuration ---'
cat -n firebase.json

printf '%s\n' '--- web HTML and service-worker references ---'
for f in app/web-build/index.html app/public/firebase-messaging-sw.example.js app/web-build/firebase-messaging-sw.js; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    cat -n "$f"
  fi
done

printf '%s\n' '--- focused browser resource references (source only) ---'
rg -n --glob 'app/src/**' --glob 'app/public/**' --glob 'app/index.html' \
  'fonts\.googleapis|fonts\.gstatic|gstatic|importScripts|<script|stylesheet|`@import`|fetch\(|WebSocket|window\.open|form-action|action=' .

Repository: roshankumar0036singh/Uni-Event

Length of output: 20132


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- certificate and browser flow excerpts ---'
sed -n '660,700p' app/src/screens/EventDetail.js
sed -n '80,125p' app/src/screens/AuthScreen.js
sed -n '1,135p' app/src/lib/CalendarService.js

printf '%s\n' '--- deterministic CSP compatibility probe ---'
python3 - <<'PY'
import json
from pathlib import Path
from urllib.parse import urlparse

config = json.loads(Path("firebase.json").read_text())
csp = next(
    h["value"]
    for rule in config["hosting"]["headers"]
    if rule["source"] == "**"
    for h in rule["headers"]
    if h["key"].lower() == "content-security-policy"
)
directives = {}
for item in csp.split(";"):
    parts = item.strip().split()
    if parts:
        directives[parts[0]] = set(parts[1:])

def allowed(directive, url):
    origin = f"{urlparse(url).scheme}://{urlparse(url).netloc}"
    sources = directives[directive]
    return "'self'" in sources and origin == "https://unievent.example" or origin in sources or f"{urlparse(url).scheme}:" in sources

print("style-src allows fonts.googleapis.com:", allowed("style-src", "https://fonts.googleapis.com/css2?family=Montserrat"))
print("font-src allows fonts.gstatic.com:", allowed("font-src", "https://fonts.gstatic.com/s/montserrat/example.woff2"))
print("connect-src allows Google Calendar HTTPS:", allowed("connect-src", "https://www.googleapis.com/calendar/v3"))
print("form-action allows same-origin form:", "'self'" in directives["form-action"])
print("index external script count:", sum(
    "src=" in line and not 'src="/' in line
    for line in Path("app/web-build/index.html").read_text().splitlines()
))
PY

Repository: roshankumar0036singh/Uni-Event

Length of output: 8685


Allow the certificate flow’s external fonts, or self-host them. EventDetail.js imports https://fonts.googleapis.com and loads fonts from fonts.gstatic.com, but this CSP allows neither origin. The certificate will use fallback fonts.

🤖 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 `@firebase.json` around lines 16 - 17, Update the Content-Security-Policy value
in firebase.json to permit the external font origins used by EventDetail.js: add
https://fonts.googleapis.com to style-src and https://fonts.gstatic.com to
font-src, or replace those external font dependencies with self-hosted assets
while preserving the existing CSP restrictions.

Source: MCP tools

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Content Security Policy (CSP)

1 participant