Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
289b6e3
Update libinjection to v4.0.0
Mar 26, 2026
38d9391
Stabilize detectSQLi/XSS regression coverage for full test run
Easton97-Jens Mar 26, 2026
0c610c0
Make benign detectSQLi/XSS regression cases assert no-match logs
Easton97-Jens Mar 26, 2026
0b29169
Merge pull request #23 from Easton97-Jens/codex/migrate-to-libinjecti…
Easton97-Jens Mar 27, 2026
46dabc0
Harden libinjection v4 handling in DetectSQLi/DetectXSS operators
Easton97-Jens Mar 27, 2026
c816add
Fix namespace declaration in libinjection_utils.h
Easton97-Jens Mar 27, 2026
d94cbeb
Fix namespace declaration syntax in libinjection_utils.h
Easton97-Jens Mar 27, 2026
b4b81aa
fix(logging): remove trailing semicolon from debug macros (ms_dbg, ms…
Easton97-Jens Mar 27, 2026
15fd157
Update detect_sqli.cc
Easton97-Jens Mar 27, 2026
4bacc36
Add array header to detect_sqli.cc
Easton97-Jens Mar 27, 2026
f9b2885
Fix formatting issues in transaction.h debug macros
Easton97-Jens Mar 27, 2026
a8debeb
Refactor fingerprint handling in detect_sqli.cc
Easton97-Jens Mar 27, 2026
c67f876
Fix debug logging for XSS detection in detect_xss.cc
Easton97-Jens Mar 27, 2026
7b5bf7f
Fix debug message formatting in detect_sqli.cc
Easton97-Jens Mar 27, 2026
e169d59
Replace push_back with emplace_back for efficiency
Easton97-Jens Mar 27, 2026
724b197
Update operator-detectsqli.json
Easton97-Jens Mar 28, 2026
b9393e7
Update XSS test cases with new payloads
Easton97-Jens Mar 28, 2026
d1eaa04
Update operator-detectsqli.json
Easton97-Jens Mar 28, 2026
de17a7c
test: expand libinjection detectxss and detectsqli regression cases
Easton97-Jens Mar 28, 2026
0f8bc6c
test: make detectxss regression checks deterministic via tx flag
Easton97-Jens Mar 28, 2026
7e1d08b
Merge branch 'owasp-modsecurity:v3/master' into v3/master-libinjectio…
Easton97-Jens Mar 28, 2026
9b37043
test: add deterministic sqli match assertions via tx.sqli_hit
Easton97-Jens Mar 28, 2026
830a340
test: harden mixed-case javascript xss regression payload
Easton97-Jens Mar 28, 2026
84cdfdd
Merge pull request #26 from Easton97-Jens/codex/generate-test-cases-f…
Easton97-Jens Mar 29, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion others/libinjection
Submodule libinjection updated 155 files
55 changes: 38 additions & 17 deletions src/operators/detect_sqli.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "src/operators/operator.h"
#include "libinjection/src/libinjection.h"
#include "libinjection/src/libinjection_error.h"
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

New dependency on libinjection/src/libinjection_error.h: please ensure this header is present in the vendored libinjection submodule version and is included in release artifacts (e.g., add it to others/Makefile.am noinst_HEADERS if make dist/packaging relies on that list). Otherwise builds from distribution tarballs can fail with a missing-header error.

Suggested change
#include "libinjection/src/libinjection_error.h"

Copilot uses AI. Check for mistakes.

namespace modsecurity {
namespace operators {
Expand All @@ -28,32 +29,52 @@
bool DetectSQLi::evaluate(Transaction *t, RuleWithActions *rule,
const std::string& input, RuleMessage &ruleMessage) {
char fingerprint[8];
int issqli;
injection_result_t sqli_result;
bool is_match = false;

issqli = libinjection_sqli(input.c_str(), input.length(), fingerprint);
sqli_result = libinjection_sqli(input.c_str(), input.length(), fingerprint);

if (!t) {
goto tisempty;
}

if (issqli) {
t->m_matched.push_back(fingerprint);
ms_dbg_a(t, 4, "detected SQLi using libinjection with " \
"fingerprint '" + std::string(fingerprint) + "' at: '" +
input + "'");
if (rule && rule->hasCaptureAction()) {
t->m_collections.m_tx_collection->storeOrUpdateFirst(
"0", std::string(fingerprint));
ms_dbg_a(t, 7, "Added DetectSQLi match TX.0: " + \
std::string(fingerprint));
}
} else {
ms_dbg_a(t, 9, "detected SQLi: not able to find an " \
"inject on '" + input + "'");
switch (sqli_result) {
case LIBINJECTION_RESULT_TRUE:
is_match = true;
t->m_matched.push_back(fingerprint);
ms_dbg_a(t, 4, "detected SQLi using libinjection with " \
"fingerprint '" + std::string(fingerprint) + "' at: '" +
input + "'");
if (rule && rule->hasCaptureAction()) {
t->m_collections.m_tx_collection->storeOrUpdateFirst(
"0", std::string(fingerprint));
ms_dbg_a(t, 7, "Added DetectSQLi match TX.0: " + \
std::string(fingerprint));
}
break;
case LIBINJECTION_RESULT_ERROR:
is_match = true;
ms_dbg_a(t, 4, "libinjection parser error during SQLi "
"analysis; treating as match (fail-safe). Input: '" + input + "'");

Check warning on line 58 in src/operators/detect_sqli.cc

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Modify the macro definition so that it needs to be followed by a semicolon, or remove this empty statement.

See more on https://sonarcloud.io/project/issues?id=owasp-modsecurity_ModSecurity&issues=AZ0vyq3MOXJ4yXD-WZ3I&open=AZ0vyq3MOXJ4yXD-WZ3I&pullRequest=3522
if (rule && rule->hasCaptureAction()) {
t->m_collections.m_tx_collection->storeOrUpdateFirst(
"0", std::string(input));
ms_dbg_a(t, 7, "Added DetectSQLi error input TX.0: " + \
std::string(input));

Check warning on line 63 in src/operators/detect_sqli.cc

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Modify the macro definition so that it needs to be followed by a semicolon, or remove this empty statement.

See more on https://sonarcloud.io/project/issues?id=owasp-modsecurity_ModSecurity&issues=AZ0vyq3MOXJ4yXD-WZ3J&open=AZ0vyq3MOXJ4yXD-WZ3J&pullRequest=3522
}
break;
Comment on lines +59 to +74
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

The new LIBINJECTION_RESULT_ERROR fail-safe path changes behavior (treat error as match and optionally capture raw input). Please add a regression test that reliably triggers a libinjection ERROR result and asserts the match/capture behavior, so this security-critical branch stays covered.

Copilot uses AI. Check for mistakes.
case LIBINJECTION_RESULT_FALSE:
ms_dbg_a(t, 9, "detected SQLi: not able to find an " \
"inject on '" + input + "'");
break;
}

tisempty:
return issqli != 0;
if (t == nullptr) {
is_match = sqli_result == LIBINJECTION_RESULT_TRUE
|| sqli_result == LIBINJECTION_RESULT_ERROR;
}
return is_match;
}


Expand Down
54 changes: 38 additions & 16 deletions src/operators/detect_xss.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "src/operators/operator.h"
#include "libinjection/src/libinjection.h"
#include "libinjection/src/libinjection_error.h"
Comment on lines 22 to +23
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

New dependency on libinjection/src/libinjection_error.h: please ensure this header is present in the vendored libinjection submodule version and is included in release artifacts (e.g., add it to others/Makefile.am noinst_HEADERS if make dist/packaging relies on that list). Otherwise builds from distribution tarballs can fail with a missing-header error.

Copilot uses AI. Check for mistakes.


namespace modsecurity {
Expand All @@ -27,25 +28,46 @@

bool DetectXSS::evaluate(Transaction *t, RuleWithActions *rule,
const std::string& input, RuleMessage &ruleMessage) {
int is_xss;

is_xss = libinjection_xss(input.c_str(), input.length());
injection_result_t xss_result = libinjection_xss(input.c_str(),
input.length());
bool is_match = false;

if (t) {
if (is_xss) {
ms_dbg_a(t, 5, "detected XSS using libinjection.");
if (rule && rule->hasCaptureAction()) {
t->m_collections.m_tx_collection->storeOrUpdateFirst(
"0", std::string(input));
ms_dbg_a(t, 7, "Added DetectXSS match TX.0: " + \
std::string(input));
}
} else {
ms_dbg_a(t, 9, "libinjection was not able to " \
"find any XSS in: " + input);
}
switch (xss_result) {
case LIBINJECTION_RESULT_TRUE:
is_match = true;
ms_dbg_a(t, 5, "detected XSS using libinjection.");
if (rule && rule->hasCaptureAction()) {
t->m_collections.m_tx_collection->storeOrUpdateFirst(
"0", std::string(input));
ms_dbg_a(t, 7, "Added DetectXSS match TX.0: " + \
std::string(input));
}
break;
case LIBINJECTION_RESULT_ERROR:
is_match = true;
ms_dbg_a(t, 4, "libinjection parser error during XSS "
"analysis; treating as match (fail-safe). Input: " + input);

Check warning on line 50 in src/operators/detect_xss.cc

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Modify the macro definition so that it needs to be followed by a semicolon, or remove this empty statement.

See more on https://sonarcloud.io/project/issues?id=owasp-modsecurity_ModSecurity&issues=AZ0vyq0lOXJ4yXD-WZ3G&open=AZ0vyq0lOXJ4yXD-WZ3G&pullRequest=3522
if (rule && rule->hasCaptureAction()) {
t->m_collections.m_tx_collection->storeOrUpdateFirst(
"0", std::string(input));
ms_dbg_a(t, 7, "Added DetectXSS error input TX.0: " + \
std::string(input));

Check warning on line 55 in src/operators/detect_xss.cc

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Modify the macro definition so that it needs to be followed by a semicolon, or remove this empty statement.

See more on https://sonarcloud.io/project/issues?id=owasp-modsecurity_ModSecurity&issues=AZ0vyq0lOXJ4yXD-WZ3H&open=AZ0vyq0lOXJ4yXD-WZ3H&pullRequest=3522
}
break;
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

The new LIBINJECTION_RESULT_ERROR fail-safe path changes behavior (treat error as match and optionally capture raw input). Please add a regression test that reliably triggers a libinjection ERROR result and asserts the match/capture behavior, so this security-critical branch stays covered.

Copilot uses AI. Check for mistakes.
case LIBINJECTION_RESULT_FALSE:
ms_dbg_a(t, 9, "libinjection was not able to " \
"find any XSS in: " + input);
break;
}
}

if (t == nullptr) {
is_match = xss_result == LIBINJECTION_RESULT_TRUE
|| xss_result == LIBINJECTION_RESULT_ERROR;
}
return is_xss != 0;

return is_match;
}


Expand Down
46 changes: 46 additions & 0 deletions test/test-cases/regression/operator-detectsqli.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,51 @@
"SecRuleEngine On",
"SecRule ARGS \"@detectSQLi\" \"id:1,phase:2,capture,pass,t:trim\""
]
},
{
"enabled": 1,
"version_min": 300000,
"title": "Testing Operator :: @detectSQLi benign input",
"client": {
"ip": "200.249.12.31",
"port": 123
},
"server": {
"ip": "200.249.12.31",
"port": 80
},
"request": {
"headers": {
"Host": "localhost",
"User-Agent": "curl/7.38.0",
"Accept": "*/*",
"Content-Length": "18",
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

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

Content-Length doesn't match the request body length here (param1=just_a_value is 19 bytes). The regression harness may auto-correct it, but keeping it accurate avoids confusion when reusing this case outside the harness.

Suggested change
"Content-Length": "18",
"Content-Length": "19",

Copilot uses AI. Check for mistakes.
"Content-Type": "application/x-www-form-urlencoded"
},
"uri": "/",
"method": "POST",
"body": [
"param1=just_a_value"
]
},
"response": {
"headers": {
"Date": "Mon, 13 Jul 2015 20:02:41 GMT",
"Last-Modified": "Sun, 26 Oct 2014 22:33:37 GMT",
"Content-Type": "text/html",
"Content-Length": "8"
},
"body": [
"no need."
]
},
"expected": {
"debug_log": "detected SQLi: not able to find an inject on 'just_a_value'",
"http_code": 200
},
"rules": [
"SecRuleEngine On",
"SecRule ARGS \"@detectSQLi\" \"id:2,phase:2,capture,pass,t:trim\""
]
}
]
46 changes: 46 additions & 0 deletions test/test-cases/regression/operator-detectxss.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,51 @@
"SecRuleEngine On",
"SecRule ARGS \"@detectXSS\" \"id:1,phase:2,capture,pass,t:trim\""
]
},
{
"enabled": 1,
"version_min": 300000,
"title": "Testing Operator :: @detectXSS benign input",
"client": {
"ip": "200.249.12.31",
"port": 123
},
"server": {
"ip": "200.249.12.31",
"port": 80
},
"request": {
"headers": {
"Host": "localhost",
"User-Agent": "curl/7.38.0",
"Accept": "*/*",
"Content-Length": "19",
"Content-Type": "application/x-www-form-urlencoded"
},
"uri": "/",
"method": "POST",
"body": [
"param1=safevalue123"
]
},
"response": {
"headers": {
"Date": "Mon, 13 Jul 2015 20:02:41 GMT",
"Last-Modified": "Sun, 26 Oct 2014 22:33:37 GMT",
"Content-Type": "text/html",
"Content-Length": "8"
},
"body": [
"no need."
]
},
"expected": {
"debug_log": "libinjection was not able to find any XSS in: safevalue123",
"http_code": 200
},
"rules": [
"SecRuleEngine On",
"SecRule ARGS \"@detectXSS\" \"id:2,phase:2,capture,pass,t:trim\""
]
}
]
Loading