CodeQL Integration
What This Does
Sets up GitHub's CodeQL for automated static analysis security testing (SAST) in CI/CD pipelines. Covers initial configuration, language setup, custom query writing, alert triage, and integration with PR workflows. CodeQL finds vulnerabilities by analyzing code as data — modeling data flow from sources (user input) to sinks (dangerous operations).
Instructions
Assess the codebase. Determine:
- Languages used (CodeQL supports: JavaScript/TypeScript, Python, Java, C/C++, C#, Go, Ruby, Swift, Kotlin)
- Repository hosting (GitHub.com, GitHub Enterprise, or other)
- Existing CI/CD pipeline
- Current security scanning tools
Set up CodeQL in GitHub Actions.
# .github/workflows/codeql.yml
name: "CodeQL"
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * 1' # Weekly Monday 6am
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ['javascript-typescript']
# Add more: 'python', 'java-kotlin', 'go', 'ruby', etc.
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
queries: security-extended
# Options: security-extended, security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{ matrix.language }}"
Choose the query suite.
| Suite |
Coverage |
False Positives |
Use When |
default |
Standard security queries |
Low |
Starting out |
security-extended |
Expanded security coverage |
Medium |
After triaging defaults |
security-and-quality |
Security + code quality |
Higher |
Comprehensive scanning |
Write custom CodeQL queries. For project-specific patterns:
/**
* @name Unvalidated user input in database query
* @description User input flows to a database query without validation
* @kind path-problem
* @problem.severity error
* @security-severity 8.0
* @id js/custom/sql-injection
*/
import javascript
import semmle.javascript.security.dataflow.SqlInjectionQuery
import DataFlow::PathGraph
from SqlInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(),
"user-provided value"
Configure alert management.
- Enable code scanning alerts in repository settings
- Set up branch protection rules to require CodeQL checks
- Configure alert dismissal policy (who can dismiss, what reasons are valid)
- Set up Slack/email notifications for new critical alerts
Integrate with PR workflow.
# Add to branch protection rules:
# - Require status checks: "CodeQL"
# - Require code scanning alerts to be resolved
# In the workflow, add PR comment with results:
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: results.sarif
Triage initial results. On first run, expect many findings:
- Start with CRITICAL and HIGH severity
- Dismiss false positives with a reason (improves future scans)
- Create issues for true positives
- Adjust query configuration to reduce noise
Output Format
# CodeQL Setup: {Repository}
## Configuration
- Languages: {list}
- Query suite: {suite}
- Trigger: {push to main, PRs, weekly schedule}
## Workflow File
{Path to the committed workflow YAML}
## Custom Queries
| Query | Description | Severity |
|-------|-------------|----------|
| {name} | {what it finds} | {severity} |
## Branch Protection
- [ ] CodeQL check required for PRs to main
- [ ] Alert dismissal requires review
## Initial Findings
| Severity | Count | Action |
|----------|-------|--------|
| Critical | {n} | Fix immediately |
| High | {n} | Fix this sprint |
| Medium | {n} | Schedule |
| Low | {n} | Backlog |
Tips
- Start with the
default query suite — it has the best signal-to-noise ratio
- CodeQL runs on every PR by default — if scan time is too long, limit to push-to-main + weekly schedule
- Custom queries are powerful but complex — start with the built-in queries before writing custom ones
- The
security-extended suite catches more issues but requires more triage effort
- CodeQL is free for public repositories and included with GitHub Advanced Security for private repos
- Use
codeql-action/autobuild for most languages — manual build steps are rarely needed for JS/Python
- Alert trends over time are more useful than absolute counts — track whether findings are increasing or decreasing
1---2name: codeql-integration3description: Set up CodeQL for automated security analysis in CI/CD pipelines with custom queries and alert management.4---56# CodeQL Integration78## What This Does910Sets up GitHub's CodeQL for automated static analysis security testing (SAST) in CI/CD pipelines. Covers initial configuration, language setup, custom query writing, alert triage, and integration with PR workflows. CodeQL finds vulnerabilities by analyzing code as data — modeling data flow from sources (user input) to sinks (dangerous operations).1112## Instructions13141. **Assess the codebase.** Determine:15 - Languages used (CodeQL supports: JavaScript/TypeScript, Python, Java, C/C++, C#, Go, Ruby, Swift, Kotlin)16 - Repository hosting (GitHub.com, GitHub Enterprise, or other)17 - Existing CI/CD pipeline18 - Current security scanning tools19202. **Set up CodeQL in GitHub Actions.**2122 ```yaml23 # .github/workflows/codeql.yml24 name: "CodeQL"2526 on:27 push:28 branches: [main]29 pull_request:30 branches: [main]31 schedule:32 - cron: '0 6 * * 1' # Weekly Monday 6am3334 jobs:35 analyze:36 name: Analyze37 runs-on: ubuntu-latest38 permissions:39 actions: read40 contents: read41 security-events: write4243 strategy:44 fail-fast: false45 matrix:46 language: ['javascript-typescript']47 # Add more: 'python', 'java-kotlin', 'go', 'ruby', etc.4849 steps:50 - name: Checkout repository51 uses: actions/checkout@v45253 - name: Initialize CodeQL54 uses: github/codeql-action/init@v355 with:56 languages: ${{ matrix.language }}57 queries: security-extended58 # Options: security-extended, security-and-quality5960 - name: Autobuild61 uses: github/codeql-action/autobuild@v36263 - name: Perform CodeQL Analysis64 uses: github/codeql-action/analyze@v365 with:66 category: "/language:${{ matrix.language }}"67 ```68693. **Choose the query suite.**7071 | Suite | Coverage | False Positives | Use When |72 |-------|----------|----------------|----------|73 | `default` | Standard security queries | Low | Starting out |74 | `security-extended` | Expanded security coverage | Medium | After triaging defaults |75 | `security-and-quality` | Security + code quality | Higher | Comprehensive scanning |76774. **Write custom CodeQL queries.** For project-specific patterns:7879 ```ql80 /**81 * @name Unvalidated user input in database query82 * @description User input flows to a database query without validation83 * @kind path-problem84 * @problem.severity error85 * @security-severity 8.086 * @id js/custom/sql-injection87 */8889 import javascript90 import semmle.javascript.security.dataflow.SqlInjectionQuery91 import DataFlow::PathGraph9293 from SqlInjection::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink94 where config.hasFlowPath(source, sink)95 select sink.getNode(), source, sink, "This query depends on a $@.", source.getNode(),96 "user-provided value"97 ```98995. **Configure alert management.**100 - Enable code scanning alerts in repository settings101 - Set up branch protection rules to require CodeQL checks102 - Configure alert dismissal policy (who can dismiss, what reasons are valid)103 - Set up Slack/email notifications for new critical alerts1041056. **Integrate with PR workflow.**106 ```yaml107 # Add to branch protection rules:108 # - Require status checks: "CodeQL"109 # - Require code scanning alerts to be resolved110111 # In the workflow, add PR comment with results:112 - name: Upload SARIF113 uses: github/codeql-action/upload-sarif@v3114 with:115 sarif_file: results.sarif116 ```1171187. **Triage initial results.** On first run, expect many findings:119 - Start with CRITICAL and HIGH severity120 - Dismiss false positives with a reason (improves future scans)121 - Create issues for true positives122 - Adjust query configuration to reduce noise123124## Output Format125126```markdown127# CodeQL Setup: {Repository}128129## Configuration130- Languages: {list}131- Query suite: {suite}132- Trigger: {push to main, PRs, weekly schedule}133134## Workflow File135{Path to the committed workflow YAML}136137## Custom Queries138| Query | Description | Severity |139|-------|-------------|----------|140| {name} | {what it finds} | {severity} |141142## Branch Protection143- [ ] CodeQL check required for PRs to main144- [ ] Alert dismissal requires review145146## Initial Findings147| Severity | Count | Action |148|----------|-------|--------|149| Critical | {n} | Fix immediately |150| High | {n} | Fix this sprint |151| Medium | {n} | Schedule |152| Low | {n} | Backlog |153```154155## Tips156157- Start with the `default` query suite — it has the best signal-to-noise ratio158- CodeQL runs on every PR by default — if scan time is too long, limit to push-to-main + weekly schedule159- Custom queries are powerful but complex — start with the built-in queries before writing custom ones160- The `security-extended` suite catches more issues but requires more triage effort161- CodeQL is free for public repositories and included with GitHub Advanced Security for private repos162- Use `codeql-action/autobuild` for most languages — manual build steps are rarely needed for JS/Python163- Alert trends over time are more useful than absolute counts — track whether findings are increasing or decreasing