The 2016 State of Devops Report from Google concludes that high-performing teams spend 50% less time remediating security issues than low-performing teams. They do this by following the “shift left” principle, integrating information security objectives into daily work. Shifting left means taking tasks that traditionally happened at the end of the development cycle and instead doing them as early and as often as possible.
The most obvious example of a shift-left success story is testing. The pendulum has swung from the waterfall model, where testing occurred after development was “complete” all the way to Test Driven Development, where tests are written before development even begins. Developers are now accustomed to running unit tests as a normal part of their local build process, and as part of an automated CI solution as well.
Security testing has unfortunately been left out of this change, in many cases. For too many developers, security testing remains a hurdle that must be cleared after development is “complete” in much the same way that quality assurance testing once was. Security vulnerabilities discovered at the end of the lifecycle are both expensive and difficult to fix, and are often not fixed at all in order to get to market.
The solution to the issue is essentially the same as with testing: shift security testing left, closer to the development teams, with tools and automation that make it part of their daily routine.
Here are a few steps you can take to improve your existing application security testing process.
Use IDE Plugins
Secure coding practices can and should start right in the developer’s integrated developer environment (IDE). Realtime source code analysis is already part of most IDEs, which allows for syntax and other errors to be highlighted for developers in their code as they type it. Static Application Security Testing (SAST) is just another flavor of source code analysis, and is increasingly available in the form of IDE plugins.
Surfacing security issues this early in the development cycle means that developers are not blindsided by a security review after they consider their code complete. It decreases time to market, and makes vulnerabilities less expensive to remediate because they can be fixed before they enter the QA cycle. It also has the benefit of educating developers about secure coding, which will help them avoid making similar mistakes again in the future.
When security vulnerabilities are found at the end of the development cycle, the remediation often resembles a hack more than secure design, or in many cases is added to the backlog to be addressed at a later date, resulting in the deployment of insecure software.
A wide variety of both commercial and open source SAST IDE plugins are available. Open source examples include sonarlint, which works with most popular IDEs. For Visual Studio Code, the OpenAPI Editor plugin can can run an API Contract Security Audit. If your app is written in Java, Find Security Bugs also supports most IDEs and testing frameworks.
Commercial options are available from Puma Scan, Veracode, Code Dx and many more.
The IEEE and OWASP provide more comprehensive lists of SAST tools that can be used as IDE plugins, as well as criteria for helping you select the tool most appropriate to your workflow.
Security testing performed in this early phase of development should strongly favor speed over comprehensive analysis. More in-depth testing can come later in the process in steps that are run less frequently. The goal is to enable developers to find security issues early and easily, instead of hindering them by slowing down their build process. Tests that take longer than a typical suite of unit tests should wait for a later state in the pipeline (e.g., where integration tests are typically run).
Use Pre-Commit Hooks
When IDE integration isn’t available, or for more time-consuming scans, consider using a pre-commit hook. Pushes to source control repositories happen less frequently than builds, and are a good place to run checks that take too long to integrate with the regular build process.
Git hooks are available in several different stages of the source control process, and trigger arbitrary scripts. This makes integration possible with a wider variety of tools.
Pre-commit hooks also provide you the ability to effectively “break the build” if certain types of vulnerabilities are identified. Preventing developers from committing code that contains these issues forces them to be addressed early, and is much more likely to produce high quality remediation in the form of better application design. Tools run at this stage can also check for hard-coded secrets, preventing those from being sent to a shared repository and possibly leaked.
Run Deeper Checks in CI
Once code has passed pre-commit checks and has been pushed to a source repository, more comprehensive checks can be performed as part of your Continuous Integration (CI) pipeline. Running multiple types of security assessment is considered best practice, and this is the ideal place to integrate other types of testing like DAST and dependency checks.
DAST
The SAST tools run earlier in the process are a form of “white box” testing that uses static analysis of source code to find weaknesses such as the OWASP Top 10. In contrast, Dynamic Application Security Testing (DAST) is a “black box” form of behavioral testing that tests a running application. It can help identify the kind of runtime vulnerabilities that SAST can not.
Many CI pipelines already deploy compiled artifacts to testing environments after building them, which makes it a great place to run DAST tools against those environments automatically, along with your other automated test suites.
As with SAST tools, a variety of both commercial and open source DAST options are available. Popular open source options include the OWASP Zed Attack Proxy (ZAP) and Arachni. Commercial solutions are available from snyk, Veracode, Fortify, and many more. Most of these tools are available as plugins for Jenkins, GitHub Actions, CircleCI, etc. for easy integration into your existing process. A much more comprehensive list of vulnerability scanners is also available from OWASP.
Dependency Checks (SCA)
Open source components are the primary building blocks of most modern software, and vulnerabilities introduced by library dependencies are often overlooked. Using components with known vulnerabilities is one of the OWASP Top 10, but tools that do exhaustive checks of this sort are too time consuming to run earlier in the SDLC.
Software Composition Analysis (SCA) is a process that checks the open source libraries used by your application for known vulnerabilities, as well as the additional libraries transitively used by them, and so on. GitHub provides Dependabot, which is a great option. OWASP provides an open-source tool called Dependency-Check as well as a comprehensive guide to selecting an SCA tool, and there are commercial offerings from snyk and many others.
Aggregate and De-duplicate
Unlike unit and integration tests, which provide a simple pass/fail when run against application code, security vulnerability scanners produce findings in the form of known vulnerabilities that are classified with varying levels of severity.
It’s up to your application security team to make the call about what needs to be remediated, and what risk can be accepted, but you can make the task easier for everyone involved by aggregating the results and displaying them in a vulnerability dashboard.
Vulnerability management tools like OWASP’s DefectDojo or ThreadFix integrate with many security scanning tools, automatically remove many duplicates, and present a convenient dashboard for your application security team to manage the vulnerabilities that are found. These tools also allow you to collect metrics about what vulnerabilities are found over time.
Provide Automated Feedback
Finally - information about the results of the various security tools run throughout the pipeline should be fed back to developers automatically via the normal communications channels they use to manage their projects.
For example, if your pipeline identifies a vulnerability that requires a fix and your development team uses Jira, have a ticket automatically filed in Jira so the team can easily integrate the fix with their normal workflow. Slack or other realtime team communication tools are also a great way to notify developers of findings, provided the signal to noise ratio can be kept to a useful level.
A fully functional application security pipeline involves a lot of moving parts and can be as complicated as you care to make it. Hopefully the above provides some simple, actionable steps you can take to incrementally improve whatever application security process you already have in place.