Skip to main content

Overview

CodeQL builds a relational database from the entire codebase, then runs QL queries against it. This enables deep semantic analysis including cross-file data flow tracking, import analysis, and type hierarchy queries.

Capabilities

  • Cross-file data flow and taint tracking
  • Control flow analysis across function boundaries
  • Import and type hierarchy queries
  • Security, correctness, and maintainability checks
  • Supports C/C++, C#, Go, Java/Kotlin, JavaScript/TypeScript, Python, Ruby, Rust, Swift

Limitations

  • Requires a build process for compiled languages
  • Not applicable to infrastructure or runtime concerns — check out InSpec, Checkov, or Goss for infrastructure validation
  • Not suited for file organization/existence checks

Generated Format

  • Language: CodeQL (QL)
  • Structure: Query files with metadata block (@id, @name, @kind, @problem.severity or @security-severity) and from-where-select clauses
  • Execution: Requires CodeQL CLI and a database built from the codebase

Example Guardrail

/**
 * @name SQL injection from user input
 * @description Untrusted data flows to SQL query
 * @kind path-problem
 * @id custom/sql-injection
 * @security-severity 9.0
 * @precision high
 * @tags security
 */

import python
import semmle.python.dataflow.new.TaintTracking

module SqlInjectionConfig implements DataFlow::ConfigSig {
  predicate isSource(DataFlow::Node source) {
    source.asExpr().(Call).getTarget().getName() = "input"
  }

  predicate isSink(DataFlow::Node sink) {
    sink.asExpr().(Call).getTarget().getName() = "execute"
  }
}

module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;
import SqlInjectionFlow::PathGraph

from SqlInjectionFlow::PathNode source, SqlInjectionFlow::PathNode sink
where SqlInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Untrusted input flows to SQL query"
Learn more at CodeQL documentation, writing queries, and query metadata.