Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6f9ee62

Browse files
authored
fix(auth): validate Origin header against APPSMITH_BASE_URL (#41426)
## DescriptionPrevent account takeover by validating Origin header in password resetand email verification endpoints against configured APPSMITH_BASE_URL.- Add validateBaseUrl() helper to check Origin matches APPSMITH_BASE_URL- Add APPSMITH_BASE_URL field to admin settings UI- Ensure backward compatibility when APPSMITH_BASE_URL is not setEE PR:appsmithorg/appsmith-ee#8448Fixeshttps://github.com/appsmithorg/appsmith/security/advisories/GHSA-7hf5-mc28-xmcv## Automation/ok-to-test tags="@tag.All"### 🔍 Cypress test results<!-- This is an auto-generated comment: Cypress test results -->> [!TIP]> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉> Workflow run:<https://github.com/appsmithorg/appsmith/actions/runs/19726406804>> Commit:3764386> <ahref="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=19726406804&attempt=1"target="_blank">Cypress dashboard</a>.> Tags: `@tag.All`> Spec:> <hr>Thu, 27 Nov 2025 07:03:50 UTC<!-- end of auto-generated comment: Cypress test results -->## CommunicationShould the DevRel and Marketing teams inform users about this change?- [ ] Yes- [ ] No<!-- This is an auto-generated comment: release notes by coderabbit.ai-->## Summary by CodeRabbit* **New Features*** Added Appsmith Base URL configuration setting in Admin Settings,enabling administrators to specify their instance's base URL.* **Bug Fixes*** Improved error handling and added URL validation in password reset andemail verification flows for enhanced security.<sub>✏️ Tip: You can customize this high-level summary in your reviewsettings.</sub><!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent9864994 commit6f9ee62

File tree

4 files changed

+69
-3
lines changed

4 files changed

+69
-3
lines changed

‎app/client/cypress/locators/AdminsSettings.js‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export default {
8080
smtpAppsmithMailUserNameInput:"[name='APPSMITH_MAIL_USERNAME']",
8181
smtpAppsmithMailPasswordInput:"[name='APPSMITH_MAIL_PASSWORD']",
8282
smtpAppsmithMailTestButton:"[data-testid='admin-settings-button']",
83+
appsmithBaseUrlInput:"[name='APPSMITH_BASE_URL']",
8384
addEmailGhostInput:
8485
"[data-testid='admin-settings-tag-input'] .bp3-input-ghost",
8586
// Static URL related locators

‎app/client/src/ce/pages/AdminSettings/config/configuration.tsx‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@ export const APPSMITH_REDIS_URL: Setting = {
3838
"* Appsmith internally uses Redis for session storage. Change this to an external redis for clustering",
3939
};
4040

41+
exportconstAPPSMITH_BASE_URL:Setting={
42+
id:"APPSMITH_BASE_URL",
43+
category:SettingCategories.CONFIGURATION,
44+
controlType:SettingTypes.TEXTINPUT,
45+
controlSubType:SettingSubtype.TEXT,
46+
label:"Appsmith Base URL",
47+
subText:
48+
"* The base URL where Appsmith is accessible. This is required for password reset and email verification links to work correctly.",
49+
placeholder:"https://appsmith.example.com",
50+
validate:(value:string)=>{
51+
if(!value||value.trim()===""){
52+
return"This field cannot be empty";
53+
}
54+
55+
if(!value.startsWith("http://")&&!value.startsWith("https://")){
56+
return"Base URL must start with http:// or https://";
57+
}
58+
},
59+
};
60+
4161
exportconstAPPSMITH_POOL_SIZE_CONFIG:Setting={
4262
id:"connectionMaxPoolSize",
4363
category:SettingCategories.CONFIGURATION,
@@ -136,6 +156,7 @@ export const config: AdminConfigType = {
136156
settings:[
137157
APPSMITH_DB_URL,
138158
APPSMITH_REDIS_URL,
159+
APPSMITH_BASE_URL,
139160
APPSMITH_POOL_SIZE_CONFIG,
140161
APPSMITH_ALLOWED_FRAME_ANCESTORS_SETTING,
141162
],

‎app/server/appsmith-server/src/main/java/com/appsmith/server/controllers/ce/UserControllerCE.java‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ public Mono<ResponseDTO<Boolean>> forgotPasswordRequest(
9595
// username scraping, where the response of this API can prove whether an email has an account or not.
9696
returnservice.forgotPasswordTokenGenerate(userPasswordDTO)
9797
.defaultIfEmpty(true)
98-
.onErrorReturn(true)
9998
.thenReturn(newResponseDTO<>(HttpStatus.OK,true));
10099
}
101100

‎app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserServiceCEImpl.java‎

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
importorg.apache.hc.core5.http.message.BasicNameValuePair;
4545
importorg.apache.hc.core5.net.WWWFormCodec;
4646
importorg.springframework.beans.factory.annotation.Autowired;
47+
importorg.springframework.beans.factory.annotation.Value;
4748
importorg.springframework.data.mongodb.core.query.UpdateDefinition;
4849
importorg.springframework.security.authentication.UsernamePasswordAuthenticationToken;
4950
importorg.springframework.security.core.Authentication;
@@ -108,6 +109,34 @@ public class UserServiceCEImpl extends BaseService<UserRepository, User, String>
108109
privatefinalUserServiceHelperuserPoliciesComputeHelper;
109110
privatefinalInstanceVariablesHelperinstanceVariablesHelper;
110111

112+
@Value("${APPSMITH_BASE_URL:}")
113+
privateStringappsmithBaseUrl;
114+
115+
/**
116+
* Validates that the provided base URL matches APPSMITH_BASE_URL if it is configured.
117+
* This prevents account takeover attacks by ensuring password reset and email verification
118+
* links are only sent to the configured base URL when APPSMITH_BASE_URL is set.
119+
* If APPSMITH_BASE_URL is not configured, validation is skipped to maintain backwards compatibility.
120+
*
121+
* @param providedBaseUrl The base URL from the request (typically from Origin header)
122+
* @return Mono that completes successfully if validation passes or is skipped, or errors if validation fails
123+
*/
124+
privateMono<Void>validateBaseUrl(StringprovidedBaseUrl) {
125+
// If APPSMITH_BASE_URL is not configured, skip validation for backwards compatibility
126+
if (!StringUtils.hasText(appsmithBaseUrl)) {
127+
returnMono.empty();
128+
}
129+
130+
// If APPSMITH_BASE_URL is configured, validate that Origin header matches it
131+
if (!appsmithBaseUrl.equals(providedBaseUrl)) {
132+
returnMono.error(newAppsmithException(
133+
AppsmithError.GENERIC_BAD_REQUEST,
134+
"Origin header does not match APPSMITH_BASE_URL configuration."));
135+
}
136+
137+
returnMono.empty();
138+
}
139+
111140
protectedstaticfinalWebFilterChainEMPTY_WEB_FILTER_CHAIN =serverWebExchange ->Mono.empty();
112141
privatestaticfinalStringFORGOT_PASSWORD_CLIENT_URL_FORMAT ="%s/user/resetPassword?token=%s";
113142
privatestaticfinalPatternALLOWED_ACCENTED_CHARACTERS_PATTERN =Pattern.compile("^[\\p{L} 0-9 .\'\\-]+$");
@@ -188,7 +217,15 @@ public Mono<Boolean> forgotPasswordTokenGenerate(ResetUserPasswordDTO resetUserP
188217
returnMono.error(newAppsmithException(AppsmithError.INVALID_PARAMETER,FieldName.ORIGIN));
189218
}
190219

191-
Stringemail =resetUserPasswordDTO.getEmail();
220+
// Validate Origin header against APPSMITH_BASE_URL
221+
returnvalidateBaseUrl(resetUserPasswordDTO.getBaseUrl()).then(Mono.defer(() -> {
222+
Stringemail =resetUserPasswordDTO.getEmail();
223+
returnprocessForgotPasswordTokenGeneration(email,resetUserPasswordDTO);
224+
}));
225+
}
226+
227+
privateMono<Boolean>processForgotPasswordTokenGeneration(
228+
Stringemail,ResetUserPasswordDTOresetUserPasswordDTO) {
192229

193230
// Create a random token to be sent out.
194231
finalStringtoken =UUID.randomUUID().toString();
@@ -811,7 +848,15 @@ public Mono<Boolean> resendEmailVerification(
811848
returnMono.error(newAppsmithException(AppsmithError.INVALID_PARAMETER,FieldName.ORIGIN));
812849
}
813850

814-
Stringemail =resendEmailVerificationDTO.getEmail();
851+
// Validate Origin header against APPSMITH_BASE_URL
852+
returnvalidateBaseUrl(resendEmailVerificationDTO.getBaseUrl()).then(Mono.defer(() -> {
853+
Stringemail =resendEmailVerificationDTO.getEmail();
854+
returnprocessResendEmailVerification(email,resendEmailVerificationDTO,redirectUrl);
855+
}));
856+
}
857+
858+
privateMono<Boolean>processResendEmailVerification(
859+
Stringemail,ResendEmailVerificationDTOresendEmailVerificationDTO,StringredirectUrl) {
815860

816861
// Create a random token to be sent out.
817862
finalStringtoken =UUID.randomUUID().toString();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp