Skip to content

draft(preservation): retain Coraza/CRS enforcement evidence for bounded successor - #95

Draft
seonghobae wants to merge 48 commits into
mainfrom
feat/issue-86-in-path-coraza
Draft

draft(preservation): retain Coraza/CRS enforcement evidence for bounded successor#95
seonghobae wants to merge 48 commits into
mainfrom
feat/issue-86-in-path-coraza

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Preservation status — 2026-09-05 KST

This PR is intentionally Draft and is not an integration candidate. Fresh protected truth is main@5829a0f08d78de464dd24393ce5d0f25fba9d126 (merged #159), while GitHub still records this branch against obsolete main@107117634764c901dff540044585d64088fafedb; current head is 304f053013a76f11a03b5ed9b058ae1712f6ea12 and GitHub reports it non-mergeable.

The branch accumulated 52 changed paths across unrelated owners/bounded contexts: Coraza/CRS enforcement, destination/egress policy, PostgreSQL control-plane/outbox, release/SBOM/provenance, deployment manifest, credentials, load evidence and product-gap documentation. That violates the current single-writer/DDD repair discipline and now overlaps newer bounded candidates/owner paths. Do not mechanically restack or merge the aggregate branch.

Unique evidence to preserve

The still-relevant Wardnet-owned slice is the proven-engine WAF/IDS work for #86. Any bounded successor must inventory and either carry forward or prove obsolete every unique item below before this preservation PR can be retired:

  • live /gateway consultation of a proven Coraza/OWASP CRS authority rather than treating hand-written scoring as detection authority;
  • explicit proven-engine availability/degraded/fail-closed behavior and machine-readable engine-status evidence;
  • Coraza audit/in-process adapter behavior and attack/benign regressions that bind a decision to the exact request and policy/ruleset identity;
  • the docs/doctoring/in-path-coraza-adapter.md / docs/doctoring/in-process-libcoraza.md reasoning and any non-duplicated APA 7 traceability for the enforcement boundary;
  • any unique hostile fixtures for engine outage, malformed engine evidence, monitor/block precedence, request framing/body handling or engine-result correlation;
  • any unique detection-quality/load evidence that remains valid after reconstruction.

Historical local test claims and predecessor workflow results do not transfer to a successor head.

Superseded / separately owned material

Do not preserve aggregate ownership merely because these paths are present here:

Reconstruction acceptance

  1. Start from the exact then-current protected main, not this stale branch tip.
  2. Review [P0] Put proven WAF/IDS engines in the enforcement path and publish detection-quality evidence #86 against current Coraza/CRS/Suricata architecture and keep Wardnet as gateway/security-control authority without copying foreign owner implementations.
  3. Add hostile RED tests first for each unique enforcement invariant being transferred.
  4. Apply only the minimal Coraza/proven-engine causal delta; exclude unrelated egress/database/release/auth/documentation-owner changes.
  5. Reacquire exact-current-head format/tests/Clippy, 100% owned statement/branch/edge coverage, fuzz, security/SAST/CodeQL/Strix, package/SBOM/provenance, current review/thread and live governance evidence.
  6. Preserve failure/degraded behavior as explicit policy; unknown/malformed/unverifiable ruleset or engine evidence must never silently become an allow.
  7. Close this preservation PR only after a protected-main successor demonstrably carries every still-valid unique Coraza/CRS code/test/fixture/docs/evidence delta or proves a specific item obsolete.

No force-push/destructive rebase, self/model approval, routine administrator bypass, predecessor evidence reuse, or aggregate-branch merge is authorized.

When CORAZA_WAF_URL is set, each /gateway request is POSTed to that
sidecar and the response is parsed with the existing Coraza audit
adapter so OWASP CRS stays the detection authority. Sidecar outage
is fail-closed when PROVEN_ENGINE_FAIL_CLOSED is true.

Refs #86.
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c596ad92-0b86-4ff2-9352-9e49e14e3666

📥 Commits

Reviewing files that changed from the base of the PR and between 129bb96 and 9114d2c.

📒 Files selected for processing (3)
  • src/control_plane.rs
  • src/lib.rs
  • tests/binary.rs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

In-process libcoraza를 sidecar보다 우선하는 WAF 경로를 추가했습니다. Outbound 목적지 검증, DNSBL, transactional outbox, PostgreSQL 운영, 서명된 릴리스 및 실행 검증 계약도 갱신했습니다.

Changes

보안 경계와 운영 기반

Layer / File(s) Summary
Coraza 엔진과 게이트웨이 평가
src/lib.rs, src/proven_engine.rs, src/coraza_inprocess.rs, src/coraza_abi_stub.rs, src/coraza_audit.rs, build.rs, tests/binary.rs
In-process libcoraza와 sidecar 평가 경로를 구성합니다. 차단, 장애, Monitor 증거, 엔진 상태 및 CRS 공격 배터리를 검증합니다.
목적지 정책과 egress DNS
src/destination.rs, src/egress_dns.rs, deploy/kubernetes/waf-ids-ai-soc.yaml
URL, DNS 결과, 주소 클래스, allowlist 및 denylist를 검증합니다. 승인된 주소를 고정하고 DNSBL A/TXT 응답과 UDP·TCP 서비스를 제공합니다.
Transactional outbox와 PostgreSQL 운영
src/outbox.rs, src/credentials.rs, crates/waf-ids-core/src/lib.rs, .github/workflows/ci.yml, Cargo.toml
Outbox 메시지, idempotency, 재시도, dead-letter 및 자격 증명 혼합 소스를 추가합니다. snapshot_version 기반 상태 계약과 PostgreSQL 테스트 환경을 갱신합니다.
서명된 릴리스와 공급망 검증
.github/workflows/release.yml, scripts/*release*, scripts/admit-release-tag.sh, scripts/pin-k8s-digest.sh, docs/runbooks/release.md, docs/doctoring/signed-release.md
Annotated 태그 승인, 잠금 빌드, 체크섬, SPDX SBOM, Sigstore 서명, SLSA 증명 및 digest 기반 배포를 구성합니다.
시작 검증과 실행 검사
src/main.rs, tests/binary.rs, scripts/smoke.sh, scripts/k6-gateway.sh, tests/load/*, .github/workflows/ci.yml
Coraza, PostgreSQL URL, SSL 모드 및 bind 조건의 시작 검증을 추가합니다. Health, 관리자 API, Gateway 및 MCP 부하 계약을 검사합니다.
운영 문서와 보안 계약
README.md, CLAUDE.md, docs/architecture.md, docs/doctoring/*, docs/runbooks/*, docs/security/*, docs/research/*, docs/camoufox-egress.md, docs/egress-api-openapi.yaml, docs/product-technical-gap-baseline.md, CHANGELOG.md
WAF 선택, SSRF 방어, egress, PostgreSQL, 백업·복구, outbox, MCP, DNSBL 및 릴리스 증거를 문서화합니다.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🟡 Moderate · up to 9114d

This PR adds synchronous Coraza sidecar decisions to live gateway traffic, so an impersonated sidecar could alter blocking decisions and a sidecar outage can silently degrade protection by default without making the gateway unready. Additional unresolved code and documentation issues affect error handling, secret initialization, and the accuracy of operational claims, so merge requires explicit owner acceptance or follow-up on these bounded risks.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Gateway
  participant InProcessCoraza
  participant CorazaSidecar
  participant DestinationPolicy
  participant EgressDNS
  Client->>Gateway: /gateway 요청
  Gateway->>InProcessCoraza: URI, 헤더, 본문 평가
  InProcessCoraza-->>Gateway: Clean 또는 interruption
  Gateway->>CorazaSidecar: InProcessCoraza가 없을 때 평가
  CorazaSidecar-->>Gateway: 상태 코드와 감사 JSON
  Gateway->>DestinationPolicy: outbound 목적지 평가
  DestinationPolicy->>EgressDNS: 승인된 주소 해석
  EgressDNS-->>DestinationPolicy: 정책 검증 주소
  Gateway-->>Client: 정상 응답, 403 또는 503
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.05% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 203 functions across 20 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목은 Coraza/CRS 강제 적용과 검증 근거 보존이라는 실제 변경 사항을 설명합니다. 다만 sidecar 평가, fail-closed 동작, 엔진 상태 API 등 전체 변경 범위를 모두 포함하지는 않지만, 주요 변경과 관련성이 충분합니다.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-86-in-path-coraza

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

devin-ai-integration[bot]

This comment was marked as resolved.

chatgpt-codex-connector[bot]

This comment was marked as resolved.

Review-hardening for PR #95 findings:

- Forward a bounded allowlist of client headers to the engine (host,
  user-agent, accept, content-type, referer, origin, x-requested-with,
  x-forwarded-for, x-real-ip, cookie; never Authorization) with 32-header and
  8 KiB caps so CRS rules that inspect headers see real input without
  shipping credentials to sidecar logs.
- Stream sidecar responses under a 1 MiB cap instead of unbounded text()
  buffering; oversized or non-UTF-8 answers are Unavailable.
- Explicit status contract: 2xx parses audit JSON (empty stays clean), 403
  without parseable JSON remains an interruption fallback, every other
  status is Unavailable so fail-closed deployments never allow on a confused
  sidecar answer.
- Monitor-mode routes and sub-threshold hits now record engine_hit events
  with the cited CRS rule instead of dropping the evidence.
- Fail-open outages record engine_unavailable events; scoring continues.

Doctoring gains the Scarfone & Mell (2007) NIST SP 800-94 grounding with the
redistributable public-domain PDF committed under docs/papers/.

Tests: header allowlist bounding + credential exclusion, sidecar payload
headers, non-success status Unavailable, oversized response Unavailable,
fail-open outage event, monitor-route engine_hit evidence.
coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

seonghobae added a commit that referenced this pull request Aug 24, 2026
In-process transactions now receive the same forwarded-header allowlist as
the sidecar path (host, user-agent, accept, content-type, referer, origin,
x-requested-with, x-forwarded-for, x-real-ip, cookie — never Authorization;
32 headers / 8 KiB caps enforced by proven_engine::engine_forwarded_headers).
Each header crosses the C ABI via coraza_add_request_header before
process_request_headers, so CRS rules that inspect headers evaluate real
client input instead of a synthetic Host only.

Brings in the PR #95 sidecar hardening via merge so both engines share one
allowlist implementation and one status/bound contract.

Behavioral header-battery evidence lands with the issue-11 battery fixture
(PR #110); this slice ships the plumbing and keeps the stub contract
unchanged.
CodeRabbit finding: a 403 with a non-JSON body (e.g. the CRS default block
page) parsed to Unavailable, and the interruption fallback only fired on
Clean — so fail-open deployments could allow a real CRS block. The fallback
now covers every non-Hit outcome on 403: audit JSON keeps its parsed hit;
empty or HTML bodies become the interrupted evidence Hit.

Test: sidecar_403_with_non_json_body_is_an_interruption_hit.
devin-ai-integration[bot]

This comment was marked as resolved.

@opencode-agent opencode-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 63b7930cdd6dbebd427f49e2c568bb198f490836.

  • Head SHA: 63b7930cdd6dbebd427f49e2c568bb198f490836

  • Workflow run: 32702403014

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (6 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (6 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (5 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (5 files)"]
  R2 --> V2["docs review"]
Loading

@opencode-agent

Copy link
Copy Markdown
Contributor

OpenCode Review Overview

  • Head SHA: 63b7930cdd6dbebd427f49e2c568bb198f490836
  • Workflow run: 32702403014
  • Workflow attempt: 1
  • Gate result: REQUEST_CHANGES (approval step)

Pull request overview

OpenCode cannot approve yet because required coverage evidence did not pass.

Review outcome

1. HIGH .github/workflows/opencode-review.yml:1 - Coverage evidence did not prove required test/docstring evidence

  • Problem: The required coverage-evidence job result was failure, so OpenCode cannot establish approval sufficiency for this head.

  • Root cause: Automated approval is only valid when the same-head coverage-evidence job proves supported repository test suites passed and configured docstring gates passed or were advisory, or reports not applicable because no supported source files or package manifests exist. Missing, failed, skipped, unavailable, or unsupported-tooling test evidence is a blocker.

  • Fix: Install or configure the repository test/docstring evidence tooling when source files or package manifests exist, rerun the current-head coverage-evidence job, and approve only after it reports success with required evidence or explicit no-source not-applicable evidence.

  • Regression test: Keep the approval branch checking needs.coverage-evidence.result == success before posting APPROVE, and publish REQUEST_CHANGES when coverage-evidence blocker states such as cancelled, skipped, failed, unsupported-tooling, or below-100 evidence are present.

  • Result: REQUEST_CHANGES

  • Reason: coverage-evidence result was failure, so required test/docstring evidence was not proven for current head 63b7930cdd6dbebd427f49e2c568bb198f490836.

  • Head SHA: 63b7930cdd6dbebd427f49e2c568bb198f490836

  • Workflow run: 32702403014

  • Workflow attempt: 1

Coverage evidence

Coverage Decision

  • Result: FAIL
  • Test evidence: not proven passing
  • Docstring evidence: not proven passing when configured
  • Failure count: 1

Changed-File Evidence Map

flowchart LR
  PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
  Evidence --> S1["Changed file (6 files)"]
  S1 --> I1["repository behavior"]
  I1 --> R1["Review risk: Changed file (6 files)"]
  R1 --> V1["required checks"]
  Evidence --> S2["Docs (5 files)"]
  S2 --> I2["operator or user guidance"]
  I2 --> R2["Review risk: Docs (5 files)"]
  R2 --> V2["docs review"]
Loading

coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e79e44e9f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/control_plane.rs
Comment thread src/lib.rs
Comment thread src/control_plane.rs
Comment thread src/control_plane.rs Outdated
Comment thread src/control_plane.rs Outdated
Comment thread src/control_plane.rs Outdated
Comment thread src/lib.rs
Comment thread src/control_plane.rs
devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Addressed on the current branch push for feat/issue-86-in-path-coraza: hash_partition_sql_for now keeps wardnet_runtime grants on the partitioned security_event parent only, so runtime access stays behind the parent RLS policy instead of direct child-table grants. Local verification on Friday, August 28, 2026: cargo fmt --check; cargo test.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae
seonghobae marked this pull request as draft September 4, 2026 18:34
@seonghobae seonghobae changed the title feat(waf): consult Coraza sidecar on live gateway transactions draft(preservation): retain Coraza/CRS enforcement evidence for bounded successor Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants