SIGN IN SIGN UP
appsmithorg / appsmith UNCLAIMED

Platform to build admin panels, internal tools, and dashboards. Integrates with 25+ databases and any API.

0 0 68 TypeScript

fix(security): fail closed when APPSMITH_BASE_URL unset for token-bearing emails (GHSA-j9gf-vw2f-9hrw) (#41767)

## Summary

Companion to PR #41766 (the GHSA-j9gf-vw2f-9hrw fail-closed fix).

Adds a non-dismissible top-of-screen banner shown only to instance
super-users when `APPSMITH_BASE_URL` is unset and the resolver is
therefore in fail-closed mode for token-bearing email flows. Multi-org
EE deployments (e.g. Appsmith Cloud) **never** see the banner — verified
via the `license_multi_org_enabled` short-circuit in the EE resolver
override (shadow EE PR linked below).

The banner deep-links to Admin Settings → Configuration where
`APPSMITH_BASE_URL` is the registered field. Saving via the existing
Configuration-tier admin-settings flow restarts the server, the SPA
auto-reloads, the resolver re-reads the env, and the banner clears — no
re-login.

## Architecture

- **Server:** new reactive
`SecureBaseUrlResolverCE#isBaseUrlConfigurationHealthy()` exposes the
health signal. CE returns `true` iff `APPSMITH_BASE_URL` is set; EE
override (in shadow EE PR) returns `true` unconditionally when
`license_multi_org_enabled` is on. Wired into
`ConsolidatedAPIServiceCEImpl` alongside the existing org-config fetch
so it runs in parallel (no sequential cost). Result populates a new
transient boolean field `instanceBaseUrlConfigurationHealthy` on
`OrganizationConfigurationCE`.
- **Client:** new `BaseUrlMissingBanner.tsx` component renders via the
ADS `Banner` component (same pattern as `PageBannerMessage`). Selector
`getShouldShowBaseUrlMissingBanner` gates on `isSuperUser &&
adminSettingsVisible && instanceBaseUrlConfigurationHealthy === false`.
The explicit `=== false` (rather than `!value`) is the rolling-deploy
guard. Mounted inside `PageHeader.tsx` alongside the existing
license/trial banner.
- **Recovery loop:** zero new code — leverages the existing
`RESTART_SERVER_POLL` → `window.location.reload()` flow that every
Configuration-tier admin setting already uses today.

Fixes
https://linear.app/appsmith/issue/APP-15046/security-high-configuration-dependent-origin-validation-bypass-in

## Test plan

- [x] `SecureBaseUrlResolverCEImplTest` — 2 new cases for
`isBaseUrlConfigurationHealthy()` (true when set, false when blank);
18/18 total pass
- [x] `usersSelectors.test.ts` — 6 new cases pinning all gating
dimensions plus the rolling-deploy `=== false` guard
- [x] `BaseUrlMissingBanner.test.tsx` — 5 new Jest cases covering all
gating dimensions
- [x] `ConsolidatedAPIServiceImplTest` — mock wired for resolver
- Cypress: skipped — CI sets `APPSMITH_BASE_URL=http://localhost`,
banner never fires by construction

## Companion / refs

- Shadow EE PR: https://github.com/appsmithorg/appsmith-ee/pull/9003
- Security advisory:
https://github.com/appsmithorg/appsmith/security/advisories/GHSA-j9gf-vw2f-9hrw
- Linear: APP-15046


## Automation
/ok-to-test tags="@tag.All"

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/25359958615>
> Commit: e9e92ce51fe8c3a39b7ca75bb51aa3330625c328
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=25359958615&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Tue, 05 May 2026 07:40:44 UTC
<!-- end of auto-generated comment: Cypress test results  -->
S
subratadeypappu committed
e498a7bb2ef084a1b07bdd153811a5194dc76824
Parent: 0d99237
Committed by GitHub <noreply@github.com> on 5/6/2026, 7:18:58 AM