Static application security testing (SAST) is one of the most effective techniques to improve application security. The term covers a variety of testing techniques that analyze an application's source, bytecode, or binary code for security vulnerabilities. Typically, developers complete this analysis during the software development lifecycle of an application. Many SAST tools are mature, and the techniques have become central to secure coding. Source code is the most common target of SAST, but you can also utilize SAST on bytecode and binary code.
Binary scanning analyzes the binary itself or the result of disassembling or decompiling it. Scanning binaries can add a benefit, unlike source code scanning, which identifies vulnerabilities created by the compiler. On the other hand, the reports from scanning binaries have many more false positives in some cases.
In general, SAST tools may generate many false positives and require tuning. The Red Hat Security Guide provides an overview of SAST.
Why is SAST important?
As SAST tools analyze source code, they can point to the exact location of problematic statements. Dynamic application security testing (DAST) and other runtime testing can indicate an existing problem, but they might not indicate where the it is.
Additionally, SAST is a recommendation and requirement by many regulations, standards, and frameworks, including the US Executive Order on Improving the Nation's Cybersecurity, NIST's Secure Software Development Framework (SSDF), and NIST's Security and Privacy Controls for Information Systems and Organizations.
How SAST works
SAST tools parse the source code, bytecode, or binary code to identify security vulnerabilities. The following sections describe two popular techniques that search for patterns and taint analysis.
How SAST tools search patterns
A SAST tool frequently looks for patterns and has a catalog of possibly dangerous code constructs. Many tools support ad-hoc patterns too. These tools report a vulnerability whenever it finds a dangerous pattern in the source code. For example, to identify an SQL injection vulnerability in Java, the SAST scanner would search for something like the following:
String query = "SELECT username FROM users WHERE userid = " + request.getParameter("userid");
Of course, the tool needs to do the scan generically, so the patterns are generalized versions of code fragments. For example, a tool may scan for a pattern like the following, where
$ATTRIBUTE, and the arguments to
getParameter can be anything:
String query = "SELECT $COLUMN FROM $TABLE WHERE $ATTRIBUTE = " + request.getParameter(...);
This technique, unfortunately, generates many false positives.
How Taint analysis works
Taint analysis finds data that comes into the program from untrusted sources, such as user input, and marks that data as tainted. Tainted data is considered dangerous to use. Then, the tool follows this tainted data in the code to see whether any known cleaning function cleans it. The tool reports a security vulnerability if tainted data is passed as a parameter to a dangerous function (a sink) before cleaning.
Tainted analysis techniques report fewer false positives than pattern-based rules, but still may report too many false positives if the SAST scanner is not tuned. When tuning, you disallow rules that generate too many false positives and specify cleaning functions. This analysis is not a trivial effort.
Other types of SAST
Some people include Software Composition Analysis (SCA) and hardcoded secrets scanning in the concept of SAST. SCA identifies dependencies used by a code base and their versions. Then various vulnerability databases are consulted to determine whether these dependencies have known vulnerabilities.
Hardcoded secrets scanning identifies whether the source code contains secrets such as passwords, API keys, or private keys. Good security practices recommend storing secrets separately from source code, such as environment variables or a secrets management solution.
The SAST workflow
You should execute SAST tools as much to the left (at early stages) as possible in the development lifecycle of an application. Developers should build these tools into their integrated development environment (IDE) if possible. That way, they can see potential issues in the source code and fix them as the developers code.
Another place to execute SAST tools is when a developer creates a pull or merge request. If the ruleset used by the tool is mature enough, you should add the findings as comments to the commit and block the pull request until you fix the vulnerabilities.
It is challenging to completely eliminate false positives in the real world. So organizations could establish a threshold whereby a pull request is blocked only by matches made by mature or high-severity rules.
It is more manageable to enable only a few rules when initiating a SAST program so that you can develop as many findings and false positives as you can handle. If you enable all the rules from the beginning, you will have so many false positives that you may give up executing the SAST tool or ignore the findings.
The languages SAST tools support
Considering multi-language open source SAST tools, we would like to highlight Semgrep and Joern. Both tools are designed to integrate easily into continuous integration/continuous delivery (CI/CD) pipelines.
Static application security testing is a worthwhile investment
Static application security testing (SAST) is an excellent technique for identifying security vulnerabilities in applications, but a significant effort is required to tune SAST tools to make them more usable. The investment in developing a successful SAST program should not be underestimated. If the program is implemented properly, the software's security improves significantly.
We welcome your questions and feedback in the comments section below.