By framework
Spring Boot security — a production hardening reference
A Spring Boot production-hardening reference: a priority checklist plus dependency CVEs (Log4Shell), production config/secrets, Spring Security authorization, Actuator exposure, deserialization, and SSRF. Defensive, no attack steps.
For: anyone running a Java / Spring Boot app. No attack steps here — this is a working reference for hardening: a priority-ordered checklist, per-area guidance, and self-verification. For the cross-framework picture, see the security-by-framework hub.
Priority-ordered hardening checklist
Do this table top-down. P0 is a prerequisite, P1 is the most frequent source of incidents, P2 is ongoing operational hygiene.
P0 ── Prerequisite (do first)
Dependency CVE monitoring + fast patching / no error detail in production / externalize secrets
P1 ── Top source of incidents
Spring Security authorization (default-deny, owner checks) / reduce Actuator & management exposure
P2 ── Operational hygiene
Unsafe deserialization / headers, CSRF, session / SSRF
| Priority | Control | Specifics (Spring Boot) |
|---|---|---|
| P0 | Dependency CVE monitoring | osv-scanner / dependency-check; judge by running version, patch fast (Log4Shell-class) |
| P0 | Production errors | Don't expose stack traces (server.error.include-stacktrace=never, etc.) |
| P0 | Externalize secrets | Connection info/keys from env/Vault, not hardcoded config. Don't commit to the repo |
| P1 | Explicit authorization | Default-deny + method security (@PreAuthorize) + owner checks |
| P1 | Reduce Actuator exposure | Minimal exposure (e.g. health) + auth required + separate port/boundary. Don't expose env/heapdump |
| P1 | Deserialization | Don't natively deserialize untrusted data. Don't let SpEL evaluate input |
| P2 | Injection | Bind with JPA/JdbcTemplate. Never build queries by string concatenation |
| P2 | Headers/CSRF/session | Spring Security headers (HSTS, etc.), CSRF, cookie attributes, session fixation |
| P2 | SSRF | Allowlist server-side fetches + block internal IPs/metadata |
1. Dependency CVEs and the ecosystem (P0)
Precisely because Spring is so widely used, a dependency-library flaw cascades to everyone at once. Log4Shell is the symbol of that.
- Machine-monitor dependency CVEs with osv-scanner or OWASP dependency-check, judge by the running version, and patch fast (decide on what's actually built, not the pom.xml/gradle declaration).
- Keep Spring Boot and Java on supported versions. Don't leave EOL versions in place.
- For the case and practice see the Log4Shell dissection · the vulnerability-response playbook · monitoring dependency CVEs.
2. Production config and secrets (P0)
- In production, don't expose error detail (stack traces) — reduce clues that leak internal structure and dependency versions.
- Keep secrets like connection info and keys out of application.properties/yml, injecting from env or a secret manager (Vault, etc.). Don't commit them to the repo (→ .env files and secrets).
- Don't enable dev tools (devtools, etc.) in production.
3. Spring Security authorization (P1 — the top source)
Common (dangerous)
- loose defaults, not designed as explicit allow
- guarded by URL patterns only, no method/owner check
- authenticated, but "logged in = allowed"
- a config gap lets some endpoint pass through
Correct
- default-deny (only what you explicitly allow passes)
- method authorization (
@PreAuthorize, etc.) + owner checks - verify permission/owner on every read/update/delete path
- build authorization explicitly, not left to defaults
See what IDOR is. Authentication and authorization are different; authorize close to the data.
4. Actuator and management endpoints (P1)
- Restrict exposed Actuator endpoints to the minimum (e.g. just health).
- Require authentication/authorization, and keep them on a separate port / network boundary unreachable from outside.
- Don't expose sensitive endpoints like
env,heapdump, orloggers(info leak / a stepping stone for operations).
5. Unsafe deserialization and expression evaluation (P2)
- Don't natively deserialize untrusted data (it can lead to RCE under the right conditions). Verify provenance and restrict to a safe format like JSON where needed (→ what RCE is).
- Don't let templates or SpEL evaluate user input. Validate input with Bean Validation, etc.
6. Injection and data access (P2)
- SQL: bind with JPA / JdbcTemplate; never build queries by string concatenation (→ what SQL injection is).
- When emitting HTML from a template, run output encoding and don't embed user input directly (XSS defense).
7. Headers, HTTPS, session (P2)
- Use Spring Security's security headers (HSTS on HTTPS, etc.). Check your own site with the security headers checker.
- Force HTTPS. Behind a load balancer, configure it to detect the correct scheme/client IP.
- Set Secure/HttpOnly/SameSite on cookies, keep CSRF protection (on by default for browser sessions; if you disable it for APIs, pair with alternative protections), and regenerate the session on login.
8. SSRF and server-side fetches (P2)
- Server-side fetching of user-supplied URLs should restrict targets to an allowlist and block reaching internal IPs / cloud metadata at connection time (→ what SSRF is).
Verify: is your Spring Boot actually hardened?
Building it isn't the end — it's done only once you've checked. These are defensive self-checks against your own environment.
Actuator isn't exposing sensitive endpoints
/actuator doesn't expose env/heapdump, etc., and that it's authenticated.Errors don't leak internals
Authorization holds
Dependencies and headers
This site's view: on a hardened foundation, dependencies and surface decide it
Spring is a solid foundation, but precisely because it's so widely used, a dependency-library flaw cascades to everyone at once. Log4Shell is the symbol of this, and the core defense is less a specific setting than the operational habit of machine-monitoring dependencies, judging by the running version, and patching fast. Alongside that, keep the handy management endpoints (Actuator) off the public surface and don't leave authorization to defaults. This site is a different stack, but the principle is identical — dependency freshness, minimal public surface, explicit authorization work regardless of framework.
Read next
- Hub: security by framework · Next.js security
- Case/practice: the Log4Shell dissection · the vulnerability-response playbook · monitoring dependency CVEs
- Glossary: what IDOR is · what RCE is · what SSRF is
- Tools: security headers checker
FAQ
QWhat should I do first to secure Spring Boot?
The three P0 items: (1) machine-monitor dependency CVEs and patch fast, judging by the running version (with Log4Shell, a foundational library cascades to many apps at once, so keeping up matters); (2) don't expose detailed errors (stack traces) in production; (3) externalize secrets (connection info, keys) instead of hardcoding them in config. Next, move to Spring Security authorization and reducing Actuator exposure.
QWhat should I watch for with Actuator?
Actuator provides management endpoints for runtime info and diagnostics, but if exposed it can leak internals and, depending on config, become a stepping stone for operations. In production, restrict exposure to the minimum (e.g. just health), require authentication and authorization, and keep it on a separate port / network boundary unreachable from outside. Don't expose sensitive endpoints like env, heapdump, or loggers.
QHow do I prepare for a dependency flaw like Log4Shell?
Log4Shell is the classic case of a widely-inherited logging library's flaw cascading to many apps at once. The core preparation is to machine-monitor dependency CVEs and patch fast, judging by the running version (osv-scanner, OWASP dependency-check, etc.) — decide on the version actually built, not the pom.xml/gradle declaration. Least privilege and network segmentation shrink the blast radius too.
QHow should I write Spring Security authorization safely?
Lean the default toward deny (only what you explicitly allow passes), don't rely on URL patterns alone, and use method-level authorization (@PreAuthorize, etc.) where appropriate. On top of login (authentication), implement an ownership check that the target resource truly belongs to the user. Config gaps become privilege-escalation holes, so build authorization explicitly.
QWhy is unsafe deserialization dangerous?
Restoring untrusted data via native Java deserialization can, under the right conditions, lead to remote code execution (RCE). Don't restore externally-sourced data as-is — verify provenance and restrict to a safe format like JSON where needed. Likewise, don't let templates or the expression language (SpEL) evaluate user input.