An abstract syntax tree (AST) is a tree that represents the structure of source code: statements, calls, names and values as nodes. Static analysis rules use it because a rule can match a function call as a call, ignoring comments, whitespace and line breaks that make regex patterns brittle.
Definitions
- Parser: turns source text into a tree.
- AST: the tree. Each node has a type, such as a call or a variable declaration, and children.
- Visitor: code that walks the tree and runs a function for each node type of interest.
- Rule: a visitor plus a decision about what to report.
Python's own documentation describes its ast module as helping programs process trees of the Python abstract syntax grammar, and notes that the grammar can change with each Python release. ESLint rules work on the ESTree format and are called as the engine goes down and up the tree.
Where regex breaks
Suppose you want to catch calls to a dangerous function called runShell. A regex such as runShell followed by an open parenthesis finds the obvious case and also finds these:
- a comment that mentions runShell(
- a string that contains the text
- a different function named myrunShell
It misses a call split across lines, or one that is written with extra whitespace. An AST rule asks a precise question instead: is this node a call whose callee is the name runShell?
Side by side
| Question | Regex | AST rule |
|---|---|---|
| Ignores comments and strings | Only with care | Yes, by construction |
| Handles line breaks and spacing | Needs pattern tweaks | Yes |
| Knows the argument is a literal | No | Yes, node type says so |
| Easy to write for a one-off | Yes | Takes longer |
| Language aware | No | Yes |
| Follows values across files | No | Not by itself |
The last row matters. An AST is a picture of one file's structure. Tracing a value from user input to a dangerous call across functions needs data flow analysis on top, and not every rule engine does that.
When regex is still fine
Regex is reasonable for text that has no structure to parse: a leaked token format, a banned license string in a manifest, a TODO marker. OWASP's source code analysis page lists the same kinds of tradeoffs, noting that static tools scale well and highlight the exact file and line, while also noting high false positive counts and limits on finding some classes of flaw.
How to see a tree
- Take a small snippet of the code you want to catch.
- Print its tree. In Python, ast.dump on the result of ast.parse shows the node names. For JavaScript, ESLint's Code Explorer shows the tree.
- Write down the node types and the field that distinguishes unsafe from safe.
- Write the rule against those node types.
Try it yourself
Click through it at your own pace, or open it full screen.
Look at how each finding points to a precise file and line. That precision comes from a parsed tree.
Quick check
Is an AST the same as a call graph?
No. An AST describes the syntax of one piece of code. A call graph describes which functions can call which, and is built from many ASTs.
Does the AST change between language versions?
It can. Python's documentation says the abstract syntax may change with each release, so rules that depend on node shapes need testing on each new version.
Safeguard's scanning covers dependencies and SBOMs, and its reachability analysis helps show which findings your code can actually call. You can run a free scan on a repository.
Sources
Last reviewed: 19 October 2026.