Skip to content

Validate href scheme in Anchor component — block javascript: and data: URIs #219

Description

@ooloth

Why

The Anchor component renders any string it receives as an href with no protocol check, so a javascript: or data: URI sourced from tutorials.yml or the GitHub API can execute arbitrary JavaScript in a visitor's browser the moment they click the link.

Current state

src/components/Anchor.tsx lines 12–18 render <a href={href} ...> where href is typed as string with no further constraints. The component is the final rendering layer shared by all link surfaces in the site; nothing upstream currently guarantees the value is a safe scheme.

Ideal state

  • Anchor rejects any href that does not begin with https:// or http:// — the link is not rendered (or is rendered as plain text) for any other scheme.
  • A javascript:, data:, vbscript:, or scheme-relative URI passed as href never reaches the DOM as a clickable anchor.
  • The validation is self-contained in Anchor.tsx so every caller benefits automatically, regardless of upstream data source.

Out of scope

  • Validating that the URL resolves to a reachable page (network check).
  • Upstream YAML or API validation — those are tracked separately; this is the last-line-of-defence guard at the component level.

Starting points

  • src/components/Anchor.tsx — lines 12–18, the rendered <a> element.
  • src/components/Tutorial.tsx — primary caller, passes tutorial.link.
  • src/components/Contributors.tsx — secondary caller, passes contributor.html_url.

QA plan

  1. Pass href="javascript:alert(1)" to <Anchor> in a local dev build. Confirm no <a> with that href appears in the rendered HTML.
  2. Pass href="data:text/html,<script>alert(1)</script>". Confirm same outcome.
  3. Pass href="https://example.com". Confirm a normal <a href="https://example.com"> is rendered and the link is clickable.
  4. Pass href="http://example.com". Confirm it also renders correctly (HTTP links are valid).
  5. Run gatsby build with a YAML entry whose link is javascript:alert(1). Confirm the built HTML contains no such href.

Done when

Anchor does not render an <a> tag (or renders a safe fallback) for any href value whose scheme is not https:// or http://.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions