Skip to content

fix: escape user-controlled category/description before innerHTML inj… - #1670

Merged
steam-bell-92 merged 1 commit into
steam-bell-92:mainfrom
akshara200829-lgtm:fix/budget-tracker-xss-escaping
Jul 12, 2026
Merged

fix: escape user-controlled category/description before innerHTML inj…#1670
steam-bell-92 merged 1 commit into
steam-bell-92:mainfrom
akshara200829-lgtm:fix/budget-tracker-xss-escaping

Conversation

@akshara200829-lgtm

@akshara200829-lgtm akshara200829-lgtm commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

📝 Description

Fixes unsanitized innerHTML usage in the Budget Tracker, where user-supplied custom category and description values were interpolated directly into template strings without escaping — allowing arbitrary HTML/JS to execute in the browser (self-XSS), and persist across reloads via localStorage.
Added an escapeHTML() helper that converts a string into safe, literal text using the browser's own DOM serialization (via textContent → innerHTML round-trip). Applied it to the two places where user input reaches innerHTML:

renderTransactions() — escapes t.category and t.description
renderBreakdown() — escapes cat (the category name used in the breakdown label)

Note: populateCategories() (the categorySelect.innerHTML dropdown) was left unchanged — it's built only from the static BUDGET_CATEGORIES constant, not user input, so it wasn't actually affected by this vulnerability.
Tested: injecting the payload above into both the custom category field and the description field, confirmed no script execution in the transaction list or breakdown panel, and confirmed it stays inert after a page reload (localStorage round-trip).

🔗 Linked Issue

Closes #1583


📋 Contribution Checklist

  • I have verified that my files are placed in the correct directory.
  • I have tested my changes thoroughly on my local machine.
  • GSSoC 2026: I have been formally assigned to this issue and noted it above.

@vercel

vercel Bot commented Jul 12, 2026

Copy link
Copy Markdown

@akshara200829-lgtm is attempting to deploy a commit to the Anuj's projects Team on Vercel.

A member of the Team first needs to authorize it.

@akshara200829-lgtm

Copy link
Copy Markdown
Contributor Author

The failing/cancelled checks (3.10, 3.11, 3.12) are unrelated to this PR.

The actual failure is a pre-existing test collection error in tests/test_merge_sort.py:

AttributeError: module 'validation' has no attribute 'get_choice'

This occurs in math/Merge-Sort/Merge-Sort.py line 17, and traces back to commits f55e900 and 9e2ba07 — both predate this branch and touch files unrelated to this PR (only web-app/js/projects/budget-tracker.js was modified here). Confirmed the same failure reproduces on a clean main checkout.

@steam-bell-92 steam-bell-92 added level:beginner gssoc:approved GSSoC 2026 approving tag labels Jul 12, 2026
@steam-bell-92
steam-bell-92 merged commit a86424c into steam-bell-92:main Jul 12, 2026
0 of 4 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🎉 Thank you for your contribution!

Your Pull Request has been merged successfully.
Thanks again for your support! 🙌

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

Labels

gssoc:approved GSSoC 2026 approving tag level:beginner

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: Budget Tracker renders user input (category/description) via innerHTML without sanitization (XSS anti-pattern)

2 participants