Skip to content

fix(frontend): plans.ts provider XSS (missing whitelist) + duplicate document/modal listeners (users, plans) #1034

Closed

Description

@cristim

Problem. Three Highs in files that skipped established patterns:

  • H1 Stored XSS: plans.ts:180 and :412 inject the API provider string into a class attribute + text via innerHTML with no whitelist (the fix already applied in history.ts:341 / recommendations.ts:2417).
  • H2 users/userList.ts:321 adds a document-level change listener on every renderUsers() → N duplicate PATCH /users/:id + N toasts after N renders.
  • H3 plans.ts:890 setupRampScheduleHandlers re-binds static modal elements on every modal open.

Evidence. Report 11 (H1, H2, H3, D1, D4). Matches feedback_innerhtml_xss / feedback_event_listener_dedup.

Suggested fix. Extract a shared providerBadgeClass() in utils.ts (D1) and use it in all four sites (also fixes L4 dashboard regex); guard the document/modal listeners with an install-once flag or AbortController (the attachPopoverGlobalListeners pattern). Optionally add a delegate() helper (D4) to make delegation the default.

References. Source: report 11 (H1, H2, H3 + D1, D4). Related #166 (column-filter primitives extraction — same "adopt shared module" theme).


Filed from automated adversarial code review (see docs/code-review/). Source finding(s): 11-H1, 11-H2, 11-H3.

Activity

  1. added
    bugSomething isn't working
    triagedItem has been triaged
    pr-createdA PR has been opened for this issue (dedup guard for the auto-PR loop)
    on Jun 7, 2026
  2. cristim commented on Jul 27, 2026

    @cristim
    MemberAuthor

    Verification sweep against main (101f099fb) on 2026-07-27 finds this already resolved.
    plans.ts now uses providerBadgeHtml() and the duplicate modal/global listener issue is guarded.
    Evidence: commit 84fcb9f.
    Recommending close.

  3. cristim commented on Sep 2, 2026

    @cristim
    MemberAuthor

    Verified resolved at 3c0f8ac: plans.ts renders the provider badge only through the shared providerBadgeHtml helper (whitelisted class, escaped label), the users list installs its document-level change listener through a single AbortController, and the ramp-schedule modal handlers are guarded by an install-once flag. Evidence: frontend/src/plans.ts:734 and frontend/src/users/userList.ts:415 (#1046). Residual axes checked: history.ts:520 and dashboard.ts:472 both use providerBadgeClass; no remaining raw provider interpolation into class or innerHTML in frontend/src. Closing as completed; reopen if the behaviour recurs.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingeffort/sHoursimpact/all-usersAffects every userpr-createdA PR has been opened for this issue (dedup guard for the auto-PR loop)pr-mergedThe PR for this issue has been mergedpriority/p2Backlog-worthyseverity/highSignificant harmtriagedItem has been triagedtype/bugDefecturgency/this-sprintWithin the current sprint

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions