Skip to content

Missing Content-Security-Policy header and no SRI on CDN <script> in dashboard #89

Description

@BHUVANSH855

Security Report

Summary

The security headers middleware sets X-Content-Type-Options, X-Frame-Options, and Referrer-Policy, but does not set a Content-Security-Policy (CSP) header. Additionally, the dashboard template loads Chart.js from a CDN without a Subresource Integrity (integrity) attribute. Together these two gaps leave the dashboard — which renders authenticated user sessions and organization data — open to script injection attacks.

Locations

  • app/main.pyadd_security_headers middleware (~line 88)
  • dashboard/templates/dashboard.html — line 10

Root Cause

Missing CSP in middleware:

response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
response.headers["Referrer-Policy"] = "strict-origin-when-cross-origin"
# ← No Content-Security-Policy

CDN script without SRI:

<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<!-- ↑ No integrity="sha384-..." crossorigin="anonymous" -->

Impact

  • Without CSP, any XSS vector (e.g. a Jinja2 template bug, a future dependency vulnerability) can execute arbitrary scripts that exfiltrate session cookies or OAuth tokens
  • Without SRI, a compromise of cdn.jsdelivr.net or a CDN cache-poisoning attack silently executes attacker-controlled JavaScript in every dashboard session
  • The dashboard displays GitHub login, avatar, and org data — making it a high-value target

Suggested Fix

Add CSP header in main.py:

response.headers["Content-Security-Policy"] = (
    "default-src 'self'; "
    "script-src 'self' https://cdn.jsdelivr.net; "
    "style-src 'self' https://fonts.googleapis.com; "
    "font-src https://fonts.gstatic.com; "
    "img-src 'self' https://avatars.githubusercontent.com data:; "
    "connect-src 'self';"
)

Add SRI to Chart.js <script> tag:

<script
  src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"
  integrity="sha384-<hash>"
  crossorigin="anonymous">
</script>

Generate the hash with: curl -s <url> | openssl dgst -sha384 -binary | openssl base64 -A

Metadata

Metadata

Assignees

No one assigned

    Labels

    SecurityFor security enhancement.enhancementNew feature or requesthelp wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions