mirror of
https://github.com/Athou/commafeed.git
synced 2026-11-03 19:05:03 +00:00
escape username in password recovery email
This commit is contained in:
@@ -35,6 +35,7 @@ import com.commafeed.frontend.model.request.RegistrationRequest;
|
|||||||
import com.commafeed.security.AuthenticationContext;
|
import com.commafeed.security.AuthenticationContext;
|
||||||
import com.commafeed.security.Roles;
|
import com.commafeed.security.Roles;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.html.HtmlEscapers;
|
||||||
|
|
||||||
import jakarta.annotation.security.PermitAll;
|
import jakarta.annotation.security.PermitAll;
|
||||||
import jakarta.annotation.security.RolesAllowed;
|
import jakarta.annotation.security.RolesAllowed;
|
||||||
@@ -412,7 +413,7 @@ public class UserREST {
|
|||||||
Urls.removeTrailingSlash(config.passwordRecoveryPublicBaseUrl().orElseThrow());
|
Urls.removeTrailingSlash(config.passwordRecoveryPublicBaseUrl().orElseThrow());
|
||||||
return String.format(
|
return String.format(
|
||||||
"You asked for password recovery for account '%s', <a href='%s'>follow this link</a> to change your password. Ignore this if you didn't request a password recovery.",
|
"You asked for password recovery for account '%s', <a href='%s'>follow this link</a> to change your password. Ignore this if you didn't request a password recovery.",
|
||||||
user.getName(), callbackUrl(user, publicUrl));
|
HtmlEscapers.htmlEscaper().escape(user.getName()), callbackUrl(user, publicUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String callbackUrl(User user, String publicUrl) throws URISyntaxException {
|
private String callbackUrl(User user, String publicUrl) throws URISyntaxException {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.commafeed.TestConstants;
|
|||||||
import com.commafeed.frontend.model.Settings;
|
import com.commafeed.frontend.model.Settings;
|
||||||
import com.commafeed.frontend.model.request.PasswordResetConfirmationRequest;
|
import com.commafeed.frontend.model.request.PasswordResetConfirmationRequest;
|
||||||
import com.commafeed.frontend.model.request.PasswordResetRequest;
|
import com.commafeed.frontend.model.request.PasswordResetRequest;
|
||||||
|
import com.commafeed.frontend.model.request.RegistrationRequest;
|
||||||
import com.commafeed.integration.BaseIT;
|
import com.commafeed.integration.BaseIT;
|
||||||
|
|
||||||
import io.quarkus.mailer.MockMailbox;
|
import io.quarkus.mailer.MockMailbox;
|
||||||
@@ -17,6 +18,7 @@ import jakarta.ws.rs.core.HttpHeaders;
|
|||||||
|
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Element;
|
import org.jsoup.nodes.Element;
|
||||||
|
import org.jsoup.select.Elements;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
@@ -119,6 +121,45 @@ class UserIT extends BaseIT {
|
|||||||
RestAssured.given().get("rest/user/settings").then().statusCode(200);
|
RestAssured.given().get("rest/user/settings").then().statusCode(200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void resetPasswordEscapesUsernameInEmail() {
|
||||||
|
String name = "<a href=//evil.example>CLICK</a>";
|
||||||
|
String email = "victim@commafeed.com";
|
||||||
|
|
||||||
|
RegistrationRequest registrationReq = new RegistrationRequest();
|
||||||
|
registrationReq.setName(name);
|
||||||
|
registrationReq.setPassword("MyPassword123!");
|
||||||
|
registrationReq.setEmail(email);
|
||||||
|
RestAssured.given()
|
||||||
|
.body(registrationReq)
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.post("rest/user/register")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
|
||||||
|
PasswordResetRequest req = new PasswordResetRequest();
|
||||||
|
req.setEmail(email);
|
||||||
|
RestAssured.given()
|
||||||
|
.body(req)
|
||||||
|
.contentType(ContentType.JSON)
|
||||||
|
.post("rest/user/passwordReset")
|
||||||
|
.then()
|
||||||
|
.statusCode(200);
|
||||||
|
|
||||||
|
List<MailMessage> mails = mailbox.getMailMessagesSentTo(email);
|
||||||
|
Assertions.assertEquals(1, mails.size());
|
||||||
|
|
||||||
|
String html = mails.getFirst().getHtml();
|
||||||
|
Assertions.assertTrue(
|
||||||
|
html.startsWith(
|
||||||
|
"You asked for password recovery for account '<a href=//evil.example>CLICK</a>'"));
|
||||||
|
|
||||||
|
Elements links = Jsoup.parse(html).select("a");
|
||||||
|
Assertions.assertEquals(1, links.size());
|
||||||
|
Assertions.assertTrue(
|
||||||
|
links.getFirst().attr("href").startsWith("https://commafeed.example.com"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void saveSettings() {
|
void saveSettings() {
|
||||||
Settings settings =
|
Settings settings =
|
||||||
|
|||||||
Reference in New Issue
Block a user