Skip to content

fix(eco): Re-adds the Complete Installation button to integration config pages"#113076

Merged
GabeVillalobos merged 3 commits into
masterfrom
gv/fix_vercel_redirects_on_install
Apr 15, 2026
Merged

fix(eco): Re-adds the Complete Installation button to integration config pages"#113076
GabeVillalobos merged 3 commits into
masterfrom
gv/fix_vercel_redirects_on_install

Conversation

@GabeVillalobos

@GabeVillalobos GabeVillalobos commented Apr 15, 2026

Copy link
Copy Markdown
Member

Adds a missing "Next" button to our integration configuration pages, which appears to have been accidentally omitted in the ProjectMapper refactor in #110666

I've tested this using the Dev UI to ensure it completes installation as expected, and requires a single project mapping to be defined prior to allowing install.

Screenshot during testing

Screenshot 2026-04-14 at 5 13 16 PM

Mobile Screenshot:

image

Resolves ISWF-2405
Resolves #112345

@linear-code

linear-code Bot commented Apr 15, 2026

Copy link
Copy Markdown

@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Apr 15, 2026
@GabeVillalobos
GabeVillalobos requested a review from a team April 15, 2026 17:25
Comment thread static/app/components/backendJsonFormAdapter/projectMapperAdapter.tsx Outdated
Comment thread static/app/components/backendJsonFormAdapter/projectMapperAdapter.tsx Outdated
Comment thread static/app/components/backendJsonFormAdapter/projectMapperAdapter.spec.tsx Outdated
};

afterEach(() => {
window.history.replaceState({}, '', '/');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You also shouldn't need this anymore

const hasLinkedProjects = value.length > 0;

return (
<Flex align="center" justify="between" gap="md">

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to check what this looks like with a small window size to make sure the text and button still look right.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just updated the description with a new screenshot showing the mobile version. Looks like things wrap correctly.

@GabeVillalobos
GabeVillalobos marked this pull request as ready for review April 15, 2026 18:30
@GabeVillalobos
GabeVillalobos requested a review from a team as a code owner April 15, 2026 18:30
@GabeVillalobos
GabeVillalobos merged commit 483a7ee into master Apr 15, 2026
64 checks passed
@GabeVillalobos
GabeVillalobos deleted the gv/fix_vercel_redirects_on_install branch April 15, 2026 18:30
return null;
}

if (!nextUrl.startsWith(nextButton.allowedDomain)) {

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.

Bug: The startsWith() check for the next URL parameter is insufficient, creating an open redirect vulnerability. It allows redirects to attacker-controlled subdomains like https://vercel.com.evil.com.
Severity: HIGH

Suggested Fix

Parse the nextUrl using the URL constructor and perform an exact match on the hostname property against the allowed domain. For example: const parsedUrl = new URL(nextUrl); if (parsedUrl.hostname !== 'vercel.com') { ... }.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: static/app/components/backendJsonFormAdapter/projectMapperAdapter.tsx#L247

Potential issue: The code uses `nextUrl.startsWith(nextButton.allowedDomain)` to
validate a redirect URL from the `next` query parameter. This check is insufficient as
it allows redirects to attacker-controlled subdomains, such as
`https://vercel.com.evil.com`, because it only checks the beginning of the string. An
attacker could craft a phishing link with a malicious `next` parameter, causing users
who click the "Complete on Vercel" button to be redirected to an attacker's site,
creating an open redirect vulnerability.

Did we get this right? 👍 / 👎 to inform future reviews.

Comment on lines +259 to +269
priority="primary"
icon={<IconOpen />}
disabled={!hasLinkedProjects}
href={nextUrl}
tooltipProps={{
title: t('Please link at least one project to continue.'),
disabled: hasLinkedProjects,
}}
>
{nextButton.text}
</LinkButton>

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.

Bug: The LinkButton receives both disabled and href props. If the component doesn't remove the href when disabled, users can still navigate to the link, bypassing the restriction.
Severity: MEDIUM

Suggested Fix

Conditionally render the href prop so it is undefined when the button is disabled. Alternatively, switch to using the internal LinkButton component which is known to handle this case correctly by removing the href when disabled.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location:
static/app/components/backendJsonFormAdapter/projectMapperAdapter.tsx#L257-L269

Potential issue: The `LinkButton` component from the external `@sentry/scraps/button`
package is passed both an `href` and a `disabled` prop. It is uncertain whether this
external component removes the `href` attribute when the button is disabled. If it does
not, a user could bypass the disabled state by right-clicking the button and selecting
"Open in new tab", allowing them to navigate to the URL when they should not be able to.
The associated tests do not verify that the `href` is absent when the button is
disabled.

Did we get this right? 👍 / 👎 to inform future reviews.

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 9edec79. Configure here.

return null;
}

if (!nextUrl.startsWith(nextButton.allowedDomain)) {

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.

Domain validation bypassable via subdomain prefix matching

High Severity

The startsWith check for allowedDomain validation can be bypassed. If allowedDomain is https://vercel.com, a URL like https://vercel.com.evil.com/phishing also passes the check, enabling an open redirect. The validation needs to ensure the character after the allowed domain is a path separator (/), query (?), fragment (#), port (:), or end of string — or better yet, compare the parsed URL's origin against the allowed domain.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9edec79. Configure here.

@github-actions github-actions Bot locked and limited conversation to collaborators May 1, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to complete Vercel integration installation.

2 participants