Secure Coding in Java SE Applications
The exam tests whether you validate input, protect secrets, and use the platform's secure APIs rather than convenient ones.
Validate everything at the boundary
Treat all external input as hostile. Prefer allowlists over blocklists, cap lengths, and parse into typed values before use. For SQL, use PreparedStatement with bound parameters - string concatenation enables SQL injection. For file access, resolve and normalize the requested path and verify it still starts with the permitted base directory, which blocks ../ traversal. Encode output for its context (HTML, URL, JSON) to stop cross-site scripting.
Secrets, randomness and hashing
Never hardcode credentials; load them from a keystore or the environment. Store passwords in char[] and zero it after use, because a String lingers in the pool until garbage collection. Use java.security.SecureRandom for tokens and salts, never java.util.Random. Derive password hashes with PBKDF2 (SecretKeyFactory with PBKDF2WithHmacSHA256), bcrypt or Argon2 - a raw MD5 or SHA-1 digest is not a password hash.
Deserialization and parsing
Do not deserialize untrusted byte streams; a crafted stream can instantiate arbitrary classes. If you must, install an ObjectInputFilter (JEP 290). Disable external entity resolution in XML parsers to prevent XXE: enable XMLConstants.FEATURE_SECURE_PROCESSING and disallow doctype declarations.
Defensive design
Make classes final or fields private, return defensive copies of mutable arrays and collections, and never let a reference escape from a constructor. Avoid Runtime.exec with user-influenced strings. Run with the least privilege available.
Worked example
Path base = Path.of("/srv/data"); Path p = base.resolve(userInput).normalize(); if (!p.startsWith(base)) throw new SecurityException(); Reasoning: normalize collapses .., so a traversal attempt no longer starts with the base and is rejected.
Traps
Blacklisting ../ instead of normalizing and checking; logging secrets; assuming a SecurityManager is installed by default (it is not).