How to Scale AppSec with Security Gates

I was recently at the OWASP AppSec Conference in Dublin where I was attending a terrific talk by Chris Romeo about DevSecOps fails. Although I could absolutely agree with most of his points, there was just one, which I often hear in this context, that I do have a different opinion about. And that is the value of security gates.

Now, I’m well aware that security gates are not really fit into the DevOps mindset of many people, at least not at first sight. And the problem Chris probably pointed out here is that many gate implementations do in fact cause unnecessary obstructions and do not work with continuous delivery. Nevertheless, I strongly believe that security gates can not only be effective controls, but also essential ones, including for DevOps.

What is a Security Gate?

Let’s start by clarifying what security gates actually are. Unfortunately, I couldn’t find a good definition so I have to try it myself. Simply put, a security gate is a quality gate for security. It can be integrated into different phases of the software development or delivery process to ensure that a specified security policy is met before the process can proceed.

Most people probably think of security gates as something that is implemented in the build process using all kinds of security testing tools and that halts or fails a build if a certain threshold of security issues is detected. But there can be much more and better ways to do that, both automatically as well as manually in terms of required human interactions. Let me give you a few examples.

(Risk-Based) Process Gates

First of all, like quality gates, security gates can be implemented on the process level and within the project lifecycle. Especially for the initial project phase, such gates can be really useful. For instance, to ensure that a secure design review or threat modeling has been conducted before the initial coding starts or a pentest was completed and findings mitigated before the initial go-live.

After that, the security gate is often replaced by security measures that are conducted periodically or in retrospect and hence should not trouble continuous delivery. Organizations that deliver large releases may still prefer to enforce security using a gate though. In order to limit the number of gate occurrences to what is necessary from a risk perspective here, it is really helpful to assess the security risk of a particular release and only enforce the security gate when the risk exceeds a certain threshold.

The following screenshot shows an example of such a risk-based security gate that was implemented in a JIRA-based release process. It uses information from the CMDB (e.g. protection class of the application) and also from a risk form about the particular release that has to be filled out by the team lead who wants to deploy something.

Thereby, the security gate ticket is only created for a release with a particular calculated risk (e.g. >= “High”). The release cannot be deployed before the security gate ticket is closed which requires specific permission. This permission is typically assigned to a dedicated security role (e.g. a security engineer), but may also be assigned to security champions of dev teams that archived a certain maturity in terms of implemented security practices. As a result, we can use the gate to promote the implementation of security practices.

Commit Gates

The next type of security gate is one that may be often not considered as one. The idea behind it is to prevent insecure code from being committed to the SCM in the first place. There are two ways to do that:

Pre-Commit Checks are automatic scripts that verify code commits before they are accepted. Security checks that are implemented here must be almost 100% accurate because they would otherwise not work and be refused by developers. Good examples are secret scanning (tip: When you generate secrets, use certain prefixes so that you can easily identify them in the code using a RegExp), identifying the use of insecure or EOL dependencies, or insecure IaC statements (e.g. in Docker file).

Pull/Merge requests enforce that all code that is committed on the major/developer branch must be reviewed and approved by a second developer (ideally a senior one). We can use training and guidance to help developers to be able to identify security problems on the code level. Also, there are some tools that can hook into this process and validate commits automatically, e.g. to prevent insecure third-party libraries from being checked in.

Release Gates (Safety Nets)

As I’ve already mentioned above, most people probably think of security gates as something that is implemented within the software delivery pipeline using all kinds of tools such as SCA, SAST, Secret Scanning, etc (have a look at the Awesome DevSecOps page for more examples).

A common place for this, which I strongly advise against, is the build process. From my personal conviction, the main function of a security gate in the software delivery pipeline is to prevent vulnerable artifacts from being deployed, not from being built. This is an important distinction because it removes a lot of pain and unnecessary obstruction.

An important aspect to archive this is by implementing a fail-fast approach. That means that potential security problems should be identified as early as possible during development. Ideally, developers would get direct feedback when they write some insecure code or use insecure dependencies. Commit gates are one good example of this. But there are more ways to accomplish this.

For instance, using story-based threat modeling exercises, secure coding checks in IDEs, non-invasive build scans (ideally using the same checks used for the security gate), and of course guardrails. I would usually not require anything here, perhaps except commit gates, and leave that to the teams. As long as a vulnerable artifact is not deployed in prod, there is currently no imminent risk associated with it and teams can manage it as they like, e.g. by automatically creating tickets in their backlog and fixing it later (but before releasing).

In such a multi-layered approach, the security gate gets primarily the role of a safety net that should be avoided so that it does not interfere with the development or delivery process. Therefore, it’s vital that the security gate policy is always transparent to the dev teams and that they can run the same checks whenever they want during development, e.g. in their build or UI.

In the following screenshot, we see an example of a security gate implemented in SonarQube.

This approach is not only transparent to dev teams (they can always check if their code violates a security gate), but like many other modern AST tools, it also allows us to limit the scope of the gate to only new code. This could be really helpful as a starting point when you already have a large existing code base full of vulnerabilities and you want to at least ensure that new code is safe. This should of course only be a temporary solution, but it at least allows us to start.

At least in the medium term, I would be cautious to implement security gates directly using particular testing tools like Sonar though, and try to be more tool agnostic instead. One way to do this is to just check for unmanaged vulnerability tickets above a certain severity in JIRA or a Defect Dojos at the gate. The exact policy could also be strengthened based on the criticality of the application. If you are interested in implementing such vulnerability management, I recommend having a look at the latest OWASP DevSecOps Guideline or the Security Drone project.

Not all findings and vulnerabilities can (and must) be fixed before a release, but they should at least be analyzed and managed in case they’re relevant. That means that their risk and implications are understood and a decision against fixing it is approved by someone with the relevant security ownership. This is what the job of a security gate should primarily be from my personal belief.

One last benefit I’d like to point out here is that from my experience, the mere existence of security gates ensures that security is taken much more seriously during development. Perhaps not so much by developers but by product owners or managers that often prioritize other aspects over security.

Conclusion

A security gate is an important mechanism to ensure that security has been taken seriously during the development process, a release is security compliant and no critical vulnerabilities are being released, at least not without proper verification and management approval if required. There are different ways to implement it, not all of them work for all organizations and not all of them are good at all.

Security gates can work efficiently without causing unnecessary impediments, regardless of what development methodology is used. There are a couple of quality criteria, that should be considered for that:

  1. Tests should be accurate, fast, and focused only on real security concerns
  2. The existence of an exception/approval process
  3. Tool agnostic (testing tools should be able to be replaced)
  4. Tests should be based on a transparent policy that could be tested by teams

In respect of their use in the software delivery process, we should think of security gates primarily as safety nets and understand that they are part of a multi-layered approach in which the policy should always be transparent to teams so that they can run non-invasive checks continuously during development to avoid interference with a security gate when they release. In practical terms, this means that teams should be able to use the same checks (e.g. tools) to check their code whenever they want.

Then, a security gate could be a really useful and accepted mechanism that works well even in highly automated DevOps environments.

Leave a Comment