Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Java Application Security Basics

ASecurity

Application-security judgement for Java 21+: password storage with current memory-hard KDF parameters, constant-time verification, secure randomness, authorisation inside the protected operation, adversarial validation, reversible-cryptography boundaries, and secret-safe types. Use when credentials, password hashes, salts, bearer tokens or peppers change; when MessageDigest, SecureRandom, Random, UUID, Cipher, Mac or PasswordEncoder serves a security purpose; when a controller annotation is t...

2 stars
0 votes
0 copies
0 views
Added 9/19/2026
developmentrustgojavaspringapidatabasesecurity

Works with

api

Security Analysis

A100/100

Scanned 9/19/2026

Install to Claude Code

$npx -y skills add robsonkades/agent-skills --skill java-application-security-basics --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Java Application Security Basics?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Java Application Security Basics
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/robsonkades-java-application-security-basics/badge)](https://www.skillsdirectory.com/skills/robsonkades-java-application-security-basics)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: java-application-security-basics
description: >
  Application-security judgement for Java 21+: password storage with current memory-hard KDF
  parameters, constant-time verification, secure randomness, authorisation inside the protected
  operation, adversarial validation, reversible-cryptography boundaries, and secret-safe types.
  Use when credentials, password hashes, salts, bearer tokens or peppers change; when
  MessageDigest, SecureRandom, Random, UUID, Cipher, Mac or PasswordEncoder serves a security purpose; when a
  controller annotation is the only authorisation check; when identity comes from the request
  instead of the principal; or when a generic CryptoUtils wrapper is proposed. Code-level only:
  layered validation is java-defensive-programming, redaction is structured-logging, ReDoS is
  java-strings-and-text, and deserialisation is java-serialization-hardening.
---

# Java Application Security Basics

## Purpose

The code-level half of application security — the decisions that survive replacing the
security framework. It prevents two failures: "I used the framework default" mistaken for
"I followed current guidance", and authorisation that lives only at the HTTP entry point.

## Scope

**Covers:** password storage and verification, secure randomness, authorisation as a
precondition of the protected operation, the adversarial half of input validation, secrets in
source and in types, and safe review boundaries for reversible cryptography.

**Does not cover:** transport security, nor framework configuration — filter chains, JWT and
OAuth2 resource server, method-security wiring and CORS belong to `spring-security-for-apis`,
in a different repository, not installed alongside this skill. Nor does it apply to a service
with no credential store, no untrusted input and no per-instance ownership rule: threading an
`Actor` through that domain is cost, no benefit.

## Workflow

Before recommending APIs or parameters, inspect the project's compiler release/toolchain,
resolved security-library versions, runtime image, credential format and binding standard.
Java 21 is this skill's example baseline, not permission to upgrade the target or add Spring
or BouncyCastle. Version-specific facts below are dated examples; verify them against the
resolved version. If evidence is missing, state the gap and keep the proposed change conditional.

1. **Name the asset and the reachable attacker.** "A leaked database backup" and "another
   tenant's authenticated user" lead to different code; "make it more secure" leads to none.
2. **Read the KDF parameters, not the class name.** Some Spring Security defaults sit below
   current OWASP guidance, so "I used `PasswordEncoderFactories`" is not a compliance claim:

   |                    | Spring Security 7.1 default                                | OWASP (fetched 2026-08-27)  |
   | ------------------ | ---------------------------------------------------------- | --------------------------- |
   | Argon2id           | `m=16384 KiB, t=2, p=1` (`defaultsForSpringSecurity_v5_8`) | `m=19456 KiB` at `t=2, p=1` |
   | PBKDF2-HMAC-SHA256 | 310,000 iterations                                         | 600,000 iterations          |
   | bcrypt             | strength 10                                                | 10 is the stated _minimum_  |

   `DelegatingPasswordEncoder.idForEncode` is still `"bcrypt"` in 7.1.1, not Argon2id — so
   it does not select OWASP's first choice for new storage. bcrypt strength 10 meets its
   minimum; adequacy still depends on measured cost and the binding standard.
   `new Argon2PasswordEncoder(16, 32, 1, 19456, 2)` closes the Argon2 parameter gap.

3. **Make authorisation a precondition of the protected operation.** Use the domain operation
   for an instance rule, or retain an application-service guard when every relevant entry path
   necessarily passes it and its checked state stays consistent with the write. An `Actor`
   parameter is an obligation, not proof of identity: construct stable claims only from a trusted
   authentication context, and do not let request JSON supply roles or tenant.
   Keep the controller annotation as cheap early rejection; it stops being the only check.
   Authorise the _instance_: "has role CUSTOMER" without "and this order is theirs".
4. **Allowlist attacker-controlled input as structure, but it is not the control** — regex over
   hostile input is a DoS vector (`java-strings-and-text`); hostile bytes are
   `java-serialization-hardening`.
5. **Trace every secret from where it enters to everywhere it can be rendered** — source,
   config, `toString()`, `equals`, an exception message, an HTTP error body. Redaction at the
   log encoder is `structured-logging`'s backstop; keeping it out of the type is the control.
6. **Verify** against `references/review.md` — a rule you cannot check on a diff is no rule.

## Decision rules

```text
IF greenfield password storage
THEN prefer Argon2id at current OWASP parameters; use scrypt if unavailable, or an approved
     PBKDF2 implementation where binding FIPS requirements demand it. An algorithm name alone
     does not establish FIPS validation. Check deployment capacity before choosing parameters.

IF existing bcrypt at a measured adequate cost
THEN keep verification support and migrate on successful authentication; schedule forced
     migration only when compliance, compromise evidence, an unacceptable cracking model,
     inactive accounts or the 72-byte legacy estate justify its user and operational cost.

IF a caller identity or resource owner is read from the request
THEN it is a claim, not an identity: take the subject from the authenticated principal.

IF comparing fixed-width hashes, MACs or token digests
THEN MessageDigest.isEqual (or the vetted library verifier), never Arrays.equals or
     String.equals; reject or canonicalise representation before decoding and keep compared
     lengths fixed. Passwords go through PasswordEncoder.matches, not a digest comparison.

IF a value must be unguessable (session id, reset token, API key, OTP, salt)
THEN generate an explicit entropy budget with SecureRandom; never Random, ThreadLocalRandom or
     Math.random(). Store reset/API tokens as a digest, bind purpose and subject, expire them,
     and consume single-use tokens atomically. Reusable API keys instead need revocation and
     rotation; do not consume them on their first authenticated request.

IF plaintext must be recovered later
THEN define the threat model and key custody first; use a vetted AEAD construction with an
     explicit transformation, unique nonce per key and versioned envelope. Never use
     Cipher.getInstance("AES"), ECB, unauthenticated CBC, or a reusable fixed GCM nonce.
```

## Rules

- Password length policy conflicts between the two standards teams cite, so say which one binds
  instead of picking silently: NIST SP 800-63B-4 (July 2025) makes 15 characters a **SHALL**
  where the password is the _single_ factor (8 within MFA); ASVS 5.0 §6.2.1 sets the floor at
  8, 15 recommended. The deciding question is not which is stricter but _which regime does this
  system answer to, and is the password ever the only factor?_ Both forbid composition rules
  and periodic rotation regardless — and never write that "NIST relaxed the password rules": it
  dropped composition and expiry and **raised** the single-factor floor. Requirement text and
  the three questions that settle it: `references/password-policy.md`.
- Spring bcrypt's 72-**byte** ceiling differs between writing and verification: the
  CVE-2025-22228 fix (6.3.8 / 6.4.4, March 2025) makes `encode` throw above it. In the named
  7.1.1 implementation, `matches` still skips the guard, including for a newly written hash
  of a 72-byte password plus an over-length candidate suffix. An uncaught re-encode can fail
  registration, change-password or rehash-on-login. Enforce the byte limit consistently or
  migrate to a suitable KDF without truncation; plan recovery for existing over-length users.
- Make account-existence paths observationally similar: the same external response, one KDF
  on both paths, and shared throttling. This mitigates rather than proves indistinguishability:
  caches, database work, network jitter and downstream side effects remain measurable.
  `orElseThrow()` before comparison — or distinct not-found/not-permitted errors — is an
  enumeration oracle.
- Treat authorisation and mutation as one consistency decision. A check against an object read
  in one transaction followed by an unconditional write in another is a TOCTOU bug; use a
  transaction with the required isolation, a version/CAS predicate, or a conditional update
  that includes tenant/owner and expected state. Returning `404` for both absent and forbidden
  resources hides detail from the caller but is not the authorisation control.
- Password-reset and API-key flows are credential systems, not random-string helpers. Generate
  at least the entropy required by the applicable standard, display the raw value once, store
  only a domain-separated digest and enforce purpose/subject/expiry. Atomically consume reset
  tokens; enforce revocation and rotation for reusable API keys.
  Rate-limit redemption; do not log query strings containing bearer material.
- Hash what only needs equality verification; encrypt only what the application must recover.
  With reversible data, `Cipher.getInstance("AES")` delegates mode and padding to the provider.
  Prefer a platform/KMS envelope or a reviewed `AES/GCM/NoPadding`/ChaCha20-Poly1305 facility;
  authenticate tenant, record id, schema and key version as AAD where those fields must not be
  swappable. Nonce uniqueness is per key, and decrypt must release no plaintext before tag
  verification. Store algorithm, key version, nonce and ciphertext/tag so rotation is possible;
  never store a plaintext data-encryption key beside the ciphertext it protects. An encrypted
  (wrapped) data key may accompany the ciphertext when its wrapping key is separately protected.
- A secret in an automatically generated record or Lombok `@Data` `toString()` can leak
  through `log.info("processing {}", request)`; check custom exclusions and renderers too.
- Two moves make code worse. **Encrypting what only needs hashing** ("so we can support
  password recovery") trades away the property that mattered — a dump yields no passwords —
  for a feature that is itself a defect, and adds a key needing rotation and custody. **The
  custom crypto wrapper that loses the credential contract**: discarding algorithm/parameter
  metadata or replacing a vetted verifier destroys migration and reviewability. Inspect the
  implementation; `hash(String)` alone proves neither defect. A small policy adapter can be
  adequate when it preserves versioned encodings, verification and upgrade behavior.

## Failure modes and production evidence

| Symptom                                              | Distinguish with                                                                    | Likely remediation                                                                                                                      |
| ---------------------------------------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Login latency or CPU jumps after a KDF change        | KDF duration histogram by encoded algorithm id; auth concurrency and CPU saturation | Bound authentication concurrency, benchmark on production-class hardware, then tune parameters without dropping below the binding floor |
| Known users and unknown users have separable latency | Distributions, not one stopwatch sample; include warm/cold cache paths              | Dummy hash with current parameters, common response path and rate limiting; remove existence-specific downstream work                   |
| Cross-tenant mutation despite role checks            | Audit subject, tenant, resource owner and write predicate; enumerate every caller   | Derive subject from trusted context and include owner/tenant/version in the transactional write condition                               |
| Reset link works twice or after replacement          | Concurrent redemption and replay tests against the real datastore                   | Digest-at-rest, expiry and one atomic consume/update; invalidate older outstanding tokens intentionally                                 |
| Secret appears after an exception                    | Structured-log and error-contract tests with canary secrets                         | Secret-free value types/messages, allowlisted error mapping and encoder-side redaction as a backstop                                    |

Do not benchmark password verification with JMH alone and call the capacity question solved.
Measure the primitive to choose parameters, then load-test the bounded authentication path:
arrival bursts, dummy-hash misses, rehash-on-login, datastore latency and rate limiting determine
whether an attacker can turn the KDF into a CPU or memory-exhaustion endpoint.

## Deliverable

For each actionable finding, return its source location, reachable attacker and consequence,
proposed adjustment, and the test that would verify it. Separate observed behavior from static
inference; grep matches alone do not prove exploitability. Report tests actually run and gaps.
If the existing controls satisfy the scoped contract, say so with the evidence; do not require
a migration or a new abstraction to make the review productive.

## References

- [Password storage](references/password-storage.md) — OWASP parameter tables, the
  Argon2id-versus-bcrypt disagreement and its JVM complication, Spring Security encoder facts,
  peppering, randomness, `char[]` versus `String`. Read at step 2, and before designing a type
  that holds a credential.
- [Password policy](references/password-policy.md) — NIST 800-63B-4 and ASVS 5.0 requirement
  text side by side. Read when setting registration or change-password rules.
- [Before and after](references/before-after.md) — the non-constant-time comparison in Urma &
  Warburton's Twootr chapter and its fix, and authorisation moved into the domain. Steps 2, 3.
- [Review prompts and verification](references/review.md) — the failure catalogue as
  questions and grep patterns, and how to tell the change improved something. Read at step 6.

Attribution

robsonkadesrobsonkades
View sourceMore from robsonkades →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

281612 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2132 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →