java.lang.security.audit.cookie-missing-httponly.cookie-missing-httponly
Community Favorite
semgrep
Author
73,396
Download Count*
License
A cookie was detected without setting the 'HttpOnly' flag. The 'HttpOnly' flag for cookies instructs the browser to forbid client-side scripts from reading the cookie. Set the 'HttpOnly' flag by calling 'cookie.setHttpOnly(true);'
Run Locally
Run in CI
Defintion
rules:
- id: cookie-missing-httponly
metadata:
cwe:
- "CWE-1004: Sensitive Cookie Without 'HttpOnly' Flag"
owasp:
- A05:2021 - Security Misconfiguration
source-rule-url: https://find-sec-bugs.github.io/bugs.htm#HTTPONLY_COOKIE
asvs:
section: "V3: Session Management Verification Requirements"
control_id: 3.4.2 Missing Cookie Attribute
control_url: https://github.com/OWASP/ASVS/blob/master/4.0/en/0x12-V3-Session-management.md#v34-cookie-based-session-management
version: "4"
category: security
technology:
- java
references:
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration
subcategory:
- audit
likelihood: LOW
impact: LOW
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Cookie Security
message: A cookie was detected without setting the 'HttpOnly' flag. The
'HttpOnly' flag for cookies instructs the browser to forbid client-side
scripts from reading the cookie. Set the 'HttpOnly' flag by calling
'cookie.setHttpOnly(true);'
severity: WARNING
languages:
- java
patterns:
- pattern-not-inside: $COOKIE.setValue(""); ...
- pattern-either:
- pattern: $COOKIE.setHttpOnly(false);
- patterns:
- pattern-not-inside: $COOKIE.setHttpOnly(...); ...
- pattern-not-inside: $COOKIE = ResponseCookie.from(...). ...; ...
- pattern: $RESPONSE.addCookie($COOKIE);
Examples
cookie-missing-httponly.java
@Controller
public class CookieController {
@RequestMapping(value = "/cookie1", method = "GET")
public void setCookie(@RequestParam String value, HttpServletResponse response) {
Cookie cookie = new Cookie("cookie", value);
// ruleid: cookie-missing-httponly
response.addCookie(cookie);
}
@RequestMapping(value = "/cookie2", method = "GET")
public void setSecureCookie(@RequestParam String value, HttpServletResponse response) {
Cookie cookie = new Cookie("cookie", value);
cookie.setSecure(true);
// ruleid: cookie-missing-httponly
response.addCookie(cookie);
}
@RequestMapping(value = "/cookie3", method = "GET")
public void setSecureHttponlyCookie(@RequestParam String value, HttpServletResponse response) {
Cookie cookie = new Cookie("cookie", value);
cookie.setSecure(true);
cookie.setHttpOnly(true);
// ok: cookie-missing-httponly
response.addCookie(cookie);
}
@RequestMapping(value = "/cookie4", method = "GET")
public void explicitDisable(@RequestParam String value, HttpServletResponse response) {
Cookie cookie = new Cookie("cookie", value);
cookie.setSecure(false);
// ruleid:cookie-missing-httponly
cookie.setHttpOnly(false);
response.addCookie(cookie);
}
@RequestMapping(value = "/cookie5", method = "GET")
public void explicitDisable(@RequestParam String value, HttpServletResponse response) {
// ignore cookies created by Spring's ResponseCookie builder, since the interface is different
Cookie cookie = ResponseCookie.from("name", "value").build();
// ok:cookie-missing-httponly
response.addCookie(cookie);
}
// test case cf. https://github.com/Dreampie/Resty/blob/9ef059c065d1894c79e7d69c150e588a61eb1cd5/resty-common/src/main/java/cn/dreampie/common/http/HttpResponse.java#L69
public Response addCookie(String name, String value, int expiration, boolean httpOnly) {
Cookie existingCookie = HttpRequest.getCookie(request.getCookies(), name);
if (existingCookie != null) {
if (Constant.cookiePath.equals(existingCookie.getPath())
|| existingCookie.getPath() == null // in some cases cookies set on path '/' are returned with a null path
) {
// update existing cookie
existingCookie.setPath(Constant.cookiePath);
existingCookie.setValue(value);
existingCookie.setMaxAge(expiration);
if (Constant.cookieHttpOnly) {
setHttpOnly(existingCookie);
}
existingCookie.setSecure(Constant.cookieSecure);
if (Constant.cookieDomain != null) {
existingCookie.setDomain(Constant.cookieDomain);
}
// uses its own method to set httponly. will not detect
// ruleid: cookie-missing-httponly
response.addCookie(existingCookie);
} else {
// we have an existing cookie on another path: clear it, and add a new cookie on root path
existingCookie.setValue("");
existingCookie.setMaxAge(0);
// ok: cookie-missing-httponly
response.addCookie(existingCookie);
Cookie c = new Cookie(name, value);
c.setPath(Constant.cookiePath);
c.setMaxAge(expiration);
if (Constant.cookieHttpOnly) {
setHttpOnly(existingCookie);
}
c.setSecure(Constant.cookieSecure);
if (Constant.cookieDomain != null) {
c.setDomain(Constant.cookieDomain);
}
// uses its own method to set httponly. will not detect
// ruleid: cookie-missing-httponly
response.addCookie(c);
}
} else {
Cookie c = new Cookie(name, value);
c.setPath(Constant.cookiePath);
c.setMaxAge(expiration);
if (Constant.cookieHttpOnly) {
setHttpOnly(c);
}
c.setSecure(Constant.cookieSecure);
if (Constant.cookieDomain != null) {
c.setDomain(Constant.cookieDomain);
}
// uses its own method to set httponly. will not detect
// ruleid: cookie-missing-httponly
response.addCookie(c);
}
return this;
}
public Response clearCookie(String cookie) {
Cookie existingCookie = HttpRequest.getCookie(request.getCookies(), cookie);
if (existingCookie != null) {
existingCookie.setPath(Constant.cookiePath);
existingCookie.setValue("");
existingCookie.setMaxAge(0);
// ok: cookie-missing-httponly
response.addCookie(existingCookie);
}
return this;
}
}
Short Link: https://sg.run/b7Be