Skip to content

fix: Prevent XSS vulnerability in report rendering (#546)#580

Open
SinghCharanjeet11 wants to merge 6 commits intofossasia:mainfrom
SinghCharanjeet11:fix/xss-security-vulnerability-546
Open

fix: Prevent XSS vulnerability in report rendering (#546)#580
SinghCharanjeet11 wants to merge 6 commits intofossasia:mainfrom
SinghCharanjeet11:fix/xss-security-vulnerability-546

Conversation

@SinghCharanjeet11
Copy link
Copy Markdown

@SinghCharanjeet11 SinghCharanjeet11 commented Apr 20, 2026

Description

This PR fixes a critical XSS (Cross-Site Scripting) security vulnerability in the Scrum Helper extension where malicious HTML/JavaScript in GitHub/GitLab API responses could execute in the extension context or email compose window.

Fixes #546

Problem

The extension was rendering user-controlled data from GitHub/GitLab API responses (PR titles, issue titles, commit messages, repository names) directly into HTML without sanitization. An escapeHtml() function existed but was never used in report rendering, allowing potential XSS attacks.

Attack Vectors:

  • Malicious PR/issue titles with <script> tags
  • Commit messages with <img src=x onerror=alert('XSS')>
  • Repository names with HTML injection
  • URLs with attribute injection (' onclick='alert(1))

Solution

Applied the existing escapeHtml() function to all vulnerable locations in src/scripts/scrumHelper.js:

Changes Made:

  1. PR/MR Rendering (Draft, Open, Closed, Merged states)

    • Escaped title, project, html_url in all PR rendering paths
    • Escaped commit.messageHeadline in commit lists
    • Lines: 1771-1820
  2. Issue Rendering (Open, Closed states)

    • Escaped title, project, html_url in all issue rendering paths
    • Lines: 1829-1863
  3. Reviewed PRs Rendering

    • Escaped pr_arr.title, pr_arr.html_url (single PR format)
    • Escaped pr_arr1.title, pr_arr1.html_url (list format)
    • Lines: 1464-1500

Security Impact

Prevents arbitrary JavaScript execution from malicious API data
Protects GitHub/GitLab tokens and user activity data
Secures both extension popup and email compose window contexts
Handles all HTML special characters: &, <, >, ", '

Preservation

All existing functionality is preserved:

  • ✅ Clickable hyperlinks work correctly
  • ✅ Status buttons (open/closed/merged/draft) display properly
  • ✅ Nested commit lists maintain structure
  • ✅ Visual layout unchanged
  • ✅ No breaking changes to legitimate content

Testing

  • ✅ Extension builds successfully for Chrome and Firefox
  • ✅ No syntax errors or linting issues
  • ✅ All HTML special characters properly escaped
  • ✅ Existing functionality preserved

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Security fix (addresses a security vulnerability)

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • The extension builds successfully (npm run build)

Summary by Sourcery

Fix XSS vulnerabilities in scrum report rendering and enhance GitLab integration for commits and documentation.

Bug Fixes:

  • Escape user-controlled PR, issue, and commit fields when rendering reports to prevent XSS in the extension popup and email compose views.

Enhancements:

  • Include authored GitLab commits from all accessible projects in the fetched data and render them in the scrum reports.
  • Extend GitLab helper processing to normalize commits alongside issues and merge requests for report generation.

Documentation:

  • Update README to highlight GitLab support, multi-platform capabilities, and the roadmap for upcoming SCM integrations and analytics.

SinghCharanjeet11 and others added 6 commits March 31, 2026 18:14
- Update biome schema version from 2.3.13 to 2.4.10 to match CLI
- Add GitLab and Gitea support to roadmap in README
- Highlight new multi-platform features in Features section
- Document upcoming SCM analytics and Gitea integration

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add commits fetching from GitLab projects with date filtering
- Map commits to standard format for report generation
- Include commits data in GitLab data processing
- Add project metadata to commits for better tracking
- Support author filtering using author_name parameter

This enables complete feature parity with GitHub support:
Projects fetching
Merge requests fetchingIssues fetching Commits fetching
…upport

feat: complete GitLab support with commits fetching
- Add commits fetching from GitLab projects with date filtering
- Map commits to standard format for report generation
- Include commits data in GitLab data processing
- Add project metadata to commits for better tracking
- Support author filtering using author_name parameter

This enables complete feature parity with GitHub support:
Projects fetching
Merge requests fetchingIssues fetching Commits fetching
…upport

feat: complete GitLab support with commits fetching
Apply escapeHtml() to all user-controlled data from GitHub/GitLab API
responses before HTML insertion. Fixes XSS vulnerabilities in PR titles,
issue titles, commit messages, and repository names.

- Escape title, project, html_url in all PR/issue rendering
- Escape commit.messageHeadline in commit lists
- Escape reviewed PR titles and URLs
- Preserve all existing HTML structure and functionality

Security Impact:
- Prevents arbitrary JavaScript execution from malicious API data
- Protects GitHub/GitLab tokens and user activity data
- Secures both extension popup and email compose window contexts

Fixes fossasia#546
@github-actions github-actions Bot added javascript Pull requests that update javascript code core documentation config labels Apr 20, 2026
@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Apr 20, 2026

Reviewer's Guide

Applies HTML escaping to all rendered GitHub/GitLab PR, MR, issue, and commit fields to fix an XSS vulnerability, and extends GitLab integration to fetch and render user commits alongside existing activity.

Sequence diagram for GitLab activity and commit fetching into scrum report

sequenceDiagram
  actor User
  participant Extension
  participant GitLabHelper
  participant GitLabAPI
  participant ReportRenderer

  User->>Extension: Trigger scrum report generation
  Extension->>GitLabHelper: Request GitLab activity data
  GitLabHelper->>GitLabAPI: GET users, projects
  GitLabAPI-->>GitLabHelper: users, projects
  loop For each project
    GitLabHelper->>GitLabAPI: GET merge requests and issues
    GitLabAPI-->>GitLabHelper: merge requests, issues
    GitLabHelper->>GitLabAPI: GET commits with author_name and date range
    GitLabAPI-->>GitLabHelper: commits with project metadata
  end
  GitLabHelper-->>Extension: gitlabData with mergeRequests, issues, commits
  Extension->>Extension: Map commits to standard format gitlabCommits
  Extension->>ReportRenderer: writeGithubIssuesPrs for issues, merge requests, commits
  ReportRenderer-->>User: HTML scrum report including GitLab commits
Loading

Updated class diagram for GitLab data and mapped commit items

classDiagram
  class GitlabDataRaw {
    user
    projects
    mergeRequests
    issues
    commits
    comments
  }

  class GitlabDataProcessed {
    mergeRequests
    issues
    commits
    comments
    user
  }

  class GitlabCommitItem {
    string id
    string short_id
    string title
    string message
    string author_name
    string author_email
    string created_at
    string project_id
    string project_name
    string project_url
    string web_url
  }

  class MappedCommitItem {
    string id
    string sha
    string message
    string html_url
    string project
    string author_name
    string author_email
  }

  GitlabDataRaw "1" --> "*" GitlabCommitItem : contains
  GitlabDataProcessed "1" --> "*" GitlabCommitItem : includes
  GitlabCommitItem --> MappedCommitItem : mapped_to
Loading

Flow diagram for escaping HTML in rendered report fields

flowchart TD
  APIResponse["GitHub and GitLab API data
  titles, URLs, messages, project names"]
  Renderer["Scrum report renderer
  writeGithubIssuesPrs and related logic"]
  Escape["escapeHtml applied to
  title, project, html_url,
  commit.messageHeadline"]
  SafeHTML["Safe HTML list items
  and links in report"]
  Email["Email compose window /
  extension popup"]

  APIResponse --> Renderer
  Renderer --> Escape
  Escape --> SafeHTML
  SafeHTML --> Email
Loading

File-Level Changes

Change Details Files
Sanitize all user-controlled PR/MR and commit fields in the report renderer to prevent XSS.
  • Wrap PR/MR titles, project names, and URLs with escapeHtml before inserting into HTML strings across all status branches (draft, open, closed, merged).
  • Escape commit.messageHeadline when rendering nested commit lists under PRs/MRs.
  • Sanitize reviewed PRs’ titles and URLs in both single and list render formats.
src/scripts/scrumHelper.js
Sanitize GitHub/GitLab issue fields in the report renderer to prevent XSS.
  • Escape issue project names, titles, and URLs when rendering open/closed issues in the scrum report.
  • Ensure conditional ‘Work on Issue’ and state_reason-based outputs use escaped values in all branches, including fallback paths.
src/scripts/scrumHelper.js
Add GitLab commits to fetched data and normalize them for reuse in the existing report generation pipeline.
  • Fetch commits per project from GitLab for the selected date range, annotate them with project metadata, and aggregate into a single commits array.
  • Include commits in the cached GitLab payload and in the processed structure returned by GitLabHelper.
  • Normalize mapped GitLab commits in allIncluded to the GitHub-style shape (message, html_url, sha, project, author_name, author_email).
  • Feed the normalized GitLab commits into writeGithubIssuesPrs for rendering when platform is gitlab.
src/scripts/gitlabHelper.js
src/scripts/scrumHelper.js
Update documentation to reflect multi-platform support and roadmap.
  • Document GitLab support and upcoming Gitea and analytics-related features in the README feature list and roadmap section.
README.md

Assessment against linked issues

Issue Objective Addressed Explanation
#546 Apply the existing escapeHtml() function to all API-sourced strings used in PR/MR rendering in scrumHelper.js (including project, title, html_url, and commit.messageHeadline in draft, open, closed, merged, and GitLab MR paths, as well as reviewed PR titles).
#546 Apply the existing escapeHtml() function to all API-sourced strings used in issue rendering in scrumHelper.js (including project, title, and html_url for next-week and all issue states).
#546 Ensure no remaining direct insertion of unescaped GitHub/GitLab API data into HTML in the scrum report rendering logic of scrumHelper.js at the locations called out in the issue.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The new githubCommitsData variable is only used for GitLab commits; consider renaming it (and related mapping keys) to a platform-agnostic name like gitlabCommitsData or allCommitsData to avoid confusion.
  • When building anchor tags, html_url is passed through escapeHtml but still used as an href; you may want to additionally validate or normalize these URLs (e.g., ensuring http/https schemes) to reduce the risk of unsafe or broken links being rendered.
  • The GitLab commits fetch loop makes sequential requests with a fixed setTimeout delay per project; for users with many projects this could be slow—consider batching or limited parallelism with a simple concurrency/rate-limit control instead of strictly serializing all calls.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new `githubCommitsData` variable is only used for GitLab commits; consider renaming it (and related mapping keys) to a platform-agnostic name like `gitlabCommitsData` or `allCommitsData` to avoid confusion.
- When building anchor tags, `html_url` is passed through `escapeHtml` but still used as an href; you may want to additionally validate or normalize these URLs (e.g., ensuring http/https schemes) to reduce the risk of unsafe or broken links being rendered.
- The GitLab commits fetch loop makes sequential requests with a fixed `setTimeout` delay per project; for users with many projects this could be slow—consider batching or limited parallelism with a simple concurrency/rate-limit control instead of strictly serializing all calls.

## Individual Comments

### Comment 1
<location path="src/scripts/gitlabHelper.js" line_range="174-183" />
<code_context>
+			// Fetch commits from each project
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Per-project commit fetching is sequential and limited to 100 items, which may be slow and can miss commits for active projects.

The per-project loop fetches only a single page (`per_page=100`) with an added 100ms delay. This can (a) silently miss commits for very active projects due to missing pagination, and (b) be slow for users with many projects. Please either add pagination support (e.g., follow `X-Next-Page` or equivalent) or explicitly enforce and document the 100-commit limit in code. You could also improve throughput by batching, reducing the delay, limiting the queried projects, or running a bounded number of requests in parallel instead of fully sequentially.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +174 to +183
// Fetch commits from each project
let allCommits = [];
for (const project of allProjects) {
try {
const projectCommitsUrl = `${this.baseUrl}/projects/${project.id}/repository/commits?author_name=${username}&since=${startDate}T00:00:00Z&until=${endDate}T23:59:59Z&per_page=100&order_by=committed_date&sort=desc`;
const projectCommitsRes = await fetch(projectCommitsUrl, { headers });
if (projectCommitsRes.ok) {
const projectCommits = await projectCommitsRes.json();
allCommits = allCommits.concat(
projectCommits.map((commit) => ({
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.

suggestion (bug_risk): Per-project commit fetching is sequential and limited to 100 items, which may be slow and can miss commits for active projects.

The per-project loop fetches only a single page (per_page=100) with an added 100ms delay. This can (a) silently miss commits for very active projects due to missing pagination, and (b) be slow for users with many projects. Please either add pagination support (e.g., follow X-Next-Page or equivalent) or explicitly enforce and document the 100-commit limit in code. You could also improve throughput by batching, reducing the delay, limiting the queried projects, or running a bounded number of requests in parallel instead of fully sequentially.

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

Labels

config core documentation javascript Pull requests that update javascript code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Security] XSS vulnerability in scrumHelper.js: escapeHtml() exists but is never applied to API-sourced data in report rendering

1 participant