fix: open coder_app links in new tab when open_in is tab#23000
Merged
fix: open coder_app links in new tab when open_in is tab#23000
Conversation
|
All contributors have signed the CLA ✍️ ✅ |
1a53985 to
dc17261
Compare
6e2e79c to
0645839
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes workspace app link behavior so that coder_app.open_in = "tab" opens the app in a new browser tab (instead of navigating the current tab), aligning with expected UX and improving safety for _blank links.
Changes:
- Add
target="_blank"andrel="noopener noreferrer"toAppLinkanchors whenapp.open_in === "tab". - Add Vitest regression coverage asserting correct
target/relbehavior foropen_in="tab"vsopen_in="slim-window". - Document why
openAppInNewWindow()intentionally omits"noopener"inwindow.open()features.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
site/src/modules/resources/AppLink/AppLink.tsx |
Conditionally sets anchor target/rel when open_in is "tab" to open in a new tab safely. |
site/src/modules/resources/AppLink/AppLink.test.tsx |
Adds regression tests verifying anchor attributes for "tab" and absence for "slim-window". |
site/src/modules/apps/apps.ts |
Adds explanatory comment about omitting "noopener" in window.open() features for popup-block detection. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
When a coder_app resource sets open_in = "tab", clicking the app link now opens in a new browser tab instead of navigating in the same tab. The fix adds target="_blank" and rel="noopener noreferrer" inline on the anchor elements in AppLink.tsx, gated on app.open_in === "tab". This matches the codebase convention of co-locating target and rel at the render site rather than returning HTML attributes from the hook. noopener prevents tabnabbing — an opened page must not be able to redirect the Coder dashboard via window.opener, which is especially important for same-origin path-based apps that would otherwise have full DOM access. noreferrer suppresses the Referer header to avoid leaking workspace IDs to destination servers. A future enhancement could allow template admins to opt into sending the referrer via a coder_app setting, enabling feedback pages based on workspace context. Vitest tests are added in AppLink.test.tsx asserting target and rel are set correctly for open_in="tab", and absent for open_in="slim-window". The slim-window path uses window.open() in onClick rather than anchor attributes — adding "noopener" to window.open() features would cause it to always return null per the WHATWG spec, making popup-blocked detection impossible. The omission is intentional and documented in apps.ts. Fixes #18573
…out slim-window - Remove redundant <ProxyProvider> wrapper in test (renderWithAuth already provides one via RequireAuth) - Remove slim-window test case and apps.ts comment to be reviewed separately in a follow-up PR
0c8d4f8 to
f8213f2
Compare
aslilac
reviewed
Mar 16, 2026
Member
aslilac
left a comment
There was a problem hiding this comment.
sorry, I just realized I didn't actually submit this review on friday 🤦♀️
current browsers are expected to include the noopener behavior when noreferrer is set. ref: https://html.spec.whatwg.org/multipage/links.html#link-type-noreferrer Co-authored-by: Kayla はな <kayla@tree.camp>
aslilac
approved these changes
Mar 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #18573
Changes
When a
coder_appresource setsopen_in = "tab", clicking the app link now opens in a new browser tab instead of navigating in the same tab.target="_blank"andrel="noopener noreferrer"are set inline on the<a>elements inAppLink.tsx, gated onapp.open_in === "tab". This follows the codebase convention of co-locatingtargetandrelat the render site.noopenerprevents tabnabbing — without it, the opened page can redirect the Coder dashboard tab viawindow.opener. This is especially relevant for same-origin path-based apps, which would otherwise have full DOM access to the dashboard.noreferrersuppresses the Referer header to avoid leaking workspace IDs to destination servers.Tests
A vitest case is added in
AppLink.test.tsx(rather than a Storybook story, since the assertions are purely behavioral with no visual component):sets target=_blank and rel=noopener noreferrer when open_in is tab— renders the app link withopen_in: "tab"and assertstarget="_blank"andrel="noopener noreferrer"are present on the anchor.Slim-window behavior
The
slim-windowtest case and theopenAppInNewWindow()comment inapps.tshave been split out into a follow-up PR for separate review, since thewindow.open()/noopenertradeoffs there deserve dedicated discussion.