agentsclimarketplace

Java security

Skill Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack/plugins/devtools-pack/skills/java-security

When to activate: Java security, Spring Security, JWT, OAuth2, SecurityFilterChain, method security, CSRF, CORS, password encodingFrom its SKILL.md

Install
npx -y skills add Mattakushi432/Claude-Code-Skills-Custom-DevTools-Pack --skill java-security

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

5.5 KB, ~1.1k tokens by cl100k_base, as published. Nobody here has run it

Java Security Patterns

Spring Security 6 Configuration

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(AbstractHttpConfigurer::disable)          // stateless API
            .sessionManagement(s -> s.sessionCreationPolicy(STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/auth/**", "/actuator/health").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
            .exceptionHandling(ex -> ex
                .authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
                .accessDeniedHandler(new BearerTokenAccessDeniedHandler())
            )
            .build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(12);
    }
}

JWT with Nimbus (Spring Security)

@Configuration
public class JwtConfig {

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

    @Bean
    public JwtDecoder jwtDecoder() {
        return NimbusJwtDecoder.withSecretKey(secretKey()).build();
    }

    @Bean
    public JwtEncoder jwtEncoder() {
        return new NimbusJwtEncoder(new ImmutableSecret<>(secretKey()));
    }

    private SecretKey secretKey() {
        return new SecretKeySpec(jwtSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
    }
}

@Service
@RequiredArgsConstructor
public class TokenService {
    private final JwtEncoder encoder;

    public String generateToken(UserDetails user) {
        Instant now = Instant.now();
        JwtClaimsSet claims = JwtClaimsSet.builder()
            .issuer("my-service")
            .issuedAt(now)
            .expiresAt(now.plus(1, ChronoUnit.HOURS))
            .subject(user.getUsername())
            .claim("roles", user.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority).toList())
            .build();
        return encoder.encode(JwtEncoderParameters.from(claims)).getTokenValue();
    }
}

Method-Level Security

@Service
public class DocumentService {

    @PreAuthorize("hasRole('ADMIN') or #userId == authentication.name")
    public Document getDocument(Long id, String userId) { ... }

    @PostAuthorize("returnObject.ownerId == authentication.name")
    public Document findById(Long id) { ... }

    @PreAuthorize("hasAuthority('DOCUMENT_WRITE')")
    public Document create(CreateDocumentRequest request) { ... }

    @Secured("ROLE_ADMIN")
    public void deleteDocument(Long id) { ... }
}

CORS Configuration

@Bean
public CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowedOrigins(List.of("https://app.example.com"));
    config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
    config.setAllowedHeaders(List.of("Authorization", "Content-Type"));
    config.setAllowCredentials(true);
    config.setMaxAge(3600L);

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

Input Validation & SQL Injection Prevention

// Always use parameterized queries
@Query("SELECT u FROM User u WHERE u.email = :email")
Optional<User> findByEmail(@Param("email") String email);

// Never concatenate user input
// BAD:  "SELECT * FROM users WHERE name = '" + name + "'"
// GOOD: jdbcTemplate.queryForObject("SELECT * FROM users WHERE name = ?", User.class, name)

// Validate at boundary
@PostMapping("/users")
public UserResponse create(@Valid @RequestBody CreateUserRequest request) { ... }

public record CreateUserRequest(
    @NotBlank @Size(max = 100) String name,
    @NotBlank @Email String email,
    @Pattern(regexp = "^(?=.*[A-Z])(?=.*\\d).{8,}$") String password
) {}

Secrets Management

// Never hardcode secrets — read from environment
@Value("${app.jwt.secret:#{null}}")
private String jwtSecret;

@PostConstruct
public void validateSecrets() {
    if (jwtSecret == null || jwtSecret.length() < 32) {
        throw new IllegalStateException("JWT secret must be at least 32 characters");
    }
}

// Use Spring Cloud Vault or AWS Secrets Manager in production
@Configuration
@EnableVaultConfiguration
public class VaultConfig extends AbstractVaultConfiguration {
    @Override
    public VaultEndpoint vaultEndpoint() {
        return VaultEndpoint.from(URI.create(System.getenv("VAULT_ADDR")));
    }
}

Key Rules

  • BCryptPasswordEncoder(12) — strength 12 is the minimum for production; never store plain or MD5 passwords
  • Disable CSRF only for stateless REST APIs; always enable for session-based apps
  • @PreAuthorize with SpEL is preferred over role checks in business logic
  • Never log passwords, tokens, or PII — use structured logging with explicit field exclusions
  • Validate all user input at the controller boundary with @Valid — never trust raw request data

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 1 of the 12 instructions most security skills give in ~1.1k tokens

Counted across 648 of the 828 authors here whose files we hold, read 2026-08-07

  • Parameterize all database querieshere, and in 68 of 648, across 51 files
  • Hash passwords using bcrypt, scrypt, or argon2in 49 of 648, across 36 files
  • Apply rate limiting to authentication endpointsin 48 of 648, across 24 files
  • Configure security headersin 35 of 648, across 19 files
  • Validate all inputsin 32 of 648, across 24 files
  • Validate all external input at the system boundaryin 29 of 648, across 19 files
  • Run containers as a non-root userin 28 of 648, across 15 files
  • Use httponly secure samesite cookies for sessionsin 26 of 648, across 15 files
  • Run dependency audits before every releasein 21 of 648, across 10 files
  • Encode output to prevent cross-site scriptingin 21 of 648, across 11 files
  • Copy dependencies before source codein 20 of 648, across 9 files
  • Store secrets in environment variablesin 20 of 648, across 18 files

Said here and by no other author read

  • disable csrf for stateless apis
  • enable csrf for session-based apps
  • use preauthorize with spel
  • validate jwt secret length in postconstruct

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 326,851. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.