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
- Pass
href="javascript:alert(1)" to <Anchor> in a local dev build. Confirm no <a> with that href appears in the rendered HTML.
- Pass
href="data:text/html,<script>alert(1)</script>". Confirm same outcome.
- Pass
href="https://example.com". Confirm a normal <a href="https://example.com"> is rendered and the link is clickable.
- Pass
href="http://example.com". Confirm it also renders correctly (HTTP links are valid).
- 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://.
Why
The
Anchorcomponent renders any string it receives as anhrefwith no protocol check, so ajavascript:ordata:URI sourced fromtutorials.ymlor the GitHub API can execute arbitrary JavaScript in a visitor's browser the moment they click the link.Current state
src/components/Anchor.tsxlines 12–18 render<a href={href} ...>wherehrefis typed asstringwith 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
Anchorrejects anyhrefthat does not begin withhttps://orhttp://— the link is not rendered (or is rendered as plain text) for any other scheme.javascript:,data:,vbscript:, or scheme-relative URI passed ashrefnever reaches the DOM as a clickable anchor.Anchor.tsxso every caller benefits automatically, regardless of upstream data source.Out of scope
Starting points
src/components/Anchor.tsx— lines 12–18, the rendered<a>element.src/components/Tutorial.tsx— primary caller, passestutorial.link.src/components/Contributors.tsx— secondary caller, passescontributor.html_url.QA plan
href="javascript:alert(1)"to<Anchor>in a local dev build. Confirm no<a>with that href appears in the rendered HTML.href="data:text/html,<script>alert(1)</script>". Confirm same outcome.href="https://example.com". Confirm a normal<a href="https://example.com">is rendered and the link is clickable.href="http://example.com". Confirm it also renders correctly (HTTP links are valid).gatsby buildwith a YAML entry whose link isjavascript:alert(1). Confirm the built HTML contains no such href.Done when
Anchordoes not render an<a>tag (or renders a safe fallback) for anyhrefvalue whose scheme is nothttps://orhttp://.