Security¶
EntryStore provides the following security measures for storing and transferring credentials:
- Passwords are stored as PBKDF2-hashes with per-user salts.
- All random numbers involved in cryptographic operations are generated using the cryptographically strong SecureRandom class.
- The tokens for cookie-authentication are based on cryptographically strong random numbers and do not have any connection to username or password.
Other security-related information:
- EntryStore can be accessed using HTTPS by using an SSL-enabled Web server and/or reverse proxy.
- It is recommended to redirect HTTP requests to HTTPS.
- It is recommended to use SSL/TLS only with Perfect Forward Secrecy (PFS). Recommended cyper suites can be found at https://wiki.mozilla.org/Security/Server_Side_TLS.
Informing users of changed passwords¶
Whenever the password of a user changes, either through password reset or manually setting the password, the user is informed by email. The following settings can be used to change the subject and body of the email message:
entrystore.auth.password-change.email.subject=Your password has been changed
entrystore.auth.password-change.email.template=<path-to-template>
See also the KB entry on Signups for more information on how the templating mechanism works.
HTTP Server response header¶
In 6.x, EntryStore stamps a Server header on every HTTP response so operators and integrators can identify the running service. By default the value is EntryStore/<version> (e.g. EntryStore/6.0), which is convenient for debugging and support but discloses the exact running version to clients — useful for fingerprinting and version-targeted reconnaissance. Two settings let operators trade off identification against fingerprinting:
entrystore.http.header.server— explicit override. Whatever string is configured here is sent verbatim, replacing both the product name and the version. Use this for fully custom branding (e.g.entrystore.http.header.server=Acme API).entrystore.http.header.server.version-precision— controls how much of the auto-computed default's version is exposed. Ignored when the explicit override above is set.
The precision values:
| Value | Resulting header (example for version 6.0.3-SNAPSHOT) |
|---|---|
full (default) |
Server: EntryStore/6.0.3-SNAPSHOT |
minor |
Server: EntryStore/6.0 |
major |
Server: EntryStore/6 |
none |
Server: EntryStore |
For public-facing deployments concerned about fingerprinting, prefer setting entrystore.http.header.server.version-precision=major (or none) over editing the explicit override every release — that way the header stays stable across upgrades without per-release maintenance.
The header is applied at the Jetty protocol level, so it covers every response — including requests rejected by Spring Security (401, 403), CSRF rejections, maintenance-mode responses (503), and protocol-level errors that bypass servlet filters.
CSRF protection¶
Since 6.x, EntryStore can protect cookie-authenticated sessions against cross-site request forgery (CSRF). The protection is off by default, because common EntryStore clients do not send the token header yet; a warning is logged at startup while it is off. Enable it once all cookie-authenticated clients of the installation send the header:
entrystore.csrf.enabled=true|false (default: false)
entrystore.csrf.cookie-name=XSRF-TOKEN (default: XSRF-TOKEN)
When enabled, EntryStore issues the token in the cookie XSRF-TOKEN (readable by JavaScript, with the same SameSite and Secure attributes as the auth_token cookie), e.g. in the response to a login. Every POST, PUT, PATCH and DELETE request that carries the auth_token cookie must send the cookie's value in the header X-XSRF-TOKEN, otherwise it is rejected with 401. Multipart uploads must use the header.
The following requests do not need the token:
- requests without the
auth_tokencookie, e.g. with HTTP Basic, POSTrequests to/auth/cookie,/auth/signup,/auth/signup/confirm,/auth/pwresetand/auth/pwreset/confirm,- SAML responses posted to the Assertion Consumer Service.
POST /auth/logout and the management endpoints require the token. Cross-origin clients must allow the header in the CORS settings (entrystore.cors.headers).
Rate limiting¶
Since 6.x, the following requests are rate limited. Requests above the limit are answered with 429. A limit is configured as a maximum number of requests within a time window; a maximum of 0 disables the limit.
| Requests | Key | Settings | Default |
|---|---|---|---|
| Sign-up, see Sign-up | client IP | entrystore.auth.signup.rate.limit.max, .window |
10 per 1h |
| Password reset, see Sign-up | client IP | entrystore.auth.password-reset.rate.limit.max, .window |
10 per 1h |
/search, see Search |
client IP | entrystore.solr.search.rate.limit.max, .window |
disabled (0), window 1m |
POST /message, see Messaging |
user | entrystore.message.rate.limit.max, .window |
10 per 1h |
Failed password logins are limited per user by the temporary lockout.
Reverse proxy and client IP¶
EntryStore 6.x takes the client IP address, which is used for rate limiting, reCAPTCHA verification and logging, from the Forwarded or X-Forwarded-For header, and derives its external URLs from the X-Forwarded-* headers. The reverse proxy must therefore remove these headers from client requests and set them itself. Without a reverse proxy, set server.forward-headers-strategy=none. See Reverse proxy for details.
The 5.x setting entrystore.trust.x-forwarded-for has no effect in 6.x.
Content-Security-Policy¶
EntryStore does not set a Content-Security-Policy for its own responses; this is left to the reverse proxy, see Reverse proxy. In 6.x, the HTML pages of EntryStore (login, sign-up and password reset forms) work with style-src 'self'. If reCAPTCHA is enabled, the policy must allow the reCAPTCHA script and frame sources on /auth/signup and /auth/pwreset.
Responses of the proxy carry their own policy script-src 'none'; form-action 'none';.
Error responses¶
In 6.x, errors are answered with a JSON object:
{
"timestamp": "2026-01-15T10:12:30.123",
"status": 401,
"path": "/store/1/entry/1",
"error": "Not authorized"
}
The error message does not reveal internal details: unexpected errors are answered with 500 and the message Internal Server Error, denied requests with Not authorized (see ACL), and failed logins with 401 regardless of the reason. The details are only logged.
Default response headers¶
Since 6.x, EntryStore sends the following headers on its responses:
X-Content-Type-Options: nosniffX-Frame-Options: DENY, i.e. EntryStore responses cannot be embedded in framesX-XSS-Protection: 0Strict-Transport-Securityon requests that EntryStore sees as HTTPS, e.g. throughX-Forwarded-Proto: https
Cache-Control is set by EntryStore per response, see HTTP caching and formats.
EntryStore 5.x
5.x does not send X-Frame-Options and X-Content-Type-Options; set them in the reverse proxy, see Reverse proxy.