Contributing
ModSecurity was transferred from Trustwave to OWASP in January 2024 and is developed by a small group of maintainers together with the community. Contributions of every kind are welcome: bug reports, fixes, features, tests, packaging, documentation and help for other users. This page explains how the project works and what a good contribution looks like.
Where things happen
- Code: https://github.com/owasp-modsecurity/ModSecurity, with the v2 engine on the
v2/masterbranch and the v3 library onv3/master(the default branch). The connectors are separate repositories: ModSecurity-nginx and ModSecurity-apache. - This documentation: https://github.com/owasp-modsecurity/documentation (every page has an edit link).
- Discussion: the
#project-modsecuritychannel on the OWASP Slack and the GitHub issue tracker. Questions about configuration and rules are best asked on Slack or as a GitHub discussion before opening an issue. - Project page: https://owasp.org/www-project-modsecurity/, which lists the project leaders. They review and merge every pull request.
Reporting a bug
Open an issue at https://github.com/owasp-modsecurity/ModSecurity/issues after checking that it has not been
reported. Include the engine version (2.9.x or 3.0.x), the connector and its version for v3, the web server
version, the operating system or package, the smallest rule that reproduces the problem, the request that
triggers it, and the relevant debug log at level 9 (SecDebugLogLevel 9). A failing regression test case
(see below) is the most useful report of all, since it becomes the test that keeps the bug fixed.
Reporting a security issue
Do not open a public issue, pull request or mailing list thread for a vulnerability. Report it privately through a draft security advisory on GitHub, where the maintainers triage it, coordinate the fix with you and publish the advisory together with the fixed release, crediting the reporter. If you cannot use GitHub, email [email protected]. The current policy is in SECURITY.md.
Proposing a feature
Open an issue describing the problem the feature solves and, if you have one, the SecLang syntax you propose. Both engines are maintained in parallel, so a new directive, variable, operator or action normally has to be implemented in both v2 and v3 and reflected in the SecLang specification; say early which parts you can take on. Discussing the design before writing code saves everyone time.
Sending a pull request
- Fork the repository and branch from
v2/masterorv3/master. A fix that applies to both engines is two pull requests, one per branch; link them to each other. - One logical change per commit, and nothing outside the scope of the change (no drive-by reformatting). The first line of the commit message says what changed; the body says why and how, since that is what reviewers and future maintainers read.
- Reference the issue with
Fixes #NNNin the pull request description. - Add or update tests (see the next section). Pull requests without a test for the change need a reason.
- CI runs the build and the test suites on Linux (gcc and clang, 32 and 64 bit, with every optional dependency on and off), macOS and Windows, plus cppcheck. All checks must pass; the cppcheck job is the one most often surprised by new code.
- Expect review comments and a request or two for changes; that is the normal course of a pull request.
- The release notes are written from the pull requests, so a clear title matters.
Coding guidelines
ModSecurity v2
- C, built with autotools against the Apache APR and httpd headers; the module must keep building against
Apache 2.4 and the IIS module in
iis/against Visual Studio (CMake). - Memory comes from APR pools; follow the existing allocation pattern of the function you are changing and never mix pool and malloc memory.
- New directives are registered in
apache2/apache2_config.c, variables inapache2/re_variables.c, actions inapache2/re_actions.c, operators inapache2/re_operators.cand transformations inapache2/re_tfns.c; each registry entry needs a unit test undertests/and an entry in this documentation. - Keep changes free of compiler warnings and run
make test(unit tests viatests/msc_test) andmake test-regression(the Apache-based regression suite, which needs a local httpd) before sending.
libModSecurity v3
- C++17, built with autotools (
./build.sh,./configure,make), CMake on Windows. The code follows the Chromium C++ style that the project adopted;make check-staticruns cppcheck andcpplintis part of the lint target. - The SecLang grammar lives in
src/parser/seclang-scanner.llandsrc/parser/seclang-parser.yy; the generated parser is committed, so regenerate it with./configure --enable-parser-generation(Flex and Bison required) and commit the result together with the grammar change. - Operators are classes under
src/operators/, transformations undersrc/actions/transformations/, actions undersrc/actions/, variables undersrc/variables/. Each is registered in the parser and, for operators and transformations, in the factory inoperator.ccortransformation.cc. - The public API lives in
headers/modsecurity/; changes there affect every connector and binding, so keep binary compatibility whenever possible and say so in the pull request when you cannot. - Use assertions for invariants and build with
--enable-assertionswhile developing;CFLAGS="-g -O0"gives readable backtraces in gdb and Valgrind.
Tests
Both trees carry their tests in the repository and in the shared
secrules-language-tests submodule, so a clone
needs git submodule update --init --recursive.
- v2:
make testbuildstests/msc_testand runs the unit tests intests/op/*.t,tests/tfn/*.tandtests/action/*.t(Perl hashes withinput,outputandret).make test-regressionrunstests/regression/*.tthrough a local Apache httpd. - v3:
make checkbuilds and runstest/unit_tests(JSON cases undertest/test-cases/unit/) andtest/regression_tests(JSON cases undertest/test-cases/regression/, each a request, a response, the rules to load and the expectedhttp_code,debug_log,error_log,audit_logorparser_error). A single file can be run withtest/regression_tests test/test-cases/regression/<file>.json, andtest/benchmarkmeasures throughput against a rule set. - A new operator or transformation needs a unit test; any other change is expected to come with a regression test that fails before the fix and passes after it. State in the pull request that you ran it both ways.
Documentation
This site is built with Hugo from Markdown in the documentation repository;
hugo serve renders it locally. Every reference-manual entry carries metadata saying in which v2 and v3
versions it is available, so a code change that adds, removes or alters a directive, variable, action,
operator or transformation should come with a pull request here, and corrections to the text are welcome on
their own. The conventions (American English, the secmeta block, the seclang code fences formatted per
the CRS guidelines) are described in the repository’s CLAUDE.md and enforced by its CI.
Packaging and bindings
Packages for the major distributions and the digitalwave repository are maintained by community members and the maintainers; if you package ModSecurity for another distribution, tell the project so it can be listed. The same goes for bindings to libModSecurity: the C and C++ API is kept stable so that bindings keep working across releases.