Org-wide CodeRabbit configuration for the corazawaf GitHub organization.
This repository contains the canonical .coderabbit.yaml that CodeRabbit applies across every repo in the org as a default. Individual repos can override settings by committing their own .coderabbit.yaml.
⚠️ A repo's.coderabbit.yamlonly inherits the org settings below if it setsinheritance: trueat the top. Without that flag the org config is ignored entirely for that repo: the engine/CGO/docs review guidance, every pre-merge check, and every tool toggle silently drop, and any field the repo didn't set falls back to the schema default (not the org value). See Overriding per Repository.
The org holds five repositories, and they are five different kinds of codebase — a generic reviewer serves none of them well:
coraza— the WAF engine itself, Go: the SecLang directive parser, the phase/transaction pipeline, operators, actions, transformations, body processors, audit logging, and the public plugin API. It implements OWASP CRS v4 but does not maintain rule content itself.coraza-caddy— a Go Caddy server module wrappingcoraza.libinjection-go— a Go port of the C libinjection library (SQLi/XSS detection), a dependency ofcoraza.libcoraza— a C library exposingcoraza's engine as a C API via CGO, for nginx and other non-Go consumers, plus SWIG-generated Python and Java bindings.coraza.io— the bilingual (English/Spanish) Hugo documentation site, partly generated fromcoraza's own source.
Reviewing the SecLang parser needs phase and evaluation-order knowledge; reviewing libcoraza needs CGO memory-management rules; reviewing coraza.io needs the English/Spanish parity contract. Path-scoped guidance is what keeps each from being reviewed as one of the others, and it is the main design constraint on the file.
Beyond that:
- one source of truth — review behaviour, checks, and tool enablement are set once and apply everywhere;
- community contributions get a real review —
enable_free_tierandallow_non_org_membersare on because Coraza takes drive-by community contributions.
flowchart TD
A[Contributor opens PR] -->|GitHub webhook| B[CodeRabbit GitHub App]
B -->|reads| C["corazawaf/coderabbit<br/>.coderabbit.yaml"]
C -->|org-level defaults| D{"Does the repo have<br/>a local .coderabbit.yaml?"}
D -- No --> F[Use org defaults as-is]
D -- Yes --> I{"Is inheritance: true<br/>set in the repo config?"}
I -- Yes --> E1["Deep-merge org + repo;<br/>repo wins per field"]
I -- No --> E2["Repo config ALONE;<br/>org config IGNORED<br/>— review guidance dropped<br/>— unset fields use schema defaults"]
F --> G[Review posted on the PR]
E1 --> G
E2 --> G
| Path | Purpose |
|---|---|
.coderabbit.yaml |
The org-wide CodeRabbit configuration — the entire deliverable |
.github/workflows/validate-coderabbit.yml |
Validates YAML syntax and the config against the CodeRabbit schema |
renovate.json |
Renovate config, extending the shared org preset |
AGENTS.md |
Working notes for AI coding agents editing this config |
CLAUDE.md |
Imports AGENTS.md, so Claude Code picks up the same notes |
README.md |
This file |
profile: chill (fewer, higher-signal comments), request_changes_workflow: false (advisory, never a hard block), incremental review on update commits, drafts skipped, and titles generated as conventional-commit types with an optional ! breaking marker — coraza-caddy, libinjection-go, and libcoraza all release via release-please, which reads the commit type directly to pick the version bump and changelog entry, so a wrong type mis-versions a release with no CI failure to catch it. Poems, fortunes, and sequence diagrams are off. finishing_touches (AI-authored docstrings, tests, simplifications) is disabled org-wide: coraza's own AGENTS.md explicitly wants the opposite of what an auto-pushed test commit would produce ("default to zero new test functions").
base_branches is main only — there is no LTS/backport branch pattern in this org.
There is no cross-repo label taxonomy in this org. corazawaf's release repos (coraza-caddy, libinjection-go, libcoraza) use release-please, which derives the version bump and changelog entry from the conventional-commit type in the title/commit message (see auto_title_instructions) — not from a label. coraza hand-curates CHANGELOG.md on the same convention. Each repo keeps its own ad hoc labels (confirmed via gh label list --repo corazawaf/coraza: plain names like bug, enhancement, good first issue, help wanted, version labels like v3/v4, no shared meaning across repos), so labeling_instructions / auto_apply_labels are left unconfigured. issue_enrichment.planning.labels uses two of those confirmed plain names (good first issue, help wanted) — CodeRabbit never creates a missing label, it just silently no-ops, so a referenced label must match an existing repo label exactly.
Seven glob-scoped entries, one per distinctive directory shape in this org. These carry the domain knowledge a generic reviewer does not have, and they are where a finding needs to land on a specific line.
| Path | What it reviews |
|---|---|
**/internal/seclang/** |
coraza's SecLang parser (only coraza has this directory): silent misparse vs. a surfaced error, ModSecurity compatibility drift, directive/variable additions not reflected in the generated maps, Include recursion protection |
**/experimental/plugins/** |
coraza's public plugin API: the import-cycle direction, breaking an Operator/Transformation/Action/BodyProcessor interface without a major-version signal, correct ActionType classification |
**/libcoraza/*.go |
the CGO boundary — the entire C API lives in one file: C.CString/C.free pairing, calloc'd interventions freed via coraza_free_intervention(), cgo.Handle lifecycle, never hand-editing the generated (and uncommitted) coraza/coraza.h |
**/*.c |
libcoraza's C test drivers: unchecked malloc/free, unbounded buffer handling, use-after-free/double-free across the CGO boundary, missing NULL checks at the API boundary |
**/content/**/*.md |
coraza.io's Hugo content (only coraza.io has this directory shape): English changed without the Spanish counterpart, a generated doc page hand-edited instead of regenerated, AI-voice/British-spelling/front-matter conventions from its own AGENTS.md |
**/.github/workflows/** |
actions pinned to a full SHA, persist-credentials: false, ${{ github.event.* }} injection, over-broad permissions, pull_request_target with a head checkout, the base-branch filter trap |
**/*.go |
general Go guidance across all four Go repos: no panics in library code (an integrator's process must not die), regex compiled outside the memoizer in a hot path, untrusted-input handling, context propagation, goroutine lifetimes, data races (coraza's collections are documented as not concurrent-safe by design) |
Thirteen checks, all mode: warning. These evaluate the diff as a unit and catch invariants no single line can express.
corazawaf-specific:
| Check | Catches |
|---|---|
| ADR Required for Structural Changes | a new directive/operator/action/type or breaking API change in coraza with no docs/adr/NNNN-*.md in the same PR |
| Test Layer Discipline & Duplication | coraza's own guidance wants zero new test functions by default; this flags a new function where a table row or engine-profile case belongs, and the same scenario tested at more than one layer |
| Generated Content Not Hand-Edited | coraza's *.gen.go directive/variable maps or coraza.io's generated directives.md/actions.md/operators.md changed without their real source (directives.go/variables.go, or coraza's version in coraza.io's go.mod) also changing |
| Documentation Translation Parity | an English coraza.io page added, removed, or restructured with no content/es/ counterpart in the same PR |
| CGO Memory Safety | unpaired C.CString/C.free, an intervention never reaching coraza_free_intervention(), a cgo.Handle never deleted, a new exported C function with no matching coraza.i update |
| Breaking Changes to Public API & Compatibility | a removed/renamed exported symbol in types//collection//experimental/plugins/plugintypes/, a libcoraza C API/ABI change, a changed coraza.conf-recommended default, a removed Caddyfile sub-directive |
| Security Fix Process Compliance | a public PR describing an exploitable vulnerability instead of routing through the private GitHub security advisory flow coraza's AGENTS.md requires |
Supply chain and appsec (trimmed to this org's actual surface — no API-server or LLM-application categories, since none of these five repos are either):
| Check | Catches |
|---|---|
| OWASP Security (Web & Supply Chain) | crypto failures, injection in the tooling's own code, misconfiguration, vulnerable components, and SSRF on the audit-log HTTPS writer |
| Unpinned Dependencies & Actions | unpinned uses:, Go/npm/Docker version drift (only the ecosystems actually present in this org) |
| New Dependency Scrutiny | a newly added dependency or Action with no justification — typosquats, single-maintainer packages |
| Install & Build-Time Code Execution | pipe-to-shell installers, GOSUMDB=off, npm lifecycle scripts, unverified Docker/autotools build-time fetches |
| Secrets, Payloads & PII in Logs | full-object logging, audit-log over-capture, the CGO log bridge, committed traffic captures |
| Renovate: config present and valid | a missing config, a wrong $schema, or one not extending corazawaf/renovate-config (accepts both the github> and local> forms actually used across this org's repos) |
| Enabled | For |
|---|---|
golangci-lint |
Go — coraza, coraza-caddy, libinjection-go, libcoraza's Go side |
fbinfer |
C — libcoraza's CGO bridge, C headers, and SWIG bindings |
yamllint, shellcheck, actionlint, zizmor, hadolint, checkov, markdownlint, github-checks |
config, shell, CI, containers |
trivy, osvScanner, trufflehog, gitleaks, presidio, opengrep, skillspector |
security scanning |
| Disabled | Why |
|---|---|
ruff, flake8, pylint |
no Python code anywhere in this org's five repos |
semgrep |
overlaps opengrep and would double-flag |
pmd |
libcoraza's Java/Python SWIG examples are a handful of files, not a codebase |
oasdiff |
no OpenAPI specs — these are libraries and a Caddy module, not API servers |
languagetool |
off by default; coraza.io can opt in locally |
code_guidelines ingests CLAUDE.md, AGENTS.md, CONTRIBUTING.md, SECURITY.md, RATIONALE.md, and docs/adr/**/*.md.
linked_repositories is capped at 20 by the schema, but our CodeRabbit plan caps it at 5 — which happens to equal exactly the five repos in this org, so all of them are linked:
| Repo | Why it's linked |
|---|---|
coraza |
the WAF engine everything else depends on or wraps; rule ID/directive accuracy, whether an API change is breaking, whether a structural change needed an ADR |
coraza-caddy |
its Caddyfile directive surface is what operators actually configure; tracks coraza's main closely, so a breaking coraza change usually shows up here first |
libinjection-go |
performance-sensitive SQLi/XSS detection dependency; distinguishes a coraza-side gap from a libinjection-go-side one |
libcoraza |
the authority on the CGO memory-management contract and the C API / SWIG interface surface |
coraza.io |
the source of truth for everything operators are told, and the counterpart obligation for any user-visible change elsewhere in the org — this org's documentation repo; there is no separate docs repo since the docs site itself is one of the five |
Follow these when adding to path_instructions or custom_checks; the file is consistent about them and reviews read worse when it isn't.
- Finding format is fixed:
⚠️ WARNING: <description> — <fix>.❌ blockeris reserved for CGO memory-safety violations, a breaking plugin-interface signature change, and a hand-edited generated artifact. - Every check is
mode: warning. Escalating one tomode: erroralso requiresrequest_changes_workflow: true, and should follow a validated low false-positive rate on real PRs. - Open ecosystem- and repo-scoped checks with a trigger condition that returns
Passedplus "not applicable" when the diff touches nothing relevant. Without it the check returnsInconclusiveon every unrelated PR. - Describe acceptable patterns alongside violations, so the reviewer has a target state rather than only a complaint.
- Where does it go? Use
path_instructionswhen the finding needs to land on a specific line. Usecustom_checksfor cross-file invariants and policy a single line can't express.
Schema caps are enforced silently at review time — CodeRabbit truncates an over-long string rather than erroring, so a check can quietly lose half its instructions. Validation does catch them: every cap below is a maxLength/maxItems in the schema, which is what makes the check-jsonschema step in CI worth running before every merge.
| Field | Cap |
|---|---|
tone_instructions |
250 chars |
labeling_instructions[].instructions |
3,000 chars |
path_instructions[].instructions |
20,000 chars |
custom_checks[].name |
50 chars |
custom_checks[].instructions |
10,000 chars |
custom_checks |
50 items |
linked_repositories |
20 items (this org's plan caps it at 5) |
linked_repositories[].instructions |
2,000 chars |
Add a .coderabbit.yaml to your repo root and set inheritance: true at the top. Without that flag, your file replaces the entire org config — every check, every tool toggle, every path instruction — and unset fields fall back to the schema default rather than the org value.
| Repo state | Effective config |
|---|---|
No local .coderabbit.yaml |
Org config only — everything above applies |
Local .coderabbit.yaml without inheritance: true |
Repo config only — org config IGNORED. Unset fields fall back to schema defaults, not org values. Drops all review guidance and every pre-merge check. |
Local .coderabbit.yaml with inheritance: true |
Deep merge; the repo wins per field, and unset fields inherit from the org |
Note that list fields are replaced, not merged, when a repo defines the same key locally. Adding an entry to custom_checks or path_instructions here only reaches repos that have not overridden that key.
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
inheritance: true # REQUIRED — without it the org config is IGNORED for this repo
reviews:
profile: "assertive" # this repo wants comprehensive reviews (overrides org "chill")
auto_review:
drafts: true # also review draft PRs hereComment @coderabbitai configuration on any PR. CodeRabbit replies with the merged config actually being applied — the fastest way to confirm whether inheritance is working.
Every change is an edit to .coderabbit.yaml. There is no application code and no build.
- Edit the file, keeping the comment above each setting in sync with what it does. The comments are the justification record.
- Validate:
# syntax — only line-length warnings are expected yamllint -d relaxed .coderabbit.yaml # schema. The URL in the file's first line 301-redirects, so fetch the asset directly: curl -sL -o /tmp/schema.v2.json \ https://storage.googleapis.com/coderabbit_public_assets/schema.v2.json uvx check-jsonschema --schemafile /tmp/schema.v2.json .coderabbit.yaml
- When adding a label, confirm it already exists in the target repo (
gh label list --repo corazawaf/coraza). CodeRabbit will not create it, and a missing label silently no-ops. - When the domain knowledge in this file changes, keep it in sync with the relevant repo's own
AGENTS.md/CLAUDE.md—coraza's (architecture, testing layer map, ADR standard, security-advisory policy),coraza.io's (bilingual content rules), andlibcoraza's (CGO binding pattern). - Open a PR. The
validateworkflow re-runs step 2 server-side on every PR touching.coderabbit.yaml.
The validate workflow runs on every PR that touches .coderabbit.yaml or the workflow itself, and weekly on a schedule. It:
- Lints YAML syntax with
yamllint -d relaxed— deliberately not--strict, so the intentional long lines don't fail the build while a real error such as a duplicated key (which would silently drop a whole section) still does. - Validates against the CodeRabbit v2 schema with
check-jsonschema. Because the schema declares every character and item cap, this is what stops an over-long instruction string from being silently truncated in production.
The schema is fetched at run time rather than vendored, so an upstream schema change can invalidate a config that passed when it merged. The weekly schedule catches that instead of leaving it for the next unrelated PR.
Both steps are the same commands listed under Making Changes — run them locally and CI will agree.