Safeguard
Application Security•

A secure coding checklist for Scala teams

Types help but do not stop injection, XSS or leaked secrets. A practical Scala checklist covering queries, output, Play filters, dependencies and review.

Safeguard Security Team
4 min read

A secure coding checklist for Scala starts with the same classes of bugs every web language has: injection, unescaped output, weak session handling and leaked secrets. Scala's type system helps with some, but it does not know which strings are trusted. Use library features that separate data from code, and review the places that opt out.

What does the type system give you, and what not?

Scala catches null misuse, mismatched types and many logic errors at compile time. It cannot tell a user-supplied string from a constant. An s"..." interpolation builds a string the same way whether it is a greeting or a query. The checklist below targets the places where a string becomes code, markup, a path or a command.

A constructed example: a reporting endpoint in a Play application sorts results by a column name taken from a query parameter and builds the SQL with string interpolation. The code compiles, tests pass and a crafted parameter changes the query. The type system had no reason to object.

Which controls does the framework give you?

The Play documentation says its filters library loads in sbt as an AutoPlugin and appends three filters to the enabled list: the CSRF filter, the security headers filter and the allowed hosts filter. On new projects those protections are on without extra work. Play's docs describe the security headers filter as setting default headers in the response to mitigate security issues and provide a layer of defense for new applications.

Do not disable these to make a test pass. If an endpoint needs an exception, make it a specific, documented one. If you use another framework, check what it enables by default instead of assuming.

The checklist

  1. Queries: use parameter binding for every value. See the companion post on SQL injection in Scala. OWASP's query parameterization cheat sheet is the reference.
  2. Output: rely on the template engine's escaping, and review every place that renders raw markup. OWASP's XSS guidance says to use the framework default first and watch escape hatches.
  3. Requests: keep CSRF protection on for state-changing routes and restrict allowed hosts.
  4. Headers: keep the security headers filter and configure a content security policy.
  5. Secrets: no secrets in source or application config committed to the repository. Load from a secret manager or environment at start. OWASP says many organizations hardcode secrets in source and config files and calls for centralized storage, auditing and rotation.
  6. Deserialization and JSON: bind to explicit case classes and do not accept more fields than the endpoint needs, so clients cannot set internal fields.
  7. Files and processes: validate paths against an allowed directory and avoid building shell commands from input.
  8. Dependencies: pin versions, generate an SBOM, scan on every build and update on a schedule. Scala projects pull in Java libraries, so scan the full transitive tree, not only Scala artifacts.
  9. Logging: never log tokens, passwords or full request bodies.
  10. Concurrency: shared mutable state in actors, futures or caches can leak data between users. Review any cache key that omits the user or tenant.

How do you make it stick?

Put the checklist in the pull request template, add compiler and linter rules where you can, and write a few tests for each control, for example a request without a CSRF token being rejected. Make the exceptions visible in review.

Safeguard's SCA with reachability analysis helps with item 8 by showing which vulnerable libraries your Scala code actually reaches, and policy gates can block merges that add known critical issues. The free scan at gold.safeguard.sh/scan covers up to 100 dependencies if you want a first look.

What to do

  1. Turn the ten items into a pull request checklist.
  2. Search for string interpolation near any query call and for raw markup rendering, and fix those first.
  3. Confirm the CSRF, security headers and allowed hosts filters are enabled in every Play service.
  4. Remove secrets from the repository and rotate any that were committed.
  5. Add dependency scanning and an SBOM step to CI.
  6. Schedule a review of exceptions every quarter.

Quick check

Are Play security filters on by default?

According to the Play documentation, the filters library adds the CSRF, security headers and allowed hosts filters automatically on new projects.

Does Scala prevent SQL injection?

No. Injection comes from building queries out of strings. Use parameter binding in whatever library you use.

Sources

  1. Play Framework: Built-in HTTP filters
  2. Play Framework: Configuring security headers
  3. OWASP Query Parameterization Cheat Sheet
  4. OWASP Secrets Management Cheat Sheet
  5. OWASP Cross Site Scripting Prevention Cheat Sheet

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.