Skip to content

Fix leak of intervention.url when headers are already sent - #397

Open
tomsommer wants to merge 1 commit into
owasp-modsecurity:masterfrom
tomsommer:fix/intervention-url-leak
Open

tomsommer wants to merge 1 commit into
owasp-modsecurity:masterfrom
tomsommer:fix/intervention-url-leak

Conversation

@tomsommer

Copy link
Copy Markdown
Contributor

what

  • Free intervention.url on the early return taken in ngx_http_modsecurity_process_intervention() when the response headers have already been sent. libmodsecurity's Transaction::intervention() hands out a strdup'd copy that the caller owns; this path returned without releasing it.
  • New test tests/modsecurity-intervention-redirect.t: a phase 1 redirect (asserts the 302 and the exact Location value) and a phase 4 RESPONSE_BODY redirect after headers were sent (asserts the rule is audit-logged and the worker keeps serving). It makes no assertion about how the phase 4 response ends, which fix: fail closed on swallowed WAF return values #384 changes.

why

  • A valgrind audit of the connector (nginx master, libmodsecurity 3.0.14, --leak-check=full) showed this record growing linearly with request count: 720 bytes in 20 blocks after 20 phase 4 redirects, 7,200 bytes in 200 blocks after 200. With the fix the record is gone at both counts, and there are no invalid or double frees.
  • This is the only outcome a phase 4 redirect: action can reach: by the time the body filter runs, ngx_http_header_filter has already sent the headers, so every such intervention leaked.

references


Origin: this fix comes from a memory-leak audit of the connector done with Claude Fable 5.1 (Anthropic), following its performance review. Verified by building against nginx master with libmodsecurity 3.0.14 (PCRE2) and with upstream CI's flags against libmodsecurity 3.0.9 (PCRE1), running the full tests/modsecurity*.t suite in both builds (16 files, 255 tests, all passing), and by valgrind runs of 20 and 200 requests before and after the change.

Transaction::intervention() hands out a strdup'd copy of the redirect
URL, which the connector owns. The early return taken when the response
headers have already been sent (the only reachable outcome for a phase 4
RESPONSE_BODY redirect, since ngx_http_header_filter has already run)
returned without releasing it, leaking the string on every such request.

The other leak of the same string, on the successful redirect path
where the Location header value is pointed straight at the strdup'd
buffer, is deliberately left alone here: that path needs the URL
copied into r->pool before the buffer is released (freeing it in place
would leave the Location header pointing at freed memory), and it is
the subject of a separate change.

Add a test covering both redirect shapes: a phase 1 redirect, asserting
the status and the exact Location value, and a phase 4 RESPONSE_BODY
redirect, asserting that the rule is audit logged and that the worker
keeps serving afterwards.
@coderabbitai

coderabbitai Bot commented Sep 19, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 6 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 4 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: f18f3052-ae7b-4702-994a-1c5594f370cf

📥 Commits

Reviewing files that changed from the base of the PR and between 9eb44fd and bd1dda5.

📒 Files selected for processing (2)
  • src/ngx_http_modsecurity_module.c
  • tests/modsecurity-intervention-redirect.t

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.

@sonarqubecloud

Copy link
Copy Markdown

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.

1 participant