Escape ME_DATA JSON in script block and add HSTS by martinmain93 · Pull Request #442 · FundersClub/fire · GitHub
Skip to content

Escape ME_DATA JSON in script block and add HSTS#442

Open
martinmain93 wants to merge 1 commit into
masterfrom
security/xss-escape-and-hsts
Open

Escape ME_DATA JSON in script block and add HSTS#442
martinmain93 wants to merge 1 commit into
masterfrom
security/xss-escape-and-hsts

Conversation

@martinmain93

Copy link
Copy Markdown
Contributor

Summary

Two security fixes for fire.fundersclub.com, both surfaced by a recent pentest:

1. Stored XSS via unescaped JSON in a <script> block (the high-severity one)

app_html injects MeView.get_me_data() into a <script> block using json.dumps(), which does not escape <, >, or &. A repository's emailmap_set contains attacker-influenceable sender email addresses (from_email), so a crafted address could break out of the script element and execute in a repo admin's browser when they load /repos.

Fix: escape <, >, & to their \uXXXX forms before injection (U+2028/U+2029 are already escaped by json.dumps' ensure_ascii default), matching Django's json_script scheme. This neutralizes the payload regardless of who plants it.

2. Missing HSTS in production

firebot/settings/prod.py set SECURE_SSL_REDIRECT and secure cookies but never set HSTS headers. Added SECURE_HSTS_SECONDS (1 year), includeSubDomains, and preload.

Notes

  • The pentest also flagged the associate-email POST authorization. After investigation we deliberately left it as is_authenticated-only: that endpoint is designed for external (non-admin) senders to self-link their email, so requiring repo-admin would break the feature. The XSS escaping above is the actual remediation; the residual identity-binding weakness is low severity and accepted.
  • No existing test covers app_html; a regression test asserting a </script> payload in ME_DATA is escaped would be a good follow-up.

🤖 Generated with Claude Code

Fixes a stored XSS: app_html injects MeView.get_me_data() into a <script>
block via json.dumps(), which does not escape <, >, or &. A repo's emailmap
contains attacker-influenced sender email addresses, so a crafted from_email
could break out of the script element and execute in a repo admin's browser.
Escape <, >, & to their \uXXXX forms before injection (U+2028/U+2029 are
already escaped by json.dumps' ensure_ascii default), matching Django's
json_script scheme.

Also add HSTS response headers to production (SECURE_HSTS_SECONDS=1y,
includeSubDomains, preload), which were previously unset.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@martinmain93 martinmain93 force-pushed the security/xss-escape-and-hsts branch from 68c0887 to d4f4e41 Compare June 22, 2026 13:51
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.

1 participant