I recently sat down with Sr. Research Lead at Synopsys and framework specialist, Ksenia Peguero, on Episode 2 of the AppSec Builders Podcast. In the episode, “Framework Security with Ksenia Peguero: Paved Road Foundation”, we discussed how to upgrade your security through your frameworks using the Paved Road foundation. In this post, I wanted to share some learnings from that discussion.
The Security Paved Road
Legacy security approaches were built as gatekeepers. Today, the challenge that any security team faces is to enable developers to ship things as quickly and efficiently as possible, while maintaining an appropriate level of security. One of the ways to enable this is through building tools and processes to ensure that developers can build secure things by default. Of course, those tools and processes need to be super close to the developer’s workflow in order to be adopted. This is called the Security Paved Road.
An ideal Paved Road would allow engineers to be fully autonomous in deployment with little to no bottlenecks from security teams.
The Security Paved Road was originally coined by Netflix Security and Engineering teams to drive adoption of their default security controls and enable developers to release quality software at a high velocity.
Using frameworks to implement your Security Paved Road
The framework level is an ideal place to implement plenty of the Security Paved Road best practices. The security team can, for instance, ensure that the examples to kick off new API endpoints are aligned to security standards, or that the way that new services are created uses the right framework template.
For most companies using a distributed architecture, where new services are regularly created, strong security foundations can be achieved by using a template. Teams can clone this template each time they prepare a new service (whether it’s a monolith, a microservice, a serverless function, etc.) to reduce risk without disrupting the developer’s workflow.
While each framework is different, there are several common dimensions security teams can influence to help developers get the most out of them.
Framework security dimensions
Some frameworks are very opinionated (e.g. Ruby on Rails, Django, Sails), while others offer a wider degree of flexibility to the developers (e.g. Express or Flask). The security team has to recommend extensive best practices to security owners that align with the framework in question (e.g. how to access data stores, how to validate input, or how to perform requests to external services).
Most frameworks have extensive security options. Some of them have secure defaults, while others don’t. Some depend on your architecture. The security team should harden the framework configuration by enforcing the defaults to their secure mode, e.g. default CSRF protection, or prevent user controlled serialized sessions) regardless of which framework is used.
This is also the right time to thoroughly read the security elements of the framework’s documentation.
Authentication and authorization
The security team should also implement best practices around authentication and authorization. At a minimum, the team should define a standard library for authentication, such as Devise or Passeport, and for authorization, such as CanCanCan.
The framework as a place to enforce company standards
Using a framework foundation has many benefits, that go way beyond security. Having coherent deployments across services, a common place where ops and other teams can improve and populate with best practices over time is extremely valuable. For instanc,e a good practice to identify repository owners is to use a CODEOWNERS file (Github, Gitlab). This will help Ops teams find out who they should call when a service is failing. This can be enforced in the CI. Such mechanisms make the Paved Road a benefit for the entire company. Examples could be using the right logging framework, the right audit log, etc.
CI around the framework
On top of building secure defaults, the security team can leverage the CI to ensure that secure defaults don’t drift away from the initial configuration, both at the code and configuration levels. The CI can not only spot security issues but also help enforce coding best practices, such as warning a developer when they are using a known dangerous method (e.g. unescaped templates, raw database queries, calls to external services without using an SSRF safe library, etc.). It can also check that known best practices are enforced, such as ensuring that a validation library is called in any API endpoint, or links in static HTML use the noopener attribute.
Security-specific static analysis tools such as Semgrep have been built with such use cases in mind.
Framework security history
Some frameworks have a lengthy security history and promptly react to vulnerability reports. Others have such a small attack surface that they rarely suffer from vulnerabilities. Security teams should monitor the right channels to be informed early of framework vulnerabilities, so they can patch anything that arises quickly.
The security coverage and functions of a framework can be very deep or very light from one framework to another. As is often the case with security, extensiveness comes at the cost of complexity. Complexity increases the attack surface, and paradoxically, brings security challenges. The paradox fades when considering that the challenges of integrating external libraries or solutions are much harder to do than enabling things that are integrated within the framework – while adding a similar attack surface.
Choosing the right framework, or building the right secure defaults for your existing frameworks, is often the most impactful way to guide your company developments in a secure direction.
Want more? Listen to the full AppSec Builders episode of “Framework Security with Ksenia Peguero: Paved Road Foundation” on any streaming platform.