# aurora-lint
A static analysis tool for C code compliance with [SEI CERT C Coding Standards](https://cmu-sei.github.io/secure-coding-standards/sei-cert-c-coding-standard). aurora-lint tracks 311 CERT C rules across 17 categories (307 implemented and enabled by default), with a CI/CD-ready command-line interface and an optional interactive terminal UI.
## Does It Find Real Bugs?
Yes, in shipping software. Nine defects found while auditing SQLite were
reported upstream, and **the SQLite team confirmed and fixed all nine the
same day they were filed**:
| `src/os_kv.c` — `kvvfsDecode()` | Heap buffer overflow: the hex-pair decode branch writes without the bounds check its sibling branch has (check-in `732c8f81b5`) | [afbc56be7b](https://sqlite.org/bugs/forumpost/afbc56be7b) |
| `ext/fts5/fts5_index.c` — `fts5SegmentSize()` | Signed integer overflow on page numbers decoded from an on-disk record with no upper bound validated (check-in `c97a940ceb`) | [2026-08-17](https://sqlite.org/bugs/info/2026-08-17T20:07:33Z) |
| `ext/fts5/fts5_index.c` — `fts5TestUtf8()` | UTF-8 validator advances 3 bytes through a 4-byte sequence, so every valid astral-plane character is rejected (check-in `ac094ec69b`) | [b02657db71](https://sqlite.org/bugs/forumpost/b02657db71) |
| `ext/session/changeset.c` | `sqlite3_mprintf()` result passed to libc `printf`'s `%s`, bypassing SQLite's own NULL-safe `mprintf` — NULL dereference under allocation failure | [f20ea456ac](https://sqlite.org/bugs/forumpost/f20ea456ac) |
| `expert.c` | same defect | [c06a3c0d3f](https://sqlite.org/bugs/forumpost/c06a3c0d3f) |
| `amatch.c` | same defect | [20d89d613b](https://sqlite.org/bugs/forumpost/20d89d613b) |
| `sqlite3_stdio.c` | same defect | [ba00fdddda](https://sqlite.org/bugs/forumpost/ba00fdddda) |
| `fts3.c` | same defect | [9b4276628a](https://sqlite.org/bugs/forumpost/9b4276628a) |
| `qrf.c` | same defect | [18338dc19d](https://sqlite.org/bugs/forumpost/18338dc19d) |
**Eight of the nine started as an aurora-lint finding** — an EXP34-C, INT32-C or
MSC12-C violation that hand-adjudication then confirmed against the source.
The `kvvfsDecode()` overflow did not: aurora-lint does not flag that site. It was
found by the close reading that reviewing aurora-lint's findings prompted, which
makes it a false negative for the tool. It is listed because it is an honest
account of what the audit produced, not a detection to claim.
All nine came out of a file-at-a-time audit of SQLite — 220 files at a pinned
commit, every finding hand-adjudicated — the same audit behind the real-world
precision figure below. Methodology:
[`docs/testing-methodology.rst`](docs/testing-methodology.rst).
## Why CERT C
aurora-lint targets the [SEI CERT C Coding
Standard](https://cmu-sei.github.io/secure-coding-standards/sei-cert-c-coding-standard)
rather than MISRA C, and that is a deliberate fit-to-domain choice rather than
a fallback.
**CERT C is open.** The standard is public and freely implementable, so the
rules a tool enforces can be read, argued with, and checked against the
analyzer's behaviour by anyone. Every rule aurora-lint implements cites its CERT C
entry, and the false-positive work in this repo is legible for the same
reason — you can look up what the rule actually says.
**The overlap with MISRA is strong.** The two standards address the same
defect classes for the most part; CERT C reaches further into security
(untrusted input, integer conversion, resource lifetime) while MISRA reaches
further into language-subsetting discipline.
**The remaining difference is process, not coverage.** MISRA's extra apparatus
— mandatory/required/advisory categories, language subsetting, a
certification-oriented deviation process — exists to satisfy a certification
body. aurora-lint does not implement that apparatus, which is a statement about what
aurora-lint is, not about who should use it: **nothing here is domain-restricted.**
If you write C for automotive, medical or aerospace, these rules apply to your
code exactly as they do to anyone else's, and aurora-lint is usable alongside whatever
MISRA tooling your certification process requires.
Two rules from NASA JPL's Power of Ten are also implemented alongside CERT C
(`BRULE-060` no dynamic allocation after initialisation, `BRULE-065` no
excessive pointer indirection). See
[`docs/future-rulesets.rst`](docs/future-rulesets.rst) for other open
standards that could be added and why they were not needed first.
## What Makes It Different
**No build system. No compilation. No `compile_commands.json` required.** Point
aurora-lint at a directory of C source and it analyses it. It parses with tree-sitter
rather than driving a compiler, so it needs neither your toolchain, your
headers, your defines, nor a working build — which means it runs on code you
*cannot* build: a partial checkout, a vendored tree, a CI job with no
cross-compiler installed, or a file an AI just generated. It will happily use
`compile_commands.json` and `-I`/`-D` flags when given them, for better
cross-file context; it just does not depend on them.
That is the trade it makes. Without a preprocessor, aurora-lint reasons about source
as written, which is why it has its own macro-expansion engine and why the
false-positive work in this repo is as substantial as the rule work.
**Imperfect on purpose, and measured about it.** aurora-lint reports every rule
violation as written rather than guessing which ones you meant, so it produces
false positives — the precision and recall above are measured against a
hand-adjudicated oracle, not asserted. What makes that workable is that the
noise judgement is yours: per-project rule manifests
([configuration](docs/configuration.rst)), inline and file-scoped
[suppression](docs/suppression.rst), and severity thresholds, so you tune it
to your codebase instead of accepting one global verdict. That same property
is what makes it cheap to drop into a CI gate or an AI-assisted development
loop as a repeated check.
**Scope: C.** aurora-lint analyses `.c` and `.h` against CERT C. It is not a C++
checker — it recognises C++ constructs only well enough to avoid reporting
nonsense on a C++ header it encounters.
## Key Features
- **307 CERT C rules** implemented and enabled by default (311 tracked; see [Configuration](docs/configuration.rst) for the 4 tracked but not yet implemented) across 17 categories (API, ARR, CON, DCL, ENV, ERR, EXP, FIO, FLP, INT, MEM, MSC, POS, PRE, SIG, STR, WIN)
- **Optional interactive terminal UI** for browsing and managing violations (build with `--features tui`)
- **Multiple export formats**: CSV, XLSX, JSON, SARIF 2.1.0
- **CI/CD ready**: exit codes, severity thresholds, diff-only mode, SARIF output
- **Cross-file analysis**: pre-scans directories for function definitions to reduce false positives
- **Fast**: tree-sitter based parsing with control-flow graphs and inter-procedural reasoning
## How Well Does It Work?
Measured, not asserted. Two benchmarks, both with published methodology.
| **Juliet Precision** | 87.1% (v0.4.321) |
| **Juliet CWEs Scanned** | 75 (fast mode, CWE-matched rules) |
| **100% Precision CWEs** | 43 (zero false positives, with real detections) |
| **Per-File Detection** | 38.0% (19,073 / 50,256 files) |
| **Real-World Precision / Recall** | 24.2% / 93.9% (v0.4.325, run #226, 89.8% label coverage) |
| **Real-World Projects** | curl, hostap, libcrc, lua, mosquitto, pure-ftpd, raylib, seL4, sqlite |
| **Basis** | `distinct/scored-projects/in_scope` (definitions `1`) |
Regenerate this table with `python -m bench render-docs --realworld-run RUN`
after a version bump or a fresh delta-adjudication.
**[NIST Juliet](https://samate.nist.gov/SARD/test-suites/112) is the headline
number**, because its defects are planted and labelled by the suite itself —
so a true/false positive is a fact, not a judgement. 75 CWEs, 87.1% of aurora-lint's
findings are true positives, and 43 CWEs come back with zero false positives
and real detections.
**The 9 real-world codebases are a reference point**, and a harder one: curl,
hostap, libcrc, lua, mosquitto, pure-ftpd, raylib, seL4 and sqlite, scanned at
pinned commits with findings hand-adjudicated into a ground-truth oracle. Real
code is messier than a test suite and the precision figure reflects that.
> **Recall is measured against *known* true positives**, not against all
> defects present. No exhaustive false-negative hunt sits behind it — past
> audits scoped their searches to specific bug categories — so true recall is
> unknown and lower than the figure above.
How both numbers are produced, what they exclude, and why the Juliet
true-positive rate is not the whole story:
[`docs/testing-methodology.rst`](docs/testing-methodology.rst) and
[`docs/juliet-history.rst`](docs/juliet-history.rst).
## Installation
The crate, the binary and the man page are all named **`aurora-lint`** — that
is the canonical name to package under.
```bash
cargo install aurora-lint
```
Or build from source:
```bash
git clone https://github.com/brandon-arrendondo/tools_sqc
cd tools_sqc
cargo build --release
```
The binary is at `target/release/aurora-lint`. Requires Rust 2021 edition (stable toolchain).
> **Formerly `sqc`.** This tool was published on crates.io as `sqc` up to
> 0.4.123. That crate is abandoned and will not be updated — crates.io names
> are permanent, so it stays claimed and pointing here, but every release from
> the rename onward is `aurora-lint`. Existing `SQC-SUPPRESS` comments and
> `.sqc-suppress.toml` files keep working; see
> [`docs/suppression.rst`](docs/suppression.rst).
## Getting Started
### Analyze a project
```bash
# Analyze a directory (prints violations to stdout)
aurora-lint /path/to/project
# With cross-file context (reduces false positives)
aurora-lint /path/to/project -d /path/to/project
```
### Interactive mode
The terminal UI is disabled by default (CLI + CI/CD is the primary use case). Build with the `tui` feature to enable it:
```bash
cargo build --release --features tui
aurora-lint /path/to/project --interactive
```
### Export results
```bash
aurora-lint /path/to/project --export results.json
aurora-lint /path/to/project --export results.sarif
aurora-lint /path/to/project --export results.csv
```
### Filter by severity
```bash
# Only report Medium and above
aurora-lint /path/to/project --min-severity Medium
# Fail if any High+ violations found (for CI)
aurora-lint /path/to/project --fail-on-severity High
```
### Diff mode (only changed files)
```bash
aurora-lint /path/to/repo --diff
```
### Exclude files from a scan
```bash
# Drop vendored code, test harnesses, or generated/amalgamated files
aurora-lint /path/to/repo --exclude "tests/**" --exclude "vendor/**" --exclude "**/onelua.c"
```
`--exclude` is the only flag that removes files from the scan — `-d` only adds
directories for cross-file context and never restricts what gets analyzed.
### Use a custom rules manifest
```bash
aurora-lint /path/to/project --manifest my-rules.toml
```
The default manifest (`rules_templates/rules-all.toml`) enables 307 of the 311 tracked rules; the other 4 are tracked but not yet implemented (2 parked on incomplete upstream CERT content) — see [Configuration](docs/configuration.rst). See the [Developer Guide](docs/index.rst) for the manifest format.
## Quick CI Example
```bash
# CI pipeline: diff-only, Medium+ reporting, fail on High, SARIF export
aurora-lint . --diff --min-severity Medium --fail-on-severity High --export results.sarif
```
Exit codes: `0` = success, `1` = violations found (with `--fail-on-*`), `2` = error.
Ready-to-use workflow examples for [GitHub Actions and Azure DevOps](docs/cicd-integration.rst) are in the Developer Guide.
## Alternatives
Honest version: on the narrow set of defect classes clang-tidy checks, **clang-tidy
is more precise than aurora-lint** — 99.2% to 81.7% on the 15 Juliet CWEs it covers, and it
finds more true positives there too. It gets that by compiling your code.
aurora-lint's case is breadth and reach, not beating clang-tidy at its fifteen:
| **aurora-lint** | **311 rules implemented**, 17 categories | **75** | **No** |
| clang-tidy | ~20 `cert-*` checks | 15 | Yes |
| cppcheck | ~20 (addon) | 15 | No |
| [Infer](https://fbinfer.com/) | bug-type indexed | 10 | Yes |
| [Frama-C](https://frama-c.com/) | not rule-indexed | 6 | Yes |
cppcheck is the useful control, since it also runs without a build: on the same
15 CWEs it scores 36.7% against aurora-lint's 81.7%, and takes roughly ten times as long
on real code.
Per-CWE precision for all five tools, the speed measurements, and what the
build-vs-no-build trade actually costs:
**[`docs/tool-comparison.rst`](docs/tool-comparison.rst)**.
## Documentation
For advanced usage, CI/CD integration details, interactive UI reference, testing methodology, and contributing:
**[Developer Guide](docs/index.rst)** - comprehensive reference for all features and project internals.
| [Developer Guide](docs/index.rst) | Advanced usage, CI/CD, UI reference, testing, architecture, contributing |
| [`docs/juliet-history.rst`](docs/juliet-history.rst) | Juliet benchmark data: TP/FP history, per-CWE results |
| [`docs/future-rulesets.rst`](docs/future-rulesets.rst) | Why CERT C is the base standard, and which open standards could be added |
| [`docs/tool-comparison.rst`](docs/tool-comparison.rst) | aurora-lint vs cppcheck, clang-tidy, Frama-C, Infer — per-CWE precision, speed, build requirements |
| [`docs/testing-methodology.rst`](docs/testing-methodology.rst) | How the benchmark numbers are produced, and what they exclude |
| [CONTRIBUTORS.md](CONTRIBUTORS.md) | Who built this |
## AI Assistance
This project was developed with assistance from [Claude](https://claude.ai) (Anthropic). Claude was used throughout the development process for code generation, rule implementation, analysis, and documentation.
Claude is deliberately not listed as a commit co-author — the acknowledgement
belongs once, here, rather than repeated across several thousand commit
messages. See [CONTRIBUTORS.md](CONTRIBUTORS.md) for the people involved.
## License
Apache-2.0. Copyright 2025-2026 BISSELL Homecare, Inc.
[LICENSE](LICENSE) is the unmodified Apache-2.0 text; copyright and
attribution live in [NOTICE](NOTICE), per Apache-2.0 section 4(d).
aurora-lint also carries third-party material from the SEI CERT C Coding Standard,
which keeps its own upstream terms: rule titles and descriptions under
CC BY 4.0, and CERT code examples under MIT. CMU's own notice is mirrored
verbatim in [thirdparty/cert/LICENSE](thirdparty/cert/LICENSE), and
[docs/licensing.rst](docs/licensing.rst) has the full breakdown and what a
distribution packager needs.
Carnegie Mellon and CERT are registered trademarks of Carnegie Mellon
University. aurora-lint is not affiliated with, endorsed by, or certified by CMU or
its Software Engineering Institute.