SOC 2 Controls for Java Spring Boot: What Auditors Actually Check
Implement SOC 2-ready controls in Java Spring Boot applications — covering Spring Security configuration, secrets management, audit logging with Spring Data, and dependency scanning.
- Configure Spring Security with method-level annotations (@PreAuthorize) and a SecurityFilterChain to enforce least-privilege access control.
- Use Spring Vault or AWS Secrets Manager integration to inject secrets at startup — never hardcode credentials in application.properties.
- Enable Spring Data Envers or a custom AuditingEntityListener to write immutable audit trail records to a dedicated audit table.
- Run OWASP Dependency-Check in CI and block builds on CVSS score >= 7.
- Use @Validated with Jakarta Bean Validation annotations on all controller method parameters and request bodies.
In this guide
SOC 2 scope for Spring Boot applications
Spring Boot is the dominant Java framework for enterprise REST APIs and microservices. SOC 2 auditors examine logical access controls, change management, and monitoring — all areas where Spring has mature support.
Common audit findings in Spring Boot applications: Spring Security disabled or using permissive wildcard rules, plaintext database passwords in application.properties committed to git, no audit trail for entity mutations, and transitive dependencies with known CVEs.
This guide addresses each finding with concrete Spring configuration. All code examples target Spring Boot 3.x with Java 17+.
Spring Security configuration for CC6
Define a SecurityFilterChain bean that defaults to deny-all and explicitly permits only required endpoints. Use `http.authorizeHttpRequests(auth -> auth.requestMatchers("/api/public/**").permitAll().anyRequest().authenticated())`. Never use `.anyRequest().permitAll()` in production.
Enable method security with `@EnableMethodSecurity` and use `@PreAuthorize("hasRole('ADMIN')")` on sensitive service methods. This provides defence-in-depth: even if a route mapping changes, the method-level guard remains.
For OAuth 2.0 / JWT: configure Spring Security as a resource server with `http.oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))`. Validate the `iss`, `aud`, and `exp` claims. Store the JWT signing public key in a mounted secret, not in application.properties.
Secrets management with Spring Vault
Spring Vault (spring-cloud-vault-config) integrates with HashiCorp Vault to inject secrets as Spring properties at startup. Configure `spring.cloud.vault.token` via a Kubernetes secret or IAM role. Secrets appear as standard `@Value("${db.password}")` injections — no code change needed.
For AWS deployments, use Spring Cloud AWS with `spring.config.import=aws-secretsmanager:/myapp/prod`. Spring Cloud AWS fetches the secret JSON at startup and maps keys to Spring properties. Add `spring-cloud-aws-secrets-manager` to your pom.xml.
Add a Gitleaks or trufflehog pre-commit hook to scan for hardcoded credentials. Document the scanning step in your change management procedure (CC8.1). Run `git log --all --full-history -- "*.properties"` periodically to ensure no historical commits contain credentials.
Audit logging with Spring Data Envers
Spring Data Envers (hibernate-envers) automatically writes a revision record to a `*_AUD` table on every INSERT, UPDATE, or DELETE of annotated entities. Add `@Audited` to any JPA entity you want tracked. Envers records the revision number, timestamp, operation type, and the full field snapshot.
For authentication events (login, logout, failed login), implement an `ApplicationListener<AbstractAuthenticationEvent>` and write records to a dedicated `audit_events` table with fields: event_type, user_id, ip_address, timestamp, outcome.
Protect audit tables with a separate DB role that has INSERT-only permissions. Application code should never UPDATE or DELETE audit records. Grant SELECT to the auditor portal service account only. This satisfies CC7.2 and provides an immutable trail for auditor review.
Dependency scanning with OWASP Dependency-Check
Add the `dependency-check-maven` plugin to your pom.xml. Configure `<failBuildOnCVSS>7</failBuildOnCVSS>` to block builds when any dependency has a CVSS score of 7 or higher. The plugin checks against the NVD database.
Run the check in your CI pipeline (GitHub Actions: `mvn verify -Powasp`). Cache the NVD database between runs to avoid rate limiting. Publish the HTML report as a CI artifact for auditor review.
Maintain a suppression file (`dependency-check-suppressions.xml`) for accepted false positives. Each suppression must include a `<notes>` element explaining the risk acceptance rationale and an expiry date. Review suppressions quarterly as part of your vulnerability management programme.
Input validation with Bean Validation
Annotate all request body DTOs with Jakarta Bean Validation constraints: `@NotBlank`, `@Size(max=255)`, `@Email`, `@Pattern`. Add `@Validated` to your `@RestController` class and `@Valid` to `@RequestBody` parameters. Spring will automatically return a 400 with constraint violation details.
For custom business rules, implement `ConstraintValidator<T, V>` and create a custom annotation. This keeps validation logic co-located with the DTO and testable in isolation.
Note on Jackson: if you have a boolean field `isActive` on a DTO, add `@JsonProperty("isActive")` to ensure Jackson serialises the field name correctly. Jackson by default uses the getter name for booleans (`isActive` getter → `"active"` JSON key), which can cause frontend type mismatches and is a known source of subtle bugs.
Collecting evidence for auditors
Auditors typically request: (1) SecurityFilterChain configuration showing deny-all default; (2) A sample Envers audit trail showing entity history; (3) OWASP Dependency-Check report from the most recent production deployment build; (4) Secret scanning CI step passing with zero findings; (5) TLS configuration showing minimum TLS 1.2.
For Spring Boot, you can expose a custom `/actuator/security-config` endpoint (protected, ADMIN role only) that returns the active security policy as JSON. This gives auditors a machine-readable snapshot without needing a codebase walkthrough.
Map your evidence to Trust Service Criteria: SecurityFilterChain → CC6.2 (logical access), Envers → CC7.2 (monitoring), Dependency-Check → CC7.1 (vulnerability management), Bean Validation → CC6.6 (input handling), Secrets Manager → CC6.1 (credential storage).
Frequently Asked Questions
Does Spring Boot auto-configuration create any SOC 2 risks?
What is the difference between Spring Security RBAC and ABAC?
Does Hibernate parameterise all queries automatically?
How do I handle secrets in integration tests without Vault?
Does running on AWS ECS satisfy any SOC 2 infrastructure controls?
Automate your compliance today
AuditPath runs 86+ automated checks across AWS, GitHub, Okta, and 14 more integrations. SOC 2 and DPDP Act. Free plan available.
Start for free