---
title: "skill by agenticluke · skilld"
canonical_url: "https://skilld.dev/gh/agenticluke/spring-security-review-plus"
meta:
  description: "Review or add security in Java Spring Boot apps. Use for login, access rules, input checks, CSRF, secrets, headers, rate limits, file uploads, logs, and… From agenticluke/spring-security-review-plus."
  "og:description": "Review or add security in Java Spring Boot apps. Use for login, access rules, input checks, CSRF, secrets, headers, rate limits, file uploads, logs, and… From agenticluke/spring-security-review-plus."
  "og:title": "skill by agenticluke"
  "twitter:description": "Review or add security in Java Spring Boot apps. Use for login, access rules, input checks, CSRF, secrets, headers, rate limits, file uploads, logs, and… From agenticluke/spring-security-review-plus."
  "twitter:title": "skill by agenticluke"
---

`

[All skills](https://skilld.dev/skills)

[![agenticluke avatar](https://skilld.dev/_img/avatar?url=https%3A%2F%2Fgithub.com%2Fagenticluke.png%3Fsize%3D96)](https://skilld.dev/gh/agenticluke)

# **/skill**

[@71a0586](https://github.com/agenticluke/spring-security-review-plus/commit/71a058611ff05927a91e206402cbe16db2e7a93b "Your agent reads SKILL.md at commit 71a0586")

by [agenticluke](https://skilld.dev/gh/agenticluke)· [agenticluke](https://skilld.dev/gh/agenticluke)/ [spring-security-review-plus](https://skilld.dev/gh/agenticluke/spring-security-review-plus)

Review or add security in Java Spring Boot apps. Use for login, access rules, input checks, CSRF, secrets, headers, rate limits, file uploads, logs, and library risks.

- 1 file
- 9.8 KB
- Updated 2 weeks ago
- [GitHub](https://github.com/agenticluke/spring-security-review-plus/blob/71a058611ff05927a91e206402cbe16db2e7a93b/skill/SKILL.md "View SKILL.md on GitHub")

## SKILL.md

9.8 KB

**≈44** tokens always: the name and description. **≈2.5k** when used: this file.

## Spring Boot Security Review

> Credit: This skill builds on the work of the original open-source author.

Use this skill when you add or review:

- Login or token code
- Access rules
- Web routes
- User input
- File uploads
- Secrets
- Security settings

### Review Steps

1. Find each public route.
2. Check who may call each route.
3. Check all input before use.
4. Check tokens, cookies, and CSRF rules.
5. Check SQL, files, logs, and secrets.
6. Check limits, headers, and libraries.
7. Report each risk with a clear fix.

Deny access unless a rule allows it. Give each user only the access they need.

### Login and Tokens

Prefer Spring Security OAuth2 Resource Server for bearer tokens. Do not write token checks by hand unless the app has a clear need.

For JWTs, check:

- The signature
- The allowed signing method
- The issuer
- The audience
- The expiry time
- The not-before time

Reject bad, missing, expired, or revoked tokens. Do not trust claims before all checks pass.

If the app needs fast token revoke, use short-lived JWTs with refresh token revoke, or use opaque tokens with a revoke list.

For login sessions, use cookies with:

- `HttpOnly`
- `Secure`
- `SameSite=Lax` or `SameSite=Strict`

Use `SameSite=None` only when cross-site use is needed. It also needs `Secure`.

Do not place tokens in URLs. URLs may leak into logs and browser history.

Example resource server setup:

```
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  return http
      .authorizeHttpRequests(auth -> auth
          .requestMatchers("/health").permitAll()
          .anyRequest().authenticated())
      .oauth2ResourceServer(oauth -> oauth.jwt(Customizer.withDefaults()))
      .sessionManagement(session -> session
          .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
      .build();
}
```

If a custom filter is required:

- Extend `OncePerRequestFilter`.
- Accept only the expected token format.
- Do not set login state until all checks pass.
- Return `401` for a bad login.
- Clear login state when a request fails.
- Do not log the token.

### Access Rules

Enable method checks:

```
@EnableMethodSecurity
@Configuration
class SecurityConfig {
}
```

Use clear rules:

```
@PreAuthorize("hasRole('ADMIN')")
```

```
@PreAuthorize("@authz.canEdit(authentication, #id)")
```

Check access to the exact record being read or changed. A logged-in user must not gain access by changing an ID in the URL.

Use:

- `401 Unauthorized` when login is missing or bad
- `403 Forbidden` when login is valid but access is denied

Do not trust a role, user ID, price, or owner ID sent by the client.

### Input Checks

Use `@Valid` on request data:

```
public record CreateUserRequest(
    @NotBlank @Size(max = 80) String name,
    @NotBlank @Email @Size(max = 254) String email
) {
}

@PostMapping("/users")
public ResponseEntity<Void> create(@Valid @RequestBody CreateUserRequest request) {
  return ResponseEntity.status(HttpStatus.CREATED).build();
}
```

Set limits for:

- Text length
- List size
- Number range
- Date range
- Nested object depth
- Request body size

Reject unknown fields when they may hide client errors.

Validation does not make HTML safe. If users may enter HTML, clean it with a strict allow list before showing it. Escape plain text when it is shown on a page.

Return safe error messages. Do not show stack traces, SQL text, file paths, or secret values.

### SQL Safety

Use Spring Data or queries with bound values.

Safe:

```
@Query("select u from User u where u.email = :email")
Optional<User> findByEmail(@Param("email") String email);
```

Unsafe:

```
String sql = "select * from users where email = '" + email + "'";
```

Never build SQL field names, sort rules, or table names from raw user input. Map user choices to a fixed allow list.

### CSRF

Keep CSRF protection on when a browser sends login cookies by itself. This includes session apps.

Put the CSRF token in each form or approved request header.

CSRF may be turned off only when all of these are true:

- The app is a stateless API.
- Login uses a bearer token in the `Authorization` header.
- The browser does not send login cookies.
- No route also accepts cookie login.

```
http
    .csrf(csrf -> csrf.disable())
    .sessionManagement(session -> session
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS));
```

CORS is not a CSRF fix. Use a short allow list for trusted origins. Do not use `*` with login data.

### Passwords and Account Safety

If the app stores passwords:

- Hash them with Spring Security's `PasswordEncoder`.
- Prefer Argon2id or bcrypt.
- Never store or log plain passwords.
- Use the same reply for unknown users and wrong passwords.
- Limit login and password reset tries.
- Make reset tokens random, short-lived, and single-use.
- End old sessions after a password reset when needed.

Do not use security questions as the main reset method.

### Secrets

- Never put secrets in source code.
- Never commit secrets to Git.
- Read secrets from environment values or a secret store.
- Keep real values out of `application.yml`.
- Use placeholders such as `${DB_PASSWORD}`.
- Give each secret only the access it needs.
- Change a secret at once if it may have leaked.
- Plan secret changes so old and new values can overlap for a short time.

Also check test files, sample files, shell scripts, build logs, and Git history.

### Security Headers

Keep Spring Security header defaults. Add a content policy that fits the app.

```
http.headers(headers -> headers
    .contentSecurityPolicy(csp -> csp
        .policyDirectives("default-src 'self'; object-src 'none'; frame-ancestors 'self'"))
    .frameOptions(frame -> frame.sameOrigin())
    .contentTypeOptions(Customizer.withDefaults())
    .referrerPolicy(referrer -> referrer
        .policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.NO_REFERRER)));
```

Test the content policy. A rule that breaks the app may be removed later and leave no guard.

Use HTTPS in live systems. Add HSTS only when the site and its subdomains are ready for HTTPS.

### Rate Limits

Limit routes that are costly or easy to abuse, such as:

- Login
- Password reset
- Sign-up
- Search
- File upload
- Email or message send
- Large reports

Use Bucket4j or a trusted gateway.

Set limits by user when logged in. Use IP limits as a second guard. Trust forwarded IP headers only from known proxies.

Return `429 Too Many Requests`. Add `Retry-After` when the wait time is known.

Do not log every blocked try. This can flood logs. Count or group repeat events.

### File Uploads

Check:

- File size
- File count
- File name length
- File type
- File content, not just the stated type
- Allowed file extensions

Also:

- Make a new random file name.
- Do not use the user path.
- Block `..` and path tricks.
- Store files outside the web root.
- Do not run uploaded files.
- Scan files when the risk calls for it.
- Set safe download headers.
- Remove file metadata when it may hold private data.

Images and archive files may expand to a huge size. Set limits after decode or unpack too.

### Logs and Private Data

Never log:

- Passwords
- Tokens
- Session IDs
- Secret keys
- Full card numbers
- Full request bodies by default

Hide or remove private fields before logging. Limit who can read logs and how long logs are kept.

Log key security events, such as denied access and account changes. Do not include secret data in those events.

### Library Safety

- Keep Spring Boot, Spring Security, Java, and build tools on supported versions.
- Run a library risk scan in CI.
- Fail the build for known high-risk flaws unless a time-bound exception is approved.
- Review indirect libraries too.
- Remove libraries that are not used.
- Do not update a major version without tests.

### Concrete Usage Example

User request:

```
Review POST /accounts/{id}/email. It uses a session cookie and accepts a new email address.
```

Apply this skill:

1. Confirm login is required.
2. Check that the user owns `id`, or has an allowed admin role.
3. Do not trust an owner ID from the request body.
4. Use `@Valid`, `@Email`, and a length limit.
5. Keep CSRF on because the route uses a session cookie.
6. Use a bound query when saving the email.
7. Do not log the email change request body.
8. Rate-limit repeat changes if the route sends a message.
9. Return `403` for a valid user who cannot edit the account.
10. Add tests for missing login, bad CSRF token, bad email, wrong owner, and valid owner.

A useful review result is:

```
High: The route checks only that the user is logged in. Any user can change another
account by changing the path ID.

Fix: Check ownership or admin rights before the update.

Test: User A must get 403 when changing User B's email.
```

### Tests to Add

Test both success and failure cases:

- No login
- Bad or expired token
- Wrong role
- Wrong record owner
- Missing CSRF token
- Bad input
- Very large input
- SQL control text in input
- Too many requests
- Unsafe upload name
- Wrong upload content
- Safe error response

### Release Checklist

- Every private route requires login.
- Every record has an owner or role check.
- Tokens have full checks and expire.
- Session cookies have safe flags.
- CSRF rules match the login type.
- CORS has a short allow list.
- All input has size and value limits.
- SQL uses bound values.
- Passwords use a safe hash.
- Secrets are outside source code and logs.
- Security headers are set and tested.
- Risky routes have rate limits.
- Uploads have type, size, name, and path checks.
- Errors do not leak private details.
- Logs do not hold secret or private data.
- Libraries are scanned and supported.
- Access checks have failure tests.

Source: [SKILL.md on GitHub](https://github.com/agenticluke/spring-security-review-plus/blob/71a058611ff05927a91e206402cbe16db2e7a93b/skill/SKILL.md)

## Third-party checks

No third-party reports yet.

## Provenance

[Signed by skilld at 71a0586.](https://github.com/agenticluke/spring-security-review-plus/commit/71a058611ff05927a91e206402cbe16db2e7a93b "71a058611ff05927a91e206402cbe16db2e7a93b") This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 weeks ago.

Activeupdated 2 weeks ago

## README badge

![README badge for agenticluke/spring-security-review-plus](https://skilld.dev/b/agenticluke/spring-security-review-plus?theme=light&label=0)

## Related skills

-
-
-
-
-
-