Skip to content

fix(frontend): add rel=noopener noreferrer to target=_blank links#2505

Merged
malinskibeniamin merged 2 commits into
masterfrom
ben/fix-external-link-rel
Jun 15, 2026
Merged

fix(frontend): add rel=noopener noreferrer to target=_blank links#2505
malinskibeniamin merged 2 commits into
masterfrom
ben/fix-external-link-rel

Conversation

@malinskibeniamin

Copy link
Copy Markdown
Contributor

What & why

Audit finding SECURITY-03. Links opened with target="_blank" but no rel
expose reverse-tabnabbing (the opened page can drive window.opener to a
phishing URL) and referrer leakage. Practical risk is low here (destinations are
the trusted docs.redpanda.com domain and modern browsers imply noopener), but
it's a latent footgun the moment a target="_blank" href becomes dynamic.

Change

Added rel="noopener noreferrer" to the 16 external-link sites (custom
Link / UILink / router-link components) across 8 files that were missing it.

Native <a target="_blank"> are already covered by biome's recommended
noBlankTarget rule — but that rule only inspects native anchors, so the registry
Link/UILink consumers needed explicit rel. The vendor registry component
(redpanda-ui/.../auto-form/field-wrapper.tsx) was left untouched (it already had
rel anyway).

Verification

  • bun run type:check
  • bun run lint:check
  • Independent sweep: 0 target="_blank" elements remain without a rel (excluding vendor/generated).

Follow-up (not in this PR)

Biome's noBlankTarget can't enforce rel on custom components. A small custom lint
rule (or defaulting rel in the upstream registry Link) would prevent regressions —
tracked separately.

🤖 Generated with Claude Code

External links opened with target="_blank" but no rel exposed reverse-tabnabbing
(window.opener) and referrer leakage. Add rel="noopener noreferrer" to the custom
Link/UILink/router-link sites that biome's noBlankTarget rule (native <a> only)
can't reach. Vendor redpanda-ui components left untouched (audit SECURITY-03).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@malinskibeniamin

Copy link
Copy Markdown
Contributor Author

@claude review

@github-actions

github-actions Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Claude finished @malinskibeniamin's task in 1m 59s —— View job


Review: fix(frontend): add rel=noopener noreferrer to target=_blank links

  • Read the diff against origin/master
  • Verify every target="_blank" site got a rel
  • Check for remaining unprotected sites
  • Verify the rel prop actually reaches the DOM anchor

Verdict: LGTM ✅ — clean, correct, low-risk security hygiene. The fix is real (not cosmetic) and the "0 remain" claim checks out.


What I verified

1. The rel prop is actually forwarded to the rendered <a> (the failure mode that would have made this a no-op).

  • Link / UILink resolve to the registry component in redpanda-ui/components/typography.tsx. The anchor branch spreads {...props} onto <a> (typography.tsx:287) and its prop type includes React.AnchorHTMLAttributes, so rel is valid and lands on the DOM node. ✅
  • TanStackRouterLink forwards arbitrary anchor attributes (incl. rel) to the rendered anchor. ✅

2. No remaining unprotected sites. Ran independent multiline sweeps across frontend/src:

  • Native <a target="_blank"> without rel0 matches
  • Component links (<Link>/<UILink>/<TanStackRouterLink>/<Button as="a">) with target="_blank" and no rel0 matches
  • Vendor auto-form/field-wrapper.tsx:162 already has rel="noreferrer" and was correctly left untouched. ✅

3. Edits are additive-only — purely new valid attributes, no behavior change. Destinations are docs.redpanda.com, so the added noreferrer won't break referrer-dependent analytics.


Notes (non-blocking)

  • Consistency: new sites use rel="noopener noreferrer" while some pre-existing sites use just rel="noreferrer". Both are safe (noreferrer implies noopener per spec); the explicit form here is the more defensive choice. No action needed.
  • The follow-up is the better long-term fix. Rather than annotating each call site, defaulting rel inside the registry Link when target="_blank" (around typography.tsx:286-290) would make all Link/UILink consumers safe automatically and prevent regressions that a linter can't catch on custom components. Worth tracking as the PR body already suggests. Default rel on the registry Link →

I did not run type:check/lint here, but the changes are trivially valid TS (additive string attributes) and the author reports both pass.
· branch ben/fix-external-link-rel

biome's formatter wraps the Link/UILink tags that exceeded line width after the
rel="noopener noreferrer" addition. No semantic change (CI 'bun run lint' output).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@malinskibeniamin malinskibeniamin requested a review from Mateoc June 13, 2026 18:01
@malinskibeniamin

Copy link
Copy Markdown
Contributor Author

Thanks for the review. No code change needed here:

  • Consistency (noopener noreferrer vs noreferrer) — both are safe (noreferrer implies noopener); leaving the explicit form. No action, as noted.
  • Registry default rel — agreed that's the better long-term fix, but it lives in the CLI-installed vendor component (redpanda-ui/.../typography.tsx), so it belongs upstream in the registry repo rather than a local edit here. Tracked as the follow-up in the PR description.

The "0 unprotected target="_blank" sites" claim was re-verified independently. CI is green.

@malinskibeniamin malinskibeniamin merged commit 0fc0cbb into master Jun 15, 2026
17 checks passed
@malinskibeniamin malinskibeniamin deleted the ben/fix-external-link-rel branch June 15, 2026 11:47
themkarimi pushed a commit to themkarimi/console that referenced this pull request Jun 19, 2026
…dpanda-data#2505)

* fix(frontend): add rel=noopener noreferrer to target=_blank links

External links opened with target="_blank" but no rel exposed reverse-tabnabbing
(window.opener) and referrer leakage. Add rel="noopener noreferrer" to the custom
Link/UILink/router-link sites that biome's noBlankTarget rule (native <a> only)
can't reach. Vendor redpanda-ui components left untouched (audit SECURITY-03).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* style(frontend): wrap long external-link tags to satisfy formatter

biome's formatter wraps the Link/UILink tags that exceeded line width after the
rel="noopener noreferrer" addition. No semantic change (CI 'bun run lint' output).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

frontend lang/ts TypeScript/JavaScript ui/ux

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants