Introducing Dlint - Robust Static Analysis for Python
It’s no secret that we love Python here at Duo. Every day, our engineering team is pushing new code that drives our products to help keep our customers secure.
One of our primary goals as an Application Security team is to work alongside our engineers to ensure that the code we’re developing is as secure as possible. We want to provide feedback quickly – giving engineers near-immediate feedback if any issues are found and guiding them toward improvements that can be made to better ensure the security of our product.
One way we accomplish this is by using an internal tool we developed called Dlint to perform static analysis every time a new commit is pushed. Today, we’re excited to open-source Dlint, making it available to the wider community.
But before diving into what Dlint does, let’s first talk a little bit about static analysis.
Introduction to Static Analysis
The goal of static analysis is to search through code and identify potential problems. This is an effective way to find issues in the code at a low cost compared to dynamic analysis, which involves executing the code. However, running effective static analysis requires overcoming a few challenges.
First, we have to figure out what to look for. There are quite a few dangerous uses of Python that would apply almost anywhere. For example, you would almost never want to pass untrusted input into a call to os.system. In addition to this, we have Duo-specific rules to make sure that our internal libraries are used in a secure way.
After we know what to look for, we need a way to look for it. The simplest form of static analysis would be search through the code line-by-line for specific strings. However, we can take this a step further by parsing the abstract syntax tree, or AST, of the code to make more informed and complex queries.
Once we have the ability to perform analysis, we need to determine when to run the checks. We believe in providing tooling that can run both locally as the code is being developed to provide quick feedback, as well as in our continuous development pipeline before code is merged into our codebase.
Dlint, our approach to Python static analysis, aims to solve all of these problems and more.
Dlint comprises a set of rules that define what we want to look for, and a linter, which is able to evaluate those rules over our codebase.
For this initial release, Dlint contains a set of rules that check for common best-practices when it comes to writing secure Python. We’ve also made it easy to add new rules that can be contributed back to the community.
To evaluate these rules over our codebase, Dlint leverages Flake8. This approach lets Flake8 do the heavy-lifting of parsing Python’s AST, letting us focus on writing a robust ruleset and giving great recommendations.
Finally, to support running Dlint as part of a development pipeline, we’ve included examples of how you could run Dlint in Gitlab and Travis CI.
Get the Code
We’re excited to share Dlint with the wider security community. By working together, we can create a common set of rules that anyone can use to help increase the quality of their codebase.
If you want to give Dlint a shot for your projects, you can find the code on Github.
We’re excited to share more about how we do AppSec at Blackhat USA 2019, so we hope to see you there!
Finally, if this is the kind of work that interests you, we are hiring! Get in touch!