By framework

Spring Boot security — a production hardening reference

A Spring Boot production-hardening checklist: dependency CVEs (Log4Shell), config and secrets, authorization, Actuator exposure and deserialization.

Published 2026-07-02 Updated 2026-10-23 7 min read
On this page

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 maintenance.

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 ── Ongoing maintenance

Unsafe deserialization / headers, CSRF, session / SSRF

Harden in order: P0 (prerequisite) → P1 (top source of incidents) → P2 (ongoing maintenance).
PriorityControlSpecifics (Spring Boot)
P0Dependency CVE monitoringosv-scanner / dependency-check; judge by running version, patch fast (Log4Shell-class)
P0Production errorsDon't expose stack traces (server.error.include-stacktrace=never, etc.)
P0Externalize secretsConnection info/keys from env/Vault, not hardcoded config. Don't commit to the repo
P1Explicit authorizationDefault-deny + method security (@PreAuthorize) + owner checks
P1Reduce Actuator exposureMinimal exposure (e.g. health) + auth required + separate port/boundary. Don't expose env/heapdump
P1DeserializationDon't natively deserialize untrusted data. Don't let SpEL evaluate input
P2InjectionBind with JPA/JdbcTemplate. Never build queries by string concatenation
P2Headers/CSRF/sessionSpring Security headers (HSTS, etc.), CSRF, cookie attributes, session fixation
P2SSRFAllowlist 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 affects many apps at once. Log4Shell is the best-known example.

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 leaves some endpoint open to anyone

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, or loggers (info leak / abuse for unauthorized 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.

1

Actuator isn't exposing sensitive endpoints

In production, confirm /actuator doesn't expose env/heapdump, etc., and that it's authenticated.
2

Errors don't leak internals

Trigger an error and confirm no stack trace is shown externally.
3

Authorization holds

In a test environment, request another user's resource and confirm it is denied (read/update/delete paths).
4

Dependencies and headers

Confirm the dependency scan (osv-scanner/dependency-check) is clean, and that HTTPS/HSTS are present via the headers checker.

This site's view: focus on dependencies and minimal public exposure

Spring is a stable framework, but precisely because it's so widely used, a dependency-library flaw affects many apps at once. Log4Shell is the best-known example, and the main 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 internet and don't leave authorization to defaults. This site is a different stack, but the principle is the same: keeping dependencies up to date, minimizing what is public, and making authorization explicit work regardless of framework.

Sources and scope

These primary references support the settings, scope or remediation discussed above; links were checked on October 23, 2026. Consult their version and configuration conditions. Checklist priorities and lessons are this site's guidance, not a full-article revalidation or a safety guarantee.

FAQ

QWhat should I do first to secure Spring Boot?
A

The three P0 items: (1) machine-monitor dependency CVEs and patch fast, judging by the running version (as Log4Shell showed, a flaw in a widely used library affects many apps at once, so updating quickly 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?
A

Actuator provides management endpoints for runtime info and diagnostics, but if exposed it can leak internals and, depending on config, be abused for unauthorized 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?
A

Log4Shell is the classic case of a flaw in a widely used logging library affecting many apps at once. The main 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 also limit the damage if you are breached.

QHow should I write Spring Security authorization safely?
A

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 flaws, so build authorization explicitly.

QWhy is unsafe deserialization dangerous?
A

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.