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.Roles;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.html.HtmlEscapers;
|
||||
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
@@ -412,7 +413,7 @@ public class UserREST {
|
||||
Urls.removeTrailingSlash(config.passwordRecoveryPublicBaseUrl().orElseThrow());
|
||||
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.",
|
||||
user.getName(), callbackUrl(user, publicUrl));
|
||||
HtmlEscapers.htmlEscaper().escape(user.getName()), callbackUrl(user, publicUrl));
|
||||
}
|
||||
|
||||
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.request.PasswordResetConfirmationRequest;
|
||||
import com.commafeed.frontend.model.request.PasswordResetRequest;
|
||||
import com.commafeed.frontend.model.request.RegistrationRequest;
|
||||
import com.commafeed.integration.BaseIT;
|
||||
|
||||
import io.quarkus.mailer.MockMailbox;
|
||||
@@ -17,6 +18,7 @@ import jakarta.ws.rs.core.HttpHeaders;
|
||||
|
||||
import org.jsoup.Jsoup;
|
||||
import org.jsoup.nodes.Element;
|
||||
import org.jsoup.select.Elements;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
@@ -119,6 +121,45 @@ class UserIT extends BaseIT {
|
||||
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
|
||||
void saveSettings() {
|
||||
Settings settings =
|
||||
|
||||
Reference in New Issue
Block a user