Cybersecurity research podcast
Modeling and Discovering Vulnerabilities with Code Property Graphs
Yamaguchi and colleagues combined source syntax, control flow, and program dependencies in a queryable code property graph, then used traversals to identify 18 previously unknown kernel vulnerabilities that developers addressed. Analysts can refine these traversals to balance false alarms against missed findings, but static analysis cannot cover runtime-dependent behavior, and this implementation analyzed within individual functions rather than across calls.
Episode 25 Aug 2026 · Paper 17 May 2014 · 35th IEEE Symposium on Security and Privacy · VERSION of RECORD
Research summary
A technical explanation of the paper's research question, method, reported findings and limitations. Applied to the Linux kernel, the traversals identified 18 previously unknown vulnerabilities that developers addressed. The buffer-overflow case study returned 11 functions and seven vulnerabilities. The approach therefore surfaced actual flaws in the…
The 2014 paper made syntax, control flow, and data dependencies jointly queryable, directly shaping Joern and ShiftLeft/Qwiet. The abstraction scaled across tools and languages, but semantic accuracy still depends on frontends, builds, frameworks, and dependencies. The strongest successor would ground constrained LLM assistance in deterministic graph queries, build provenance, runtime evidence, and unseen confirmed vulnerabilities.
Paper details
Authors: Fabian Yamaguchi , Nico Golde , Daniel Arp , Konrad Rieck
Transcript
Highlighting follows the podcast. Select any word to seek.
Modeling and Discovering Vulnerabilities with Code Property Graphs. Fabian Yamaguchi and colleagues presented this work at the IEEE Symposium on Security and Privacy in 2014. They joined source syntax, control flow, and program dependencies in a code property graph, then used composable graph traversals to describe vulnerability patterns. The practical question is whether defenders can search a large program for those patterns and refine the search when it returns too many or too few candidates.
A code property graph brings syntax, control flow, and program dependencies together in one property graph. Composable graph traversals then express vulnerability descriptions across those three views.
Taken together, the design and evaluation test two linked questions. Can vulnerability descriptions be expressed as reusable paths through syntax, execution order, and dependencies? And can those descriptions be run against a kernel-sized codebase while remaining adjustable by an analyst? The representation is not limited to a single fixed detector. Analysts can refine a traversal and consciously manage the tradeoff between irrelevant candidates and vulnerabilities that the query may miss.
The method combines syntax, control flow, and program dependencies in a property graph. Composable graph traversals express vulnerability descriptions across those views. For the coverage study, the researchers mapped 88 vulnerabilities into 12 types. The merged representation modeled 10 of those types.
Applied to the Linux kernel, the traversals identified 18 previously unknown vulnerabilities that developers addressed. The buffer-overflow case study returned 11 functions and seven vulnerabilities. The approach therefore surfaced actual flaws in the evaluated kernel. A returned function is still only a candidate, because static analysis cannot prove that arbitrary candidate code contains a vulnerability.
The kernel graph represented roughly 1.3 million lines of source code, and importing it took about 110 minutes. Once loaded, the evaluated traversals ran in under 40 seconds from a cold start. In this evaluated setup, importing the representation took longer than executing an individual traversal.
Static analysis cannot cover behavior that depends on runtime state or prove that arbitrary candidate code is vulnerable. The implementation examined relationships within individual procedures and deferred analysis across procedures. As a result, flows crossing function boundaries were outside the evaluated implementation. The analysis does not establish complete ground truth for every vulnerability in a program.
Operationally, detection engineers can treat a traversal as an inspectable, adjustable search rule. Refining it lets them choose between accepting more irrelevant candidates and risking more missed findings. Returned code should still be validated rather than treated as an exploitability verdict. Patterns that depend on live runtime conditions or data moving across function calls also require evidence beyond what this implementation evaluated. The graph helps structure the search; it does not remove the need to reason about what the program actually does.
Yamaguchi and colleagues combined syntax, control flow, and program dependencies in one property graph. Their composable traversals expressed vulnerability descriptions across those views and surfaced previously unknown kernel vulnerabilities that developers addressed. Security teams considering this approach should treat matches as candidates. Static analysis cannot prove that arbitrary candidate code is vulnerable or cover runtime-dependent behavior. Teams should also account for the evaluated implementation’s restriction to analysis within individual procedures.