github-advanced-security[bot] commented on code in PR #2900:
URL: https://github.com/apache/shiro/pull/2900#discussion_r4239202234
##########
support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupportCookies.java:
##########
@@ -46,41 +34,47 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@SuppressWarnings("HideUtilityClassConstructor")
public class FormResubmitSupportCookies {
- static final String DONT_ADD_ANY_MORE_COOKIES =
"org.apache.shiro.no-more-cookies";
+ private static final String HOST_PREFIX = "__Host-";
- static void addCookie(@NonNull HttpServletResponse response,
ServletContext servletContext,
- @NonNull String cookieName, @NonNull String cookieValue, int
maxAge, boolean httpOnly) {
- var cookie = new Cookie(cookieName, cookieValue);
- cookie.setPath(servletContext.getContextPath());
+ /**
+ * With secure cookies, the {@code __Host-} prefix makes browsers refuse
the cookie unless this very host
+ * set it over HTTPS, so it can't be planted from another subdomain or
over plain HTTP.
+ * The prefix requires {@code Path=/}, hence the context path moves into
the name, URL-encoded
+ * (cookie-name safe) to keep co-hosted applications apart.
+ */
+ static String cookieName(ServletContext servletContext, @NonNull String
baseName) {
+ return isFormResubmitSecureCookies(servletContext)
+ ? HOST_PREFIX + baseName +
URLEncoder.encode(servletContext.getContextPath(), StandardCharsets.UTF_8)
+ : baseName;
+ }
+
+ private static Cookie newCookie(ServletContext servletContext, String
baseName, String value, int maxAge,
+ boolean useHostPrefix) {
+ var cookie = new Cookie(useHostPrefix ? cookieName(servletContext,
baseName) : baseName, value);
+ boolean secure = useHostPrefix &&
isFormResubmitSecureCookies(servletContext);
+ cookie.setPath(secure ? "/" : servletContext.getContextPath());
+ cookie.setSecure(secure);
cookie.setMaxAge(maxAge);
- cookie.setHttpOnly(httpOnly);
- if
(EnvironmentLoaderListener.isFormResubmitSecureCookies(servletContext)) {
- cookie.setSecure(true);
- }
- response.addCookie(cookie);
+ return cookie;
}
+ /**
+ * @param cookieName base name, see {@link #cookieName}
+ */
static void addCookie(@NonNull HttpServletResponse response,
ServletContext servletContext,
- @NonNull String cookieName, @NonNull HttpCookie
inputCookie) {
- var cookie = new Cookie(cookieName, inputCookie.getValue());
- cookie.setPath(inputCookie.getPath() != null ? inputCookie.getPath() :
servletContext.getContextPath());
- cookie.setMaxAge(Math.toIntExact(inputCookie.getMaxAge()));
- cookie.setHttpOnly(inputCookie.isHttpOnly());
- if
(EnvironmentLoaderListener.isFormResubmitSecureCookies(servletContext)) {
- cookie.setSecure(true);
- }
+ @NonNull String cookieName, @NonNull String cookieValue, int
maxAge, boolean httpOnly) {
+ var cookie = newCookie(servletContext, cookieName, cookieValue,
maxAge, true);
+ cookie.setHttpOnly(httpOnly);
response.addCookie(cookie);
}
+ /**
+ * @param cookieName base name, see {@link #cookieName}
+ * @param useHostPrefix false for a plain-name, context-scoped cookie
regardless of the secure-cookie setting
+ */
static void deleteCookie(@NonNull HttpServletResponse response,
ServletContext servletContext,
- @NonNull String cookieName) {
- var cookieToDelete = new Cookie(cookieName, "tbd");
- cookieToDelete.setPath(servletContext.getContextPath());
- cookieToDelete.setMaxAge(0);
- if
(EnvironmentLoaderListener.isFormResubmitSecureCookies(servletContext)) {
- cookieToDelete.setSecure(true);
- }
- response.addCookie(cookieToDelete);
+ @NonNull String cookieName, boolean useHostPrefix) {
+ response.addCookie(newCookie(servletContext, cookieName, "tbd", 0,
useHostPrefix));
Review Comment:
## CodeQL / Sensitive cookies without the HttpOnly response header set
[This sensitive cookie](1) doesn't have the HttpOnly flag set.
[This sensitive cookie](2) doesn't have the HttpOnly flag set.
[This sensitive cookie](3) doesn't have the HttpOnly flag set.
[Show more
details](https://github.com/apache/shiro/security/code-scanning/59)
##########
support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/FormResubmitSupportCookiesTest.java:
##########
@@ -0,0 +1,118 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.shiro.ee.filters;
+
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletResponse;
+
+import static
org.apache.shiro.ee.filters.FormResubmitSupport.SHIRO_FORM_DATA_KEY;
+import static org.apache.shiro.ee.filters.FormResubmitSupportCookies.addCookie;
+import static
org.apache.shiro.ee.filters.FormResubmitSupportCookies.cookieName;
+import static
org.apache.shiro.ee.filters.FormResubmitSupportCookies.deleteCookie;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.apache.shiro.web.util.WebUtils;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.mockito.junit.jupiter.MockitoExtension;
+
+/**
+ * Secure saved-form cookies can't be planted by another host, since they are
host-prefixed
+ */
+@ExtendWith(MockitoExtension.class)
+class FormResubmitSupportCookiesTest {
+ private static final String SECURE_COOKIES =
"org.apache.shiro.form-resubmit.secure-cookies";
+ @Mock
+ private ServletContext servletContext;
+ @Mock
+ private HttpServletResponse response;
+
+ private Cookie added(boolean secure, String contextPath, int maxAge) {
+ when(servletContext.getAttribute(SECURE_COOKIES)).thenReturn(secure);
+ when(servletContext.getContextPath()).thenReturn(contextPath);
+ if (maxAge == 0) {
+ deleteCookie(response, servletContext, SHIRO_FORM_DATA_KEY, true);
+ } else {
+ addCookie(response, servletContext, SHIRO_FORM_DATA_KEY, "value",
maxAge, true);
+ }
+ var cookie = ArgumentCaptor.forClass(Cookie.class);
+ verify(response).addCookie(cookie.capture());
+ return cookie.getValue();
+ }
+
+ @Test
+ void secureCookieIsHostPrefixedAndRootScopedWithContextInName() {
+ var cookie = added(true, "/my-app", 1);
+ assertThat(cookie.getName()).isEqualTo("__Host-" + SHIRO_FORM_DATA_KEY
+ "%2Fmy-app");
+ assertThat(cookie.getPath()).isEqualTo("/");
+ assertThat(cookie.getSecure()).isTrue();
+ assertThat(cookie.isHttpOnly()).isTrue();
+ assertThat(cookie.getDomain()).isNull();
+ assertThat(cookie.getMaxAge()).isEqualTo(1);
+ }
+
+ @Test
+ void secureRootContextNeedsNoSuffix() {
+ assertThat(added(true, "", 1).getName()).isEqualTo("__Host-" +
SHIRO_FORM_DATA_KEY);
+ }
+
+ @Test
+ void insecureCookieKeepsLegacyNameAndContextPath() {
+ var cookie = added(false, "/my-app", 1);
+ assertThat(cookie.getName()).isEqualTo(SHIRO_FORM_DATA_KEY);
+ assertThat(cookie.getPath()).isEqualTo("/my-app");
+ assertThat(cookie.getSecure()).isFalse();
+ assertThat(cookie.isHttpOnly()).isTrue();
+ }
+
+ @Test
+ void deletionMatchesTheCookieItDeletes() {
+ var cookie = added(true, "/my-app", 0);
+ assertThat(cookie.getName()).isEqualTo(cookieName(servletContext,
SHIRO_FORM_DATA_KEY));
+ assertThat(cookie.getPath()).isEqualTo("/");
+ assertThat(cookie.getSecure()).isTrue();
+ assertThat(cookie.getMaxAge()).isZero();
+ }
+
+ @Test
+ void plainCookieDeletionDoesNotUseTheSecureConvention() {
+ when(servletContext.getContextPath()).thenReturn("/my-app");
+ deleteCookie(response, servletContext, WebUtils.SAVED_REQUEST_KEY,
false);
+ var cookies = ArgumentCaptor.forClass(Cookie.class);
+ verify(response).addCookie(cookies.capture());
Review Comment:
## CodeQL / Failure to use secure cookies
Cookie is added to response without the 'secure' flag being set.
[Show more
details](https://github.com/apache/shiro/security/code-scanning/61)
##########
support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/SavedFormDataTest.java:
##########
@@ -0,0 +1,131 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.shiro.ee.filters;
+
+import static org.apache.shiro.ee.filters.FormResubmitSupport.FORM_DATA_CACHE;
+import static
org.apache.shiro.ee.filters.FormResubmitSupport.SHIRO_FORM_DATA_KEY;
+import static
org.apache.shiro.ee.filters.FormResubmitSupport.getSavedFormDataKey;
+import static org.apache.shiro.ee.filters.FormResubmitSupport.hasSavedFormData;
+import static
org.apache.shiro.ee.filters.FormResubmitSupport.isFormDataDiscarded;
+import static org.apache.shiro.ee.filters.Forms.DISCARD_FORM_DATA_PARAMETER;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+import java.util.UUID;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.shiro.cache.MemoryConstrainedCacheManager;
+import org.apache.shiro.mgt.DefaultSecurityManager;
+import org.apache.shiro.util.ThreadContext;
+import org.apache.shiro.web.mgt.CookieRememberMeManager;
+import org.apache.shiro.web.util.WebUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.ArgumentCaptor;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+
+/**
+ * Login-page view of saved form data: whether any is waiting, and the user's
choice to discard it
+ */
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+class SavedFormDataTest {
+ @Mock
+ private HttpServletRequest request;
+ @Mock
+ private ServletContext servletContext;
+ @Mock
+ private HttpServletResponse response;
+ private final DefaultSecurityManager securityManager = new
DefaultSecurityManager();
+
+ @BeforeEach
+ void bindSecurityManager() {
+ when(request.getServletContext()).thenReturn(servletContext);
+ securityManager.setCacheManager(new MemoryConstrainedCacheManager());
+ ThreadContext.bind(securityManager);
+ }
+
+ @AfterEach
+ void unbindSecurityManager() {
+ ThreadContext.unbindSecurityManager();
+ }
+
+ private void savedFormDataCookie(String value) {
+ when(request.getCookies()).thenReturn(new Cookie[] {new
Cookie(SHIRO_FORM_DATA_KEY, value)});
+ }
+
+ @Test
+ void nothingSavedWithoutCookie() {
+ assertThat(getSavedFormDataKey(request)).isNull();
+ assertThat(hasSavedFormData(request)).isFalse();
+ }
+
+ @Test
+ void malformedCookieIsIgnored() {
+ savedFormDataCookie("not-a-uuid");
+ assertThat(getSavedFormDataKey(request)).isNull();
+ assertThat(hasSavedFormData(request)).isFalse();
+ }
+
+ @Test
+ void savedOnlyWhileFormDataIsCached() {
+ var key = UUID.randomUUID();
+ savedFormDataCookie(key.toString());
+ assertThat(getSavedFormDataKey(request)).isEqualTo(key);
+ assertThat(hasSavedFormData(request)).as("stale cookie").isFalse();
+ securityManager.getCacheManager().getCache(FORM_DATA_CACHE).put(key,
"firstName=Jack");
+ assertThat(hasSavedFormData(request)).isTrue();
+ }
+
+ @Test
+ void discardOnlyWhenAsked() {
+ assertThat(isFormDataDiscarded(request)).as("no checkbox").isFalse();
+
when(request.getParameter(DISCARD_FORM_DATA_PARAMETER)).thenReturn("on");
+ assertThat(isFormDataDiscarded(request)).as("checked
checkbox").isTrue();
+
when(request.getParameter(DISCARD_FORM_DATA_PARAMETER)).thenReturn("false");
+ assertThat(isFormDataDiscarded(request)).isFalse();
+ }
+
+ @Test
+ void savedRequestDeletionMatchesThePlainCookieEvenWithSecureFormCookies()
throws Exception {
+ securityManager.setRememberMeManager(new CookieRememberMeManager());
+
when(servletContext.getAttribute("org.apache.shiro.form-resubmit.secure-cookies")).thenReturn(Boolean.TRUE);
+ when(servletContext.getContextPath()).thenReturn("/myapp");
+ when(servletContext.getSessionTimeout()).thenReturn(1);
+ when(request.getContextPath()).thenReturn("/myapp");
+ when(request.getRequestURI()).thenReturn("/myapp/form");
+ FormResubmitSupport.saveRequest(request, response, false);
+ var cookies = ArgumentCaptor.forClass(Cookie.class);
+ verify(response).addCookie(cookies.capture());
Review Comment:
## CodeQL / Failure to use secure cookies
Cookie is added to response without the 'secure' flag being set.
[Show more
details](https://github.com/apache/shiro/security/code-scanning/62)
##########
support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupportCookies.java:
##########
@@ -46,41 +34,47 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@SuppressWarnings("HideUtilityClassConstructor")
public class FormResubmitSupportCookies {
- static final String DONT_ADD_ANY_MORE_COOKIES =
"org.apache.shiro.no-more-cookies";
+ private static final String HOST_PREFIX = "__Host-";
- static void addCookie(@NonNull HttpServletResponse response,
ServletContext servletContext,
- @NonNull String cookieName, @NonNull String cookieValue, int
maxAge, boolean httpOnly) {
- var cookie = new Cookie(cookieName, cookieValue);
- cookie.setPath(servletContext.getContextPath());
+ /**
+ * With secure cookies, the {@code __Host-} prefix makes browsers refuse
the cookie unless this very host
+ * set it over HTTPS, so it can't be planted from another subdomain or
over plain HTTP.
+ * The prefix requires {@code Path=/}, hence the context path moves into
the name, URL-encoded
+ * (cookie-name safe) to keep co-hosted applications apart.
+ */
+ static String cookieName(ServletContext servletContext, @NonNull String
baseName) {
+ return isFormResubmitSecureCookies(servletContext)
+ ? HOST_PREFIX + baseName +
URLEncoder.encode(servletContext.getContextPath(), StandardCharsets.UTF_8)
+ : baseName;
+ }
+
+ private static Cookie newCookie(ServletContext servletContext, String
baseName, String value, int maxAge,
+ boolean useHostPrefix) {
+ var cookie = new Cookie(useHostPrefix ? cookieName(servletContext,
baseName) : baseName, value);
+ boolean secure = useHostPrefix &&
isFormResubmitSecureCookies(servletContext);
+ cookie.setPath(secure ? "/" : servletContext.getContextPath());
+ cookie.setSecure(secure);
cookie.setMaxAge(maxAge);
- cookie.setHttpOnly(httpOnly);
- if
(EnvironmentLoaderListener.isFormResubmitSecureCookies(servletContext)) {
- cookie.setSecure(true);
- }
- response.addCookie(cookie);
+ return cookie;
}
+ /**
+ * @param cookieName base name, see {@link #cookieName}
+ */
static void addCookie(@NonNull HttpServletResponse response,
ServletContext servletContext,
- @NonNull String cookieName, @NonNull HttpCookie
inputCookie) {
- var cookie = new Cookie(cookieName, inputCookie.getValue());
- cookie.setPath(inputCookie.getPath() != null ? inputCookie.getPath() :
servletContext.getContextPath());
- cookie.setMaxAge(Math.toIntExact(inputCookie.getMaxAge()));
- cookie.setHttpOnly(inputCookie.isHttpOnly());
- if
(EnvironmentLoaderListener.isFormResubmitSecureCookies(servletContext)) {
- cookie.setSecure(true);
- }
+ @NonNull String cookieName, @NonNull String cookieValue, int
maxAge, boolean httpOnly) {
+ var cookie = newCookie(servletContext, cookieName, cookieValue,
maxAge, true);
+ cookie.setHttpOnly(httpOnly);
response.addCookie(cookie);
}
+ /**
+ * @param cookieName base name, see {@link #cookieName}
+ * @param useHostPrefix false for a plain-name, context-scoped cookie
regardless of the secure-cookie setting
+ */
static void deleteCookie(@NonNull HttpServletResponse response,
ServletContext servletContext,
- @NonNull String cookieName) {
- var cookieToDelete = new Cookie(cookieName, "tbd");
- cookieToDelete.setPath(servletContext.getContextPath());
- cookieToDelete.setMaxAge(0);
- if
(EnvironmentLoaderListener.isFormResubmitSecureCookies(servletContext)) {
- cookieToDelete.setSecure(true);
- }
- response.addCookie(cookieToDelete);
+ @NonNull String cookieName, boolean useHostPrefix) {
+ response.addCookie(newCookie(servletContext, cookieName, "tbd", 0,
useHostPrefix));
Review Comment:
## CodeQL / Failure to use secure cookies
Cookie is added to response without the 'secure' flag being set.
[Show more
details](https://github.com/apache/shiro/security/code-scanning/60)
##########
support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/SavedFormDataTest.java:
##########
@@ -0,0 +1,131 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.shiro.ee.filters;
+
+import static org.apache.shiro.ee.filters.FormResubmitSupport.FORM_DATA_CACHE;
+import static
org.apache.shiro.ee.filters.FormResubmitSupport.SHIRO_FORM_DATA_KEY;
+import static
org.apache.shiro.ee.filters.FormResubmitSupport.getSavedFormDataKey;
+import static org.apache.shiro.ee.filters.FormResubmitSupport.hasSavedFormData;
+import static
org.apache.shiro.ee.filters.FormResubmitSupport.isFormDataDiscarded;
+import static org.apache.shiro.ee.filters.Forms.DISCARD_FORM_DATA_PARAMETER;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.times;
+import java.util.UUID;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.Cookie;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.apache.shiro.cache.MemoryConstrainedCacheManager;
+import org.apache.shiro.mgt.DefaultSecurityManager;
+import org.apache.shiro.util.ThreadContext;
+import org.apache.shiro.web.mgt.CookieRememberMeManager;
+import org.apache.shiro.web.util.WebUtils;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.ArgumentCaptor;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+
+/**
+ * Login-page view of saved form data: whether any is waiting, and the user's
choice to discard it
+ */
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+class SavedFormDataTest {
+ @Mock
+ private HttpServletRequest request;
+ @Mock
+ private ServletContext servletContext;
+ @Mock
+ private HttpServletResponse response;
+ private final DefaultSecurityManager securityManager = new
DefaultSecurityManager();
+
+ @BeforeEach
+ void bindSecurityManager() {
+ when(request.getServletContext()).thenReturn(servletContext);
+ securityManager.setCacheManager(new MemoryConstrainedCacheManager());
+ ThreadContext.bind(securityManager);
+ }
+
+ @AfterEach
+ void unbindSecurityManager() {
+ ThreadContext.unbindSecurityManager();
+ }
+
+ private void savedFormDataCookie(String value) {
+ when(request.getCookies()).thenReturn(new Cookie[] {new
Cookie(SHIRO_FORM_DATA_KEY, value)});
+ }
+
+ @Test
+ void nothingSavedWithoutCookie() {
+ assertThat(getSavedFormDataKey(request)).isNull();
+ assertThat(hasSavedFormData(request)).isFalse();
+ }
+
+ @Test
+ void malformedCookieIsIgnored() {
+ savedFormDataCookie("not-a-uuid");
+ assertThat(getSavedFormDataKey(request)).isNull();
+ assertThat(hasSavedFormData(request)).isFalse();
+ }
+
+ @Test
+ void savedOnlyWhileFormDataIsCached() {
+ var key = UUID.randomUUID();
+ savedFormDataCookie(key.toString());
+ assertThat(getSavedFormDataKey(request)).isEqualTo(key);
+ assertThat(hasSavedFormData(request)).as("stale cookie").isFalse();
+ securityManager.getCacheManager().getCache(FORM_DATA_CACHE).put(key,
"firstName=Jack");
+ assertThat(hasSavedFormData(request)).isTrue();
+ }
+
+ @Test
+ void discardOnlyWhenAsked() {
+ assertThat(isFormDataDiscarded(request)).as("no checkbox").isFalse();
+
when(request.getParameter(DISCARD_FORM_DATA_PARAMETER)).thenReturn("on");
+ assertThat(isFormDataDiscarded(request)).as("checked
checkbox").isTrue();
+
when(request.getParameter(DISCARD_FORM_DATA_PARAMETER)).thenReturn("false");
+ assertThat(isFormDataDiscarded(request)).isFalse();
+ }
+
+ @Test
+ void savedRequestDeletionMatchesThePlainCookieEvenWithSecureFormCookies()
throws Exception {
+ securityManager.setRememberMeManager(new CookieRememberMeManager());
+
when(servletContext.getAttribute("org.apache.shiro.form-resubmit.secure-cookies")).thenReturn(Boolean.TRUE);
+ when(servletContext.getContextPath()).thenReturn("/myapp");
+ when(servletContext.getSessionTimeout()).thenReturn(1);
+ when(request.getContextPath()).thenReturn("/myapp");
+ when(request.getRequestURI()).thenReturn("/myapp/form");
+ FormResubmitSupport.saveRequest(request, response, false);
+ var cookies = ArgumentCaptor.forClass(Cookie.class);
+ verify(response).addCookie(cookies.capture());
+ Cookie saved = cookies.getValue();
+ when(request.getCookies()).thenReturn(new Cookie[] {saved});
+ FormResubmitSupport.redirectToSaved(request, response, (path, req) ->
false, "/", false);
+ verify(response, times(2)).addCookie(cookies.capture());
Review Comment:
## CodeQL / Failure to use secure cookies
Cookie is added to response without the 'secure' flag being set.
[Show more
details](https://github.com/apache/shiro/security/code-scanning/63)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]