Skip to content
Open
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d925bdc
chore: update Windows build to use PCRE2 as default
fzipi Feb 8, 2026
d1b1956
fix: update IIS installer file
fzipi Feb 8, 2026
b0dd255
chore: remove deprecated method using msm files
fzipi Feb 8, 2026
e9c84a6
fix: update dependencies howto to reflect changes
fzipi Feb 8, 2026
a4a5a5b
fix: apply comments from copilot review
fzipi Feb 8, 2026
a3fb241
ci: update msys2 action
fzipi Feb 8, 2026
9b87f0f
fix(ci): install VC redistributables
fzipi Feb 8, 2026
394f3b7
ci: update CRS version
fzipi Feb 8, 2026
7f07ffd
fix: support latest iis installer
fzipi Feb 8, 2026
b495486
fix(windows): add posix conformant names and suppress warnings
fzipi Feb 8, 2026
906eae5
fix: avoid redefinition if already in apr
fzipi Feb 8, 2026
2268276
chore: add debug information to identify install problems
fzipi Feb 8, 2026
6334d28
chore: update lua to 5.4
fzipi Feb 8, 2026
5aa007e
fix: windows x32
fzipi Feb 8, 2026
6d36425
fix: OWASP CRS install
fzipi Feb 8, 2026
191c51c
fix: download full CRS version to get tests also
fzipi Feb 8, 2026
ef44728
fix: release url
fzipi Feb 8, 2026
932c83b
Apply suggestions from code review
fzipi Feb 8, 2026
cf619f9
fix: address copilot suggestions
fzipi Feb 8, 2026
2fbcd90
fix: change backslash to slash
fzipi Feb 8, 2026
0f5e0a1
fix: include creation for directories in installer
fzipi Feb 8, 2026
ba624f3
fix: remove warning on deprecated action
fzipi Feb 8, 2026
4c52436
fix: add permissions to IIS
fzipi Feb 8, 2026
360691b
fix: use powershell for custom cmd
fzipi Feb 8, 2026
de2564f
fix: install crs path
fzipi Feb 13, 2026
76323ea
fix: installer dir creation
fzipi Feb 13, 2026
db46478
fix: address Copilot review feedback on Windows build
fzipi Feb 15, 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
119 changes: 105 additions & 14 deletions .github/workflows/test-ci-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ jobs:
echo "APACHE_ROOT=C:\tools\Apache24" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append

- name: Setup MSYS2
uses: msys2/setup-msys2@fb197b72ce45fb24f17bf3f807a388985654d1f2
uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda #v2.30.0
with:
msystem: ${{ matrix.arch == 'x86' && 'MINGW32' || 'UCRT64' }}
update: true
Expand Down Expand Up @@ -100,6 +100,7 @@ jobs:
-A $cmakeArch `
-DWITH_LUA=ON `
-DWITH_YAJL=ON `
-DWITH_PCRE_JIT=ON `
-S IIS -B "iis\build"

- name: Build IIS Module
Expand Down Expand Up @@ -166,29 +167,119 @@ jobs:
name: modsecurityiis-installers-${{ matrix.config }}
path: ${{ github.workspace }}/

- name: Install VC++ 2019 Redistributables (Prerequisites)
shell: pwsh
run: |
Write-Host "=== Checking Pre-Existing VC++ Installations ==="
Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*" -ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName -like "*Visual C++*" -or $_.DisplayName -like "*Microsoft Visual Studio*Runtime*" } |
Select-Object DisplayName, DisplayVersion, PSChildName |
Format-Table -AutoSize

Write-Host "`n=== Installing Visual C++ 2019 Redistributable (x64) ==="
$vc_x64_url = "https://aka.ms/vs/17/release/vc_redist.x64.exe"
$vc_x64_installer = "${{ github.workspace }}\vc_redist.x64.exe"
Invoke-WebRequest -Uri $vc_x64_url -OutFile $vc_x64_installer
$x64Process = Start-Process -FilePath $vc_x64_installer -ArgumentList "/install", "/quiet", "/norestart" -Wait -PassThru
Write-Host "VC++ x64 installer exit code: $($x64Process.ExitCode)"
# Exit codes: 0 = success, 1638 = already installed (newer version), 3010 = success (reboot required)
if ($x64Process.ExitCode -notin @(0, 1638, 3010)) {
Write-Error "VC++ x64 installation failed with exit code $($x64Process.ExitCode)"
exit 1
}

Write-Host "`n=== Installing Visual C++ 2019 Redistributable (x86) ==="
$vc_x86_url = "https://aka.ms/vs/17/release/vc_redist.x86.exe"
$vc_x86_installer = "${{ github.workspace }}\vc_redist.x86.exe"
Invoke-WebRequest -Uri $vc_x86_url -OutFile $vc_x86_installer
$x86Process = Start-Process -FilePath $vc_x86_installer -ArgumentList "/install", "/quiet", "/norestart" -Wait -PassThru
Write-Host "VC++ x86 installer exit code: $($x86Process.ExitCode)"
# Exit codes: 0 = success, 1638 = already installed (newer version), 3010 = success (reboot required)
if ($x86Process.ExitCode -notin @(0, 1638, 3010)) {
Write-Error "VC++ x86 installation failed with exit code $($x86Process.ExitCode)"
exit 1
}

Write-Host "VC++ 2019 Redistributables installed successfully"

# Verify installations
Write-Host "`nVerifying VC++ installations in registry..."
$vc142x64 = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64" -Name "Installed" -ErrorAction SilentlyContinue).Installed
# On 64-bit Windows, x86 runtime is in WOW6432Node
$vc142x86 = (Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x86" -Name "Installed" -ErrorAction SilentlyContinue).Installed
Write-Host "VC++ 2019 x64 in registry: $vc142x64"
Write-Host "VC++ 2019 x86 in registry: $vc142x86"

if (-not $vc142x64 -or -not $vc142x86) {
Write-Error "VC++ redistributables not properly registered. x64=$vc142x64, x86=$vc142x86"
exit 1
}

- name: Install MSI
shell: pwsh
run: |
Write-Host "=== Pre-Installation Debug Info ==="

# Check MSI file
$msiPath = "${{ github.workspace }}\modsecurityiis.msi"
if (-not (Test-Path $msiPath)) {
Write-Error "MSI file not found at $msiPath"
exit 1
}

# Install with logging for debugging
Write-Host "MSI file found: $msiPath"
Write-Host "MSI file size: $((Get-Item $msiPath).Length) bytes"

# Check IIS version
$iisVersion = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\InetStp" -Name "MajorVersion" -ErrorAction SilentlyContinue).MajorVersion
Write-Host "IIS Version: $iisVersion"

# Check VC++ redistributables
$vc142x64 = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64" -Name "Installed" -ErrorAction SilentlyContinue).Installed
$vc142x86 = (Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x86" -Name "Installed" -ErrorAction SilentlyContinue).Installed
Write-Host "VC++ 2019 x64 installed: $vc142x64"
Write-Host "VC++ 2019 x86 installed: $vc142x86"

Write-Host "`n=== Starting MSI Installation ==="

# Install with verbose logging
$installLog = "${{ github.workspace }}\install.log"
$installResult = Start-Process -FilePath "msiexec.exe" -ArgumentList @(
"/i", "`"$msiPath`"",
"/qn",
"/norestart",
"/l*", "`"$installLog`""
"/l*vx", "`"$installLog`""
) -Wait -PassThru


Write-Host "Installation process completed with exit code: $($installResult.ExitCode)"

# Check if log file was created
if (Test-Path $installLog) {
$logSize = (Get-Item $installLog).Length
Write-Host "Install log created: $installLog ($logSize bytes)"

Write-Host "`n=== Installation Log Contents ==="
if ($logSize -gt 0) {
Get-Content $installLog -Raw | Write-Host
} else {
Write-Host "WARNING: Log file is empty!"
}
} else {
Write-Host "WARNING: Install log was not created at $installLog"
}

if ($installResult.ExitCode -ne 0) {
Write-Host "`n=== Installation Failed ==="
Write-Host "Exit code: $($installResult.ExitCode)"
Write-Host "Common MSI error codes:"
Write-Host " 1603 - Fatal error during installation"
Write-Host " 1619 - Package could not be opened"
Write-Host " 1620 - Package could not be opened (corrupt)"
Write-Host " 1633 - Platform not supported"
Write-Error "MSI installation failed with exit code $($installResult.ExitCode)"
Get-Content $installLog | Write-Host
exit 1
}

Write-Host "`n=== Installation Successful ==="

$installDir = "C:\Program Files\ModSecurity IIS"
$requiredFiles = @(
Expand All @@ -204,13 +295,13 @@ jobs:
}
}

- name: Install OWASP Core Rules
- name: Install OWASP CRS
shell: pwsh
run: |
$crsVersion = "v4.18.0"
$crsUrl = "https://github.com/coreruleset/coreruleset/archive/refs/tags/$crsVersion.tar.gz"
$crsDir = "C:\Program Files\ModSecurity IIS\coreruleset"
$modSecurityConfigDir = "C:\Program Files\ModSecurity IIS"
$crsVersion = "4.23.0"
$crsUrl = "https://github.com/coreruleset/coreruleset/archive/refs/tags/v$crsVersion.tar.gz"
$crsDir = 'C:\Program Files\ModSecurity IIS\coreruleset'
$modSecurityConfigDir = 'C:\Program Files\ModSecurity IIS'

try {
New-Item -ItemType Directory -Path $crsDir -Force
Expand All @@ -221,8 +312,9 @@ jobs:
$newName = $_.Name.Replace(".example", "")
Rename-Item -Path $_.FullName -NewName $newName
}

$modSecurityConfigFile = "$modSecurityConfigDir\modsecurity_iis.conf"
$modsecConf = "$modSecurityConfigDir\modsecurity.conf"

$crsRules = @(
"Include coreruleset/crs-setup.conf",
Expand All @@ -234,8 +326,7 @@ jobs:

Add-Content -Path $modSecurityConfigFile -Value $crsRules

(Get-Content -Path $modSecurityConfigDir\modsecurity.conf) -replace 'SecRuleEngine DetectionOnly', 'SecRuleEngine On' | Set-Content -Path $modSecurityConfigDir\modsecurity.conf

(Get-Content -Path $modsecConf) -replace 'SecRuleEngine DetectionOnly', 'SecRuleEngine On' | Set-Content -Path $modsecConf
}
catch {
Write-Error "Failed to install OWASP Core Rules: $($_.Exception.Message)"
Expand Down
121 changes: 65 additions & 56 deletions README_WINDOWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,41 @@ by Tom Donovam, 4/2/2011

Dependency | Tested with | Note
----|------|----
Microsoft Visual Studio C++ | Visual Studio 2013 (aka VC12) |
[CMake build system](http://www.cmake.org/) | CMake v3.8.2 |
[Apache 2.4.x](http://httpd.apache.org/) | Apache 2.4.27 | Apache must be built from source using the same Visual Studio compiler as mod_security.
[PCRE, Perl Compatible Regular Expression library](http://www.pcre.org/) | PCRE v8.40
[LibXML2](http://xmlsoft.org/) | LibXML2 v2.9.4 |
[Lua Scripting Language](http://www.lua.org/) | Lua v5.3.4
[cURL multiprotocol file transfer library](http://curl.haxx.se/) | cURL v7.54.0
Microsoft Visual Studio C++ | Visual Studio 2019 (aka VS16) |
[CMake build system](http://www.cmake.org/) | CMake v4.2.3 |
[Apache 2.4.x](http://httpd.apache.org/) | Apache 2.4.66 | Apache must be built from source using the same Visual Studio compiler as mod_security.
[PCRE2, Perl Compatible Regular Expression library](https://www.pcre.org/) | PCRE2 v10.47 | ModSecurity v2 now uses PCRE2 by default (not legacy PCRE)
[LibXML2](http://xmlsoft.org/) | LibXML2 v2.15.1 |
[Lua Scripting Language](http://www.lua.org/) | Lua v5.4.8
[cURL multiprotocol file transfer library](http://curl.haxx.se/) | cURL v8.18.0
[zlib compression library](https://zlib.net/) | zlib v1.3.1


## Before building

The directory where you build software from source ( ``C:\work`` in this exmaple)
must contain the Apache source you used to build the Apache web serverand the mod_security source
The directory where you build software from source ( ``C:\work`` in this example)
must contain the Apache source you used to build the Apache web server and the mod_security source

Apache source is in C:\work\httpd-2.4.27 in this example.
Apache has been installed to C:\Apache2427 in this example.
Apache source is in C:\work\httpd-2.4.66 in this example.
Apache has been installed to C:\Apache2466 in this example.
Mod_security source is in C:\work\mod_security in this example.

## Download and untar the prerequisite library sources:

Download pcre-8.40.tar.gz from ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/
untar it into C:\work\ creating C:\work\pcre-8.40
Download pcre2-10.47.zip from https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.47/
unzip it into C:\work\ creating C:\work\pcre2-10.47

Download libxml2-2.9.4.tar.gz from ftp://xmlsoft.org/libxml2/
untar it into C:\work\ creating C:\work\libxml2-2.9.4
Download libxml2-2.15.1.tar.gz from https://download.gnome.org/sources/libxml2/2.15/
untar it into C:\work\ creating C:\work\libxml2-2.15.1

Download lua-5.3.4.tar.gz from http://www.lua.org/ftp/
untar it into C:\work\ creating C:\work\lua-5.3.4
Download lua-5.4.8.tar.gz from http://www.lua.org/ftp/
untar it into C:\work\ creating C:\work\lua-5.4.8

Download curl-7.54.0.tar.gz from http://curl.haxx.se/download.html
untar it into C:\work\ creating C:\work\curl-7.54.0
Download curl-8.18.0.zip from https://curl.se/download/
unzip it into C:\work\ creating C:\work\curl-8.18.0

Download zlib-1.3.1.tar.gz from https://github.com/madler/zlib/releases/download/v1.3.1/
untar it into C:\work\ creating C:\work\zlib-1.3.1

## Setup your build environment:

Expand All @@ -49,7 +53,7 @@ must contain the Apache source you used to build the Apache web serverand the mo
3. Set an environment variable to the Apache source code directory:

```
SET HTTPD_BUILD=C:\work\httpd-2.4.27
SET HTTPD_BUILD=C:\work\httpd-2.4.66
```

### Optional:
Expand All @@ -71,54 +75,58 @@ If OpenSSL and zlib support were included when you built Apache 2.4, and you wan

## Build

### PCRE-8.40
### PCRE2-10.47

CD C:\work\pcre-8.40
CMAKE -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_SHARED_LIBS=True
CD C:\work\pcre2-10.47
CMAKE -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_SHARED_LIBS=True -DPCRE2_BUILD_PCRE2_8=ON -DPCRE2_SUPPORT_JIT=ON
NMAKE

### LibXML2-2.9.4
Note: PCRE2 with JIT support provides better performance and fixes stack overflow issues present in older PCRE versions.

### LibXML2-2.15.1

CD C:\work\libxml2-2.9.4\win32
CD C:\work\libxml2-2.15.1\win32
CSCRIPT configure.js iconv=no vcmanifest=yes zlib=yes
NMAKE -f Makefile.msvc

### Lua-5.3.4
### Lua-5.4.8

CD C:\work\lua-5.3.4\src
CD C:\work\lua-5.4.8\src
CL /Ox /arch:SSE2 /GF /GL /Gy /FD /EHsc /MD /Zi /TC /wd4005 /D "_MBCS" /D "LUA_CORE" /D "LUA_BUILD_AS_DLL" /D "_CRT_SECURE_NO_WARNINGS" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_WIN32" /D "_WINDLL" /c *.c
DEL lua.obj luac.obj
LINK /DLL /LTCG /DEBUG /OUT:lua5.1.dll *.obj
IF EXIST lua5.1.dll.manifest MT -manifest lua5.1.dll.manifest -outputresource:lua5.1.dll;2
LINK /DLL /LTCG /DEBUG /OUT:lua54.dll *.obj
IF EXIST lua54.dll.manifest MT -manifest lua54.dll.manifest -outputresource:lua54.dll;2

### cURL-7.54.0
### cURL-8.18.0

CD C:\work\curl-7.54.0
CMAKE -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBUILD_SHARED_LIBS=True -DCURL_ZLIB=True
NMAKE
CD C:\work\curl-8.18.0\winbuild
SET ARCH=x64
NMAKE /f Makefile.vc mode=dll ENABLE_WINSSL=yes MACHINE=%ARCH% WITH_ZLIB=dll

### ModSecurity-2.9.x

CD C:\work\mod_security\apache2
NMAKE -f Makefile.win APACHE=C:\Apache2427 PCRE=C:\work\pcre-8.40 LIBXML2=C:\work\libxml2-2.9.4 LUA=C:\work\lua-5.3.4\src
NMAKE -f Makefile.win APACHE=C:\Apache2466 PCRE=C:\work\pcre2-10.47 LIBXML2=C:\work\libxml2-2.15.1 LUA=C:\work\lua-5.4.8\src CURL=C:\work\curl-8.18.0

## Install ModSecurity and run Apache

Copy these five files to ``C:\Apache2427\bin``:
Copy these files to ``C:\Apache2466\bin``:

C:\work\pcre-8.40\pcre.dll C:\Apache2427\bin\
C:\work\lua-5.3.4\src\lua5.1.dll C:\Apache2427\bin\
C:\work\libxml2-2.9.4\win32\bin.msvc\libxml2.dll C:\Apache2427\bin\
C:\work\curl-7.54.0\libcurl.dll C:\Apache2427\bin\
C:\work\mod_security\apache2\mlogc-src\mlogc.exe
C:\work\pcre2-10.47\pcre2-8.dll C:\Apache2466\bin\
C:\work\lua-5.4.8\src\lua54.dll C:\Apache2466\bin\
C:\work\libxml2-2.15.1\win32\bin.msvc\libxml2.dll C:\Apache2466\bin\
C:\work\curl-8.18.0\builds\libcurl-vc-x64-release-dll-zlib-dll-ipv6-sspi-schannel-obj-lib\libcurl.dll C:\Apache2466\bin\
C:\work\mod_security\apache2\mlogc-src\mlogc.exe C:\Apache2466\bin\
Copy link

Copilot AI Feb 17, 2026

Choose a reason for hiding this comment

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

The documentation references C:\work\mod_security\apache2\mlogc-src\mlogc.exe, but this repository’s mlogc project lives under the top-level mlogc/ directory (and there is no apache2\mlogc-src folder). Please update this path to the actual built mlogc.exe location so Windows users can follow the instructions successfully.

Suggested change
C:\work\mod_security\apache2\mlogc-src\mlogc.exe C:\Apache2466\bin\
C:\work\mod_security\mlogc\mlogc.exe C:\Apache2466\bin\

Copilot uses AI. Check for mistakes.

Copy this one file to ``C:\Apache2427\modules``:
Copy this one file to ``C:\Apache2466\modules``:

C:\work\mod_security\apache2\mod_security2.so

You may also copy ``C:\work\curl-7.54.0\curl.exe`` to ``C:\Apache2427\bin``, if you want to use the cURL command-line program.
You may also copy ``C:\work\curl-8.18.0\curl.exe`` to ``C:\Apache2466\bin``, if you want to use the cURL command-line program.

Download OWASP CRS from https://github.com/coreruleset/coreruleset/releases/latest and unzip it into ``C:\Apache2466\conf\owasp_crs``

Download the core rules from http://sourceforge.net/projects/mod-security/files/modsecurity-crs/0-CURRENT/ and unzip them into ``C:\Apache2427\conf\modsecurity_crs``
For example, download ``coreruleset-4.x.x.zip``, extract it, and rename the extracted directory to ``owasp_crs``.

Add configuration directives to your Apache conf\httpd.conf:

Expand All @@ -130,8 +138,9 @@ Add configuration directives to your Apache conf\httpd.conf:
<IfModule security2_module>
SecRuleEngine On
SecDataDir logs
Include conf/modsecurity_crs/*.conf
Include conf/modsecurity_crs/base_rules/*.conf
# Include OWASP CRS configuration
Include conf/owasp_crs/crs-setup.conf
Include conf/owasp_crs/rules/*.conf
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4\d[^4])"
SecAuditLogType Serial
Expand All @@ -144,34 +153,34 @@ Add configuration directives to your Apache conf\httpd.conf:
Edit the top of ``C:\work\mod_security\apache2\mlogc-src\Makefile.win`` and set your local paths

# Path to Apache httpd installation
BASE = C:\Apache2427
BASE = C:\Apache2466

# Paths to required libraries
PCRE = C:\work\pcre-8.40
CURL = C:\work\curl-7.54.0
PCRE = C:\work\pcre2-10.47
CURL = C:\work\curl-8.18.0

# Linking libraries
LIBS = $(BASE)\lib\libapr-1.lib \
$(BASE)\lib\libaprutil-1.lib \
$(PCRE)\pcre.lib \
$(CURL)\libcurl_imp.lib \
$(PCRE)\pcre2-8.lib \
$(CURL)\libcurl.lib \
wsock32.lib

Build the ``mlogc.exe`` program:

CD C:\work\mod_security_trunk\mlogc
NMAKE -f Makefile.win

Copy ``mlocg.exe`` to ``C:\Apache2427\bin\``
Copy ``mlocg.exe`` to ``C:\Apache2466\bin\``

Create a new command file ``C:\Apache2427\bin\mlogc.bat`` with one line:
Create a new command file ``C:\Apache2466\bin\mlogc.bat`` with one line:

C:\Apache2427\bin\mlogc.exe C:\Apache2427\conf\mlogc.conf
C:\Apache2466\bin\mlogc.exe C:\Apache2466\conf\mlogc.conf

Create a new configuration file ``C:\Apache2427\conf\mlogc.conf`` to control the piped-logging program ``mlogc.exe``.
Create a new configuration file ``C:\Apache2466\conf\mlogc.conf`` to control the piped-logging program ``mlogc.exe``.
Here is an example ``conf\mlogc.conf``:

CollectorRoot "C:/Apache2427/logs"
CollectorRoot "C:/Apache2466/logs"
ConsoleURI "https://localhost:8888/rpc/auditLogReceiver"
SensorUsername "test"
SensorPassword "testtest"
Expand All @@ -191,4 +200,4 @@ Here is an example ``conf\mlogc.conf``:

Change the SecAuditLog directive in ``conf\httpd.conf`` to pipe the log data to mlogc instead of writing them to a file:

SecAuditLog |C:/Apache2427/bin/mlogc.bat
SecAuditLog |C:/Apache2466/bin/mlogc.bat
Loading
Loading