Skip to content

Commit 09e820c

Browse files
joemahady-commcursoragent
authored andcommitted
Fix ZonePathContextRewritingFilter rewriting __Host- cookie paths
RFC 6265bis requires `__Host-` prefixed cookies to unconditionally have `Path=/`. The `ZonePathContextRewritingFilter` was incorrectly mutating the path of these cookies to the zone context path (e.g. `/auth`), causing browsers to reject them and resulting in CSRF token mismatch errors. This change updates the filter to exclude `__Host-` prefixed cookies from path rewriting, ensuring they retain their required `Path=/` attribute. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 0cbf5f6 commit 09e820c

2 files changed

Lines changed: 44 additions & 4 deletions

File tree

server/src/main/java/org/cloudfoundry/identity/uaa/zone/ZonePathContextRewritingFilter.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,9 @@ public void setHeader(String name, String value) {
316316
}
317317

318318
private boolean shouldRewritePath(String name, String path) {
319+
if (name != null && name.startsWith("__Host-")) {
320+
return false;
321+
}
319322
if (ignoreCookies.contains(name)) {
320323
return false;
321324
}
@@ -351,7 +354,7 @@ private String rewriteSetCookieHeaderValue(String headerValue) {
351354
return headerValue;
352355
}
353356
String cookieName = extractCookieNameFromSetCookieHeader(headerValue);
354-
if (cookieName != null && ignoreCookies.contains(cookieName)) {
357+
if (cookieName != null && (cookieName.startsWith("__Host-") || ignoreCookies.contains(cookieName))) {
355358
return headerValue;
356359
}
357360
String pathToUse = originalContextPath;

server/src/test/java/org/cloudfoundry/identity/uaa/zone/ZonePathContextRewritingFilterTests.java

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,23 @@ void cookieWithPathNull_whenZonePathRewritten_rewritesToOriginalContextPath() th
459459
assertThat(cookies[0].getPath()).isEqualTo("/uaa");
460460
}
461461

462+
@Test
463+
void addCookie_hostPrefixedCookie_leavesPathUnchanged() throws Exception {
464+
request.setContextPath("/uaa");
465+
request.setRequestURI("/uaa/z/myzone/login");
466+
467+
FilterChain chain = (_, res) -> {
468+
Cookie c = new Cookie("__Host-X-Uaa-Csrf", "v");
469+
c.setPath("/");
470+
((HttpServletResponse) res).addCookie(c);
471+
};
472+
filter.doFilter(request, response, chain);
473+
474+
Cookie[] cookies = response.getCookies();
475+
assertThat(cookies).hasSize(1);
476+
assertThat(cookies[0].getPath()).isEqualTo("/");
477+
}
478+
462479
@Test
463480
void noZonePath_withContextPath_rewritesCookiePathToContextPath() throws Exception {
464481
request.setContextPath("/uaa");
@@ -596,10 +613,26 @@ void addHeaderSetCookie_ignoredCookieName_leavesPathUnchanged() throws Exception
596613

597614
String header = response.getHeader("Set-Cookie");
598615
assertThat(header)
599-
.contains("Path=/")
616+
.contains("Path=/;")
617+
.doesNotContain("Path=/uaa")
600618
.contains("Current-User=");
601619
}
602620

621+
@Test
622+
void addHeaderSetCookie_hostPrefixedCookie_leavesPathUnchanged() throws Exception {
623+
request.setContextPath("/uaa");
624+
request.setRequestURI("/uaa/z/myzone/login");
625+
626+
FilterChain chain = (_, res) -> ((HttpServletResponse) res).addHeader("Set-Cookie", "__Host-X-Uaa-Csrf=encoded; Path=/; HttpOnly");
627+
filter.doFilter(request, response, chain);
628+
629+
String header = response.getHeader("Set-Cookie");
630+
assertThat(header)
631+
.contains("Path=/;")
632+
.doesNotContain("Path=/uaa")
633+
.contains("__Host-X-Uaa-Csrf=");
634+
}
635+
603636
@Test
604637
void setHeaderSetCookie_ignoredCookieName_leavesPathUnchanged() throws Exception {
605638
request.setContextPath("/uaa");
@@ -609,7 +642,9 @@ void setHeaderSetCookie_ignoredCookieName_leavesPathUnchanged() throws Exception
609642
filter.doFilter(request, response, chain);
610643

611644
String header = response.getHeader("Set-Cookie");
612-
assertThat(header).contains("Path=/");
645+
assertThat(header)
646+
.contains("Path=/")
647+
.doesNotContain("Path=/uaa");
613648
}
614649

615650
@Test
@@ -621,7 +656,9 @@ void addHeaderSetCookie_withPathSlash_whenNoContextPath_leavesPathSlash() throws
621656
filter.doFilter(request, response, chain);
622657

623658
String header = response.getHeader("Set-Cookie");
624-
assertThat(header).contains("Path=/");
659+
assertThat(header)
660+
.contains("Path=/")
661+
.doesNotContain("Path=/uaa");
625662
}
626663

627664
// --- zones.paths.enabled flag ---

0 commit comments

Comments
 (0)