- Use `play-json` or `circe` decode results and validate them with domain types immediately — never pass raw `JsValue` or `Json` objects across service boundaries.
- Avoid `Class.forName`, `classOf[T].getMethods`, and `.asInstanceOf` on untrusted data — reflection bypasses the type system and enables remote code injection.
- Use `scala.util.matching.Regex` to validate and sanitise string inputs at the entry point; reject input that does not match expected patterns early.
- Disable Java serialisation entirely with `-Djava.io.ObjectInputStream.enableSerialFiltering=false` or a serialisation filter — never deserialise untrusted binary Java streams.
- Use `SecureRandom` from `java.security` instead of `scala.util.Random` for cryptographic tokens, session IDs, and nonces.
- Parameterise all database queries — use `doobie` `sql""` interpolator or `Slick` lifted embedding which prevent SQL injection by construction.
- Redact sensitive fields (`password`, `token`, `secret`) in `case class` `toString` by overriding it or using a custom `Show` type class instance.