Skip to content

Security

As a new framework, Brut has not been battle-tested against potential securitiy exploits. That said, Brut does configure several features to help manage security issues.

Overview

Web application security is a large topic. Brut provides a few features out of the box to manage security of your app:

  • Encrypted sessions
  • Cross-Site Request Forgery (CSRF) protection
  • Content Security Policy headers and tools
  • bundle audit

Encrypted Sessions

Brut uses the Rack::Session::Cookie middleware to manage cookies. They are encrypted with the value of the environment variable SESSION_SECRET. This prevents both the website visitor and other websites from examining the contents of the cookie.

This means that if Brut places data in there, it can rely on it being safe when fetched later.

Cookie behavior and configuration is currently not configurable.

CSRF Protection

A cross-site request forgery happens when a malicious site submits information from their site to a Brut-powered site, assuming it will allow and respect your credentials, potentially initiating an action on the Brut-powered site that you did not intend.

The common way to mitigate this is to require a CSRF token to be included with each form submission. This value is generated by the server and included int he user's secure session. If the form submission's CSRF token matches, the request is assumed to be valid.

Brut configures Rack::Protection::AuthenticityToken as a middleware. Its configuration requires that all form submissions include a valid CSRF token, with a few exceptions noted in the Technical Notes section below.

To include a valid CSRF token in your form, use Brut::FrontEnd::Components::FormTag to generate your <form>. That's it.

Brut's approach to Ajax requests is to model them as form submissions, so by creating a form using FormTag and using its FormData to submit that form with e.g. fetch, the CSRF token will be supplied.

NOTE

AJax and CSRF is currently somewhat immature in Brut, so there may be areas where things don't work as you'd expect.

Content Security Policy headers and tools

Content Security Policy (CSP) is a way for a website to tell the browser what CSS and JavaScript is allowed to execute on the page. Most web frameworks default to a lax or no policy, which makes applying one later difficult.

Brut takes the opposite approach. By default, Brut configures Brut::FrontEnd::RouteHooks::CSPNoInlineStylesOrScripts as an after route hook. This sets the content security poilcy header to disallow all inline stylings (the style= attribute) and all inline script tags (e.g. onclick=). In development, inline styles are allowed, since they are convienient when prototyping.

Brut also configures CSP reporting, which is sent into the instrumentation system.

You can control this behavior by changing the csp_class and/or csp_reporting_class using Brut.container.override in your App. You can either create your own route hook and use that, or set either to nil to disable CSP entirely.

bundle audit

The bin/ci script provided when you created your Burt app includes a call to bundle exec bundle audit check --update, which will audit your RubyGems for versions that have known vulnerabilities. If any are found, bin/ci exits nonzero, thus failing your build.

Testing

In general, you don't want to test any of this unless you've set up something custom or complex. Testing security is done more effectively by a third party evaluating your app as a so-called "black box" or "opaque box" where its probed for issues without knowing how the app is implemented.

  • Do not disable CSRF protection.
  • Do not disable your content security policy. Use Brut's built-in and design your app to not require inline styles or scripts. It's much easier to not do this in the first place than to try to unwind it later.
  • Do not ship your app if bundle audit finds vulnerabilities.

Technical Notes

IMPORTANT

Technical Notes are for deeper understanding and debugging. While we will try to keep them up-to-date with changes to Brut's internals, the source code is always more correct.

Last Updated June 13, 2025

CSRF Protection

CSRF protection is not required for Brut-owned paths, as defined by Brut::FrontEnd::Middlewares::AnnotateBrutOwnedPaths. The reason for this is that these paths semantically should not be HTTP GETs, but are also not form submissions. They are currently used for locale detection and instrumentation, which we believe are OK to allow without CSRF protection.

This may change in the future.

Encrypted Sessions

Session cookies are set to expire after 1 year and use the value Lax for SameSite. "Lax" allows other sites to submit the Brut-powered site's cookies, but only if the user navigates to the site. They are not sent if another site submits an Ajax request. We feel this is the right tradeoff betweeen usability and security.