Skip to content

Reject javascript: and vbscript: URI schemes in href#4113

Merged
jonrohan merged 1 commit into
mainfrom
liuliu/reject-unsafe-href-schemes
Jun 30, 2026
Merged

Reject javascript: and vbscript: URI schemes in href#4113
jonrohan merged 1 commit into
mainfrom
liuliu/reject-unsafe-href-schemes

Conversation

@liuliu-dev

Copy link
Copy Markdown
Contributor

Closes https://github.com/github/primer/issues/6760

Summary

Defense in depth: rejects javascript: and vbscript: URI schemes in a component's href argument, applied centrally in Primer::BaseComponent. Covers every component that routes through BaseComponent (Label, Button, Link, action list items, action menus, etc.) when rendered as an anchor.

Scheme detection strips ASCII whitespace and control characters (\u0000\u0020) before matching, per the WHATWG URL spec, so bypasses like \tJaVaScRiPt: or j\u0000avascript: are caught too.

Behavior

  • Dev/test (raise_on_invalid_options = true): raises ArgumentError so misuse is caught early.
  • Production: silently sets href to nil so the anchor renders without an href attribute rather than crashing the request.
  • data: is intentionally not blocked.

Changes

Testing

  • bundle exec rake test — green across all affected files.
  • Manual verification in Lookbook: unsafe href renders without an href attribute and is inert on click; safe values are preserved.

@changeset-bot

changeset-bot Bot commented Jun 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 534698a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/view-components Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@joshblack

Copy link
Copy Markdown
Member

Just wanted to add @jonrohan on here too for this kind of change 👀

Copilot AI left a comment

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.

Pull request overview

This PR adds a defense-in-depth guardrail to prevent XSS via href values by centrally rejecting javascript: and vbscript: URI schemes when Primer components render as anchors.

Changes:

  • Introduces Primer::SafeHrefHelper to detect disallowed href schemes, including common whitespace/control-character bypasses.
  • Hooks sanitize_href! into Primer::BaseComponent initialization to raise in non-production when invalid options are enforced and otherwise neutralize by dropping the href.
  • Adds unit + component regression tests for both raising and neutralization paths, plus a changeset entry.
Show a summary per file
File Description
app/lib/primer/safe_href_helper.rb Adds scheme detection with normalization to catch control/whitespace bypasses.
app/components/primer/component.rb Adds sanitize_href! and wires it to the existing should_raise_error? behavior.
app/components/primer/base_component.rb Applies sanitize_href! centrally to validated system arguments.
test/lib/safe_href_helper_test.rb Unit tests for detection behavior and bypass cases.
test/components/base_component_test.rb Regression tests for raising vs neutralization and safe href allowance.
test/components/beta/label_test.rb Ensures label-as-anchor rejects/neutralizes unsafe href.
test/components/primer/beta/button_test.rb Ensures button-as-anchor rejects/neutralizes unsafe href.
.changeset/sanitize-href-uri-scheme.md Documents the patch-level behavior change for consumers.

Review details

  • Files reviewed: 8/8 changed files
  • Comments generated: 0
  • Review effort level: Low

@jonrohan jonrohan merged commit 7c52375 into main Jun 30, 2026
39 of 40 checks passed
@jonrohan jonrohan deleted the liuliu/reject-unsafe-href-schemes branch June 30, 2026 17:28
@primer primer Bot mentioned this pull request Jun 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants