Secure Java engineering
Security starts with supported software, minimal input trust, safe dependencies, and protected secrets.
Patch and supply chain
Run a supported JDK and update security patches promptly. Pin and verify build toolchains and dependencies. Generate an SBOM, scan artifacts, review transitive dependencies, sign/prove releases, and keep rollback artifacts.
Input and output
Validate size, type, range, encoding, and business rules. Use
parameterized SQL, safe output encoding, and allow-list validation for
structured identifiers. Avoid shell construction; use
ProcessBuilder with separate arguments only when a process
is truly necessary.
Deserialization and XML
Never deserialize untrusted native Java objects. Apply filters for legacy use. Configure XML parsers to block external entities and unwanted external access. Limit nested structures and decompression.
Cryptography
Use standard high-level protocols and modern library/provider
defaults. Generate secrets with SecureRandom, use
authenticated encryption, store keys outside source code, rotate keys,
and never invent a cryptographic algorithm. Passwords need adaptive
password hashing, not reversible encryption.
Secrets and logs
Do not place secrets in command lines, source, images, stack traces,
heap dumps, or logs. Redact tokens and sensitive values. Zeroing a
char[] can reduce exposure but does not solve every copy in
memory.
Least privilege
Run as a non-root OS user, restrict filesystem/network access, minimize modules and native libraries, and isolate high-risk parsing. The legacy Security Manager is not a modern sandbox strategy.
Feynman check
Treat every external byte as an unopened package. Check the sender, size, label, and allowed contents before opening it in a restricted room.