Skip to content
Skills Library
Security · Building & coding

java-security

/java-security

Java and Spring Boot security patterns. Covers Spring Security, dependency auditing, secure coding practices, and OWASP for Java ecosystem. USE WHEN: user works with "Java", "Spring Boot", "Spring Security", asks about "Java vulnerabilities", "Maven security", "Gradle security", "Java injection", "Java authentication" DO NOT USE FOR: general OWASP concepts - use `owasp` or `owasp-top-10` instead, Node.js/Python security - use language-specific skills

Licence
MIT
Last repository change
21.10.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
1
Scripts
0
HTML comments
3
URLs in SKILL.md
2
Deprecation

No signals detected. Repository changed on 21.10.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What to check before installing
  • SKILL.md zawiera komentarze HTML (3). Nie widać ich w podglądzie Markdown, a model je czyta.

What it does and when to use it

Java and Spring Boot security patterns. Covers Spring Security, dependency auditing, secure coding practices, and OWASP for Java ecosystem. USE WHEN: user works with "Java", "Spring Boot", "Spring Security", asks about "Java vulnerabilities", "Maven security", "Gradle security", "Java injection", "Java authentication" DO NOT USE FOR: general OWASP concepts - use `owasp` or `owasp-top-10` instead, Node.js/Python security - use language-specific skills

Triggers from the description

JavaSpring BootSpring SecurityJava vulnerabilitiesMaven securityGradle securityJava injectionJava authentication
Original author description

Java and Spring Boot security patterns. Covers Spring Security, dependency auditing, secure coding practices, and OWASP for Java ecosystem. USE WHEN: user works with "Java", "Spring Boot", "Spring Security", asks about "Java vulnerabilities", "Maven security", "Gradle security", "Java injection", "Java authentication" DO NOT USE FOR: general OWASP concepts - use `owasp` or `owasp-top-10` instead, Node.js/Python security - use language-specific skills

How it works

  1. When NOT to Use This Skill
  2. Dependency Auditing
  3. Spring Security Configuration
  4. SQL Injection Prevention
  5. XSS Prevention
  6. Authentication Best Practices
  7. Input Validation
  8. Secure File Upload
  9. Logging Security Events
  10. Anti-Patterns
Original SKILL.md headings · 385 lines, 1,108 words
SKILL.md preview
---
name: java-security
description: |
  Java and Spring Boot security patterns. Covers Spring Security, dependency auditing,
  secure coding practices, and OWASP for Java ecosystem.

  USE WHEN: user works with "Java", "Spring Boot", "Spring Security", asks about "Java vulnerabilities", "Maven security", "Gradle security", "Java injection", "Java authentication"

  DO NOT USE FOR: general OWASP concepts - use `owasp` or `owasp-top-10` instead, Node.js/Python security - use language-specific skills
allowed-tools: Read, Grep, Glob, Bash
---
# Java Security - Quick Reference

## When NOT to Use This Skill
- **General OWASP concepts** - Use `owasp` or `owasp-top-10` skill
- **Node.js/TypeScript security** - Use base security skills
- **Python security** - Use `python-security` skill
- **Secrets management** - Use `secrets-management` skill

> **Deep Knowledge**: Use `mcp__documentation__fetch_docs` with technology: `spring-boot` for Spring Security documentation.

## Dependency Auditing

```bash
# Maven - OWASP Dependency Check
mvn dependency-check:check

# Maven - check for updates
mvn versions:display-dependency-updates

# Gradle - dependency check plugin
./gradlew dependencyCheckAnalyze

# Snyk for Java
snyk test --all-projects
```

### Maven Plugin Configuration

```xml
<plugin>
    <groupId>org.owasp</groupId>
    <artifactId>dependency-check-maven</artifactId>
    <version>9.0.9</version>
    <configuration>
        <failBuildOnCVSS>7</failBuildOnCVSS>
        <suppressionFile>dependency-check-suppression.xml</suppressionFile>
    </configuration>
</plugin>
```

## Spring Security Configuration

### Basic Security Config (Spring Boot 3.x)

```java
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(csrf -> csrf
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            )
            .cors(cors -> cors.configurationSource(corsConfigurationSource()))
            .headers(headers -> headers
                .contentSecurityPolicy(csp ->
                    csp.policyDirectives("default-src 'self'; script-src 'self'"))
                .frameOptions(frame -> frame.deny())
                .xssProtection(xss -> xss.disable()) // Use CSP instead
                .contentTypeOptions(Customizer.withDefaults())
            )
            .sessionManagement(session -> session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            )
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(List.of("https://myapp.com"));
        config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
        config.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/api/**", config);
        return source;
    }
}
```

### Password Encoding

```java
@Bean
public PasswordEncoder passwordEncoder() {
    // BCrypt with strength 12 (recommended)
    return new BCryptPasswordEncoder(12);
}

// Usage
String encoded = passwordEncoder.encode(rawPassword);
boolean matches = passwordEncoder.matches(rawPassword, encoded);
```

### Method-Level Security

```java
@Configuration
@EnableMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig {}

// Usage in service
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) { ... }

@PreAuthorize("#userId == authentication.principal.id or hasRole('ADMIN')")
public User getUser(Long userId) { ... }

@PostAuthorize("returnObject.owner == authentication.principal.username")
public Document getDocument(Long id) { ... }
```

## SQL Injection Prevention

### JPA/Hibernate - Safe

```java
// SAFE - Named parameters
@Query("SELECT u FROM User u WHERE u.email = :email")
Optional<User> findByEmail(@Param("email") String email);

// SAFE - Criteria API
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> root = query.from(User.class);
query.where(cb.equal(root.get("email"), email));

// SAFE - Spring Data JPA method names
Optional<User> findByEmailAndStatus(String email, Status status);
```

### JPA/Hibernate - UNSAFE

```java
// UNSAFE - String concatenation
@Query("SELECT u FROM User u WHERE u.email = '" + email + "'")  // NEVER!

// UNSAFE - Native query without parameters
@Query(value = "SELECT * FROM users WHERE email = " + email, nativeQuery = true)  // NEVER!
```

### JDBC Template - Safe

```java
// SAFE - Parameterized query
jdbcTemplate.query(
    "SELECT * FROM users WHERE email = ? AND status = ?",
    new Object[]{email, status},
    userRowMapper
);

// SAFE - Named parameters
namedParameterJdbcTemplate.query(
    "SELECT * FROM users WHERE email = :email",
    Map.of("email", email),
    userRowMapper
);
```

## XSS Prevention

### Thymeleaf (Auto-escaping)

```html
<!-- SAFE - Auto-escaped -->
<p th:text="${userInput}"></p>

<!-- UNSAFE - Unescaped HTML -->
<p th:utext="${userInput}"></p>  <!-- Avoid if possible -->
```

### API Response Sanitization

```java
// Use OWASP Java HTML Sanitizer
import org.owasp.html.PolicyFactory;
import org.owasp.html.Sanitizers;

PolicyFactory policy = Sanitizers.FORMATTING.and(Sanitizers.LINKS);
String safeHtml = policy.sanitize(userInput);
```

## Authentication Best Practices

### JWT Configuration

```java
@Component
public class JwtTokenProvider {

    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.expiration:3600000}") // 1 hour
    private long expiration;

    public String generateToken(Authentication auth) {
        Date now = new Date();
        Date expiryDate = new Date(now.getTime() + expiration);

        return Jwts.builder()
            .setSubject(auth.getName())
            .setIssuedAt(now)
            .setExpiration(expiryDate)
            .signWith(Keys.hmacShaKeyFor(secret.getBytes()), SignatureAlgorithm.HS512)
            .compact();
    }

    public boolean validateToken(String token) {
        try {
            Jwts.parserBuilder()
                .setSigningKey(Keys.hmacShaKeyFor(secret.getBytes()))
                .build()
                .parseClaimsJws(token);
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            return false;
        }
    }
}
```

### Rate Limiting with Resilience4j

```java
@RateLimiter(name = "loginRateLimiter", fallbackMethod = "loginFallback")
public AuthResponse login(LoginRequest request) {
    // login logic
}

public AuthResponse loginFallback(LoginRequest request, RequestNotPermitted ex) {
    throw new TooManyRequestsException("Too many login attempts. Try again later.");
}
```

```yaml
# application.yml
resilience4j:
  ratelimiter:
    instances:
      loginRateLimiter:
        limitForPeriod: 5
        limitRefreshPeriod: 15m
        timeoutDuration: 0
```

## Input Validation

```java
public record CreateUserRequest(
    @NotBlank
    @Email
    @Size(max = 255)
    String email,

    @NotBlank
    @Size(min = 12, max = 128)
    @Pattern(regexp = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&]).*$",
             message = "Password must contain uppercase, lowercase, number and special char")
    String password,

    @NotBlank
    @Size(min = 2, max = 100)
    @Pattern(regexp = "^[a-zA-Z\\s-']+$")
    String name
) {}

@PostMapping("/users")
public ResponseEntity<User> createUser(@Valid @RequestBody CreateUserRequest request) {
    // request is already validated
}
```

## Secure File Upload

```java
@PostMapping("/upload")
public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {
    // Validate file type
    String contentType = file.getContentType();
    if (!ALLOWED_TYPES.contains(contentType)) {
        throw new InvalidFileTypeException("File type not allowed");
    }

    // Validate file size (also configure in application.yml)
    if (file.getSize() > MAX_FILE_SIZE) {
        throw new FileTooLargeException("File exceeds maximum size");
    }

    // Generate safe filename
    String originalName = file.getOriginalFilename();
    String safeName = UUID.randomUUID() + getExtension(originalName);

    // Store outside web root
    Path destination = uploadPath.resolve(safeName);
    Files.copy(file.getInputStream(), destination);

    return ResponseEntity.ok(safeName);
}
```

## Logging Security Events

```java
@Slf4j
@Component
public class SecurityEventLogger {

    public void logLoginAttempt(String username, boolean success, HttpServletRequest request) {
        log.info("Login attempt: user={}, success={}, ip={}, userAgent={}",
            username,
            success,
            request.getRemoteAddr(),
            request.getHeader("User-Agent")
        );
    }

    public void logAccessDenied(String username, String resource, HttpServletRequest request) {
        log.warn("Access denied: user={}, resource={}, ip={}",
            username,
            resource,
            request.getRemoteAddr()
        );
    }

    // NEVER log sensitive data
    // log.info("Password: {}", password);  // NEVER!
    // log.info("Token: {}", jwt);          // NEVER!
}
```

## Anti-Patterns

| Anti-Pattern | Why It's Bad | Correct Approach |
|--------------|--------------|------------------|
| `@Query` with string concat | SQL injection | Use named parameters `:param` |
| `th:utext` for user content | XSS vulnerability | Use `th:text` (auto-escaped) |
| MD5/SHA1 for passwords | Easily cracked | Use BCrypt with strength 12+ |
| Storing JWT secret in code | Secret exposure | Use environment variables |
| `permitAll()` for sensitive endpoints | Unauthorized access | Define explicit auth rules |
| Disabling CSRF for stateful apps | CSRF attacks | Keep CSRF enabled for sessions |
| Catching `Exception` silently | Hides security issues | Log and handle specifically |

## Quick Troubleshooting

| Issue | Likely Cause | Solution |
|-------|--------------|----------|
| 403 on valid request | CSRF token missing | Include CSRF token in requests |
| 401 with valid JWT | Token expired or wrong key | Check expiration and secret key |
| CORS error in browser | Missing CORS config | Add origin to `allowedOrigins` |
| Password validation fails | BCrypt version mismatch | Use same encoder version |
| Method security not working | `@EnableMethodSecurity` missing | Add annotation to config class |
| Dependency check fails build | CVSS threshold too low | Adjust `failBuildOnCVSS` or suppress |

## Security Scanning Commands

```bash
# OWASP Dependency Check
mvn dependency-check:check
./gradlew dependencyCheckAnalyze

# SpotBugs with Security Plugin
mvn spotbugs:check -Dspotbugs.plugins=com.h3xstream.findsecbugs:findsecbugs-plugin:1.12.0

# Snyk
snyk test --all-projects

# SonarQube (if configured)
mvn sonar:sonar -Dsonar.host.url=http://localhost:9000
```

## Related Skills
- [OWASP Top 10:2025](../owasp-top-10/SKILL.md)
- [OWASP General](../owasp/SKILL.md)
- [Secrets Management](../secrets-management/SKILL.md)
- [Supply Chain Security](../supply-chain/SKILL.md)

Versions

The database has no other skills named java-security.

Database snapshot: 13.11.2026 · package version faa1a590f618 (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 95dotnet-security
    .NET and ASP.NET Core security patterns. Covers Identity, authentication, dependency auditing, secure coding practices, and OWASP for .NET ecosystem. USE WHEN: user works with "C#", ".NET", "ASP.NET Core", "Entity Framework", asks about ".NET vulnerabilities", "NuGet security",…
  • 95security-audit
    Java security checklist covering OWASP Top 10, input validation, injection prevention, and secure coding. Works with Spring, Quarkus, Jakarta EE, and plain Java. Use when reviewing code security, before releases, or when user asks about vulnerabilities.
  • 100python-security
    Python security patterns for Django, FastAPI, and Flask. Covers Bandit, Safety, secure coding practices, and OWASP for Python ecosystem. USE WHEN: user works with "Python", "Django", "FastAPI", "Flask", asks about "Python vulnerabilities", "pip security", "Bandit", "Python…
  • 100java-expert
    Expert-level Java development with Java 21+ features, Spring Boot, Maven/Gradle, and enterprise best practices. Use when the user mentions JVM, Spring, Maven, Gradle, or enterprise, or when the task involves Modern Java, Spring Boot, Build Tools, or Dependency Injection.
  • 90spring-boot
    Use when modifying a Java application that actually uses Spring Boot, Spring MVC, Spring Security, Spring Data, or Spring-managed configuration.
  • 100java-spring-patterns
    Java 17+ and Spring Boot 3/4 architecture, idioms, transactions and testing. Use when building or reviewing Java or Spring Boot services.

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.