How do I set Secure, HttpOnly and SameSite on my sign-in cookie?
If your sign-in cookie is missing Secure, HttpOnly or SameSite, add all three to the Set-Cookie header your server sends at sign-in, with SameSite set to Strict or Lax. Don't read a missing flag as proof that anyone's account was taken over.
What do Secure, HttpOnly and SameSite do?
If the credentials are correct, the server responds with a cookie containing a session ID that records the user's sign-in status. When the user moves to another page on the same site, the browser sends that cookie with the request to show it still thinks the user is signed in. A criminal who steals a session ID can use it to set a cookie that makes it look like they are signed in as someone else.
Secure. The Secure attribute tells browsers to send the cookie only through an encrypted HTTPS connection. Forcing HTTPS on your site does not protect the session ID if Secure isn't set, because the browser can be deceived into sending it over plain HTTP. Secure does not stop all access, since someone with access to the computer's hard disk, or JavaScript if HttpOnly isn't set, can still read and change the cookie.
HttpOnly. The HttpOnly attribute stops scripts from reading the cookie through document.cookie, which protects the session ID from theft through cross-site scripting (XSS). A cookie set with HttpOnly is still sent with requests your own JavaScript makes, such as fetch().
SameSite. SameSite controls whether browsers send the cookie with cross-site requests. SameSite=Strict leaves the cookie off cross-site requests, while SameSite=Lax allows it on top-level cross-site navigations that use safe HTTP methods. OWASP says to treat SameSite as defense in depth against cross-site request forgery (CSRF), not as a replacement for a CSRF token. If you set SameSite=None, you must also set Secure.
The OWASP session management cheat sheet recommends the __Host- prefix for session IDs. A cookie whose name starts with __Host- must be set with Secure from an HTTPS page, must have no Domain attribute and must use Path=/. OWASP's example of a session cookie with every protection in place looks like this:
Set-Cookie: __Host-SessionID=<value>; Secure; HttpOnly; SameSite=Strict; Path=/Which flags does my sign-in cookie need?
Find the row that matches your cookie.
| What you see | What to set | Why |
|---|---|---|
| Sign-in cookie has no Secure flag | Add Secure | Without Secure, the browser can be deceived into sending the session ID over plain HTTP. |
| Sign-in cookie has no HttpOnly flag | Add HttpOnly | Cookies that keep users signed in should have HttpOnly, because making them available to JavaScript is insecure. |
| Sign-in cookie has no SameSite attribute | Add SameSite=Strict, or SameSite=Lax | The browser default for SameSite varies across browsers and versions. |
Sign-in cookie has SameSite=None without Secure | Add Secure, or switch to Strict or Lax | SameSite=None requires a secure context. |
| Sign-in cookie must work when people follow a link from another site | Use SameSite=Lax | Lax permits top-level cross-site navigations that use safe HTTP methods. |
| Sign-in cookie is never needed on requests from other sites | Use SameSite=Strict | OWASP prefers Strict for session cookies. |
| Sign-in cookie has a Domain attribute set to your whole domain | Remove Domain and use the __Host- prefix | A too permissive Domain lets attackers go after session IDs across different hosts on the same domain. |
| Sign-in token is kept in localStorage or sessionStorage | Move it to an HttpOnly; Secure; SameSite=Strict cookie | Any JavaScript running on your origin can read localStorage and sessionStorage, so one XSS bug discloses every token. |
How do I check?
Sign in to your site, open your browser's developer tools and find the list of cookies for your site. Look at the cookie that holds your session and see whether Secure, HttpOnly and SameSite are set. Many apps also set a cookie before sign-in to track anonymous visitors, so look at those too.
To read the raw headers for Atlas, run this and look for any Set-Cookie line and the flags at its end:
curl -sI https://atlas.example/Lockpick reads what anyone online can see about your site, within fixed limits, and reports only what it saw. Lockpick never signs in to your site and never looks at anything behind a login, so check the cookie you get after signing in yourself. See the session cookie protections check and the cookie flags check for what each one looks at.
How do I fix it?
- Find where your app sets the sign-in cookie. Look in your sign-in route, your auth library's cookie settings and your host's config.
- Add
Secure,HttpOnlyandSameSite=Strictto that cookie. UseSameSite=Laxinstead only if people must stay signed in when they follow a link to your site from another site. - Remove the
Domainattribute, setPath=/and rename the cookie with the__Host-prefix. - Serve the site over HTTPS only. Insecure sites (http:) can't set cookies with the Secure attribute. On localhost the HTTPS rule for Secure is relaxed, although Safari doesn't support that exception.
- Issue a fresh session cookie every time someone signs in, even if one already exists. MDN says this helps prevent session fixation attacks, where a third party reuses a user's session.
- If your app keeps a session token in localStorage or sessionStorage, move it into an HttpOnly cookie that your server sets.
- If you can't change the app code, a web application firewall can add Secure and HttpOnly by rewriting the
Set-Cookieheader. - Sign out, sign back in and look at the cookie in your browser again.
Fix it with your AI
Paste the prompt for your builder. Read the diff before you accept it.
Find every place this app creates the cookie or token that keeps a user signed in. For each session cookie, set Secure, HttpOnly and SameSite=Strict, set Path=/ and remove any Domain attribute. Use SameSite=Lax only if users must stay signed in when they arrive from a link on another site, and tell me if you chose it. If the session token is stored in localStorage or sessionStorage, list each place and propose a change that keeps it in an HttpOnly cookie set by the server. Issue a new session cookie each time a user signs in. Change nothing else, and show me the diff before applying it.Search the project for every Set-Cookie header and every cookie set by the sign-in or session code. On the session cookie, add Secure, HttpOnly, SameSite=Strict and Path=/, remove the Domain attribute, and rename it with the __Host- prefix if nothing else depends on the old name. Never set SameSite=None on the session cookie. If any session token is written to localStorage or sessionStorage, list where and propose moving it to an HttpOnly cookie set by the server. Show me each change before applying it.Review how this app sets its session cookie. List every file that sets a cookie for sign-in or sessions, with the attributes it sets today. Then update the session cookie to use Secure, HttpOnly, SameSite=Strict and Path=/ with no Domain attribute, and the __Host- prefix on its name. Regenerate the session cookie on every successful sign-in. If tokens are kept in localStorage or sessionStorage, propose moving them into an HttpOnly cookie set by the server. Keep the change limited to cookie and session code and show me the diff.What a cookie check cannot tell you
Don't read a missing flag as proof that someone took over an account, and don't read a full set of flags as proof the session is safe. The HttpOnly flag only protects the cookie's confidentiality. If an XSS attack is combined with a CSRF attack, the requests it sends still carry the session cookie, because the browser always includes cookies with requests.
A Lockpick report says what each part of the scan could read, and marks anything it couldn't check as not checked, never as passed. A Lockpick report is not a certificate and not a full penetration test. It covers what that scan could see on that day.
Questions people ask
Is the Secure flag enough on its own?
Set HttpOnly and SameSite too. Secure keeps the cookie off unencrypted HTTP, but someone with access to the computer's hard disk, or JavaScript if HttpOnly isn't set, can still read and change it.
Should I use SameSite=Strict or SameSite=Lax?
OWASP says session cookies must set SameSite=Strict, which it prefers, or SameSite=Lax. Lax lets the cookie go with top-level cross-site navigations that use safe HTTP methods. Pick Lax if people must arrive from links on other sites already signed in, and Strict otherwise.
Will HttpOnly stop my own fetch calls from working?
A cookie set with HttpOnly is still sent with JavaScript-initiated requests, such as calls to fetch(). Your code can't read the cookie's value through document.cookie.
Does a session cookie disappear when the browser closes?
A cookie without an Expires or Max-Age attribute is a session cookie, and it's removed when the browser shuts down. Many browsers have a session restore feature that brings session cookies back, as if the browser was never closed.
Can Lockpick see the cookie I get after signing in?
No. Lockpick never signs in to your site and never looks at anything behind a login. Check that cookie yourself in your browser's developer tools.
See what your site shows from outside
A quick check reads your homepage the way a visitor would and gives you a score. No account needed.
Check your siteSources
- How we check · Docs · Lockpick Lockpick docs, read on October 17, 2026
- Session Management - OWASP Cheat Sheet Series OWASP Cheat Sheet Series, read on October 17, 2026
- Set-Cookie header - HTTP | MDN MDN Web Docs, read on October 17, 2026
- Using HTTP cookies - HTTP | MDN MDN Web Docs, read on October 17, 2026
- What we never do · Docs · Lockpick Lockpick docs, read on October 16, 2026