OWASP CRS Docker Image

June 9, 2026 ยท View on GitHub

Build Status GitHub issues GitHub PRs License

What is the OWASP CRS

OWASP CRS is a set of generic attack detection rules for use with ModSecurity or compatible web application firewalls. ModSecurity is an open source, cross platform web application firewall (WAF) engine for Apache, IIS and Nginx.

Supported Tags

Stable Tags

Stable Tags are composed of:

  • CRS version, in the format <major>[.<minor>[.<patch]]
  • web server variant
  • OS variant (optional, nginx only)
  • writable (optional)
  • date, in the format YYYYMMDDHHMM

The stable tag format is <CRS version>-<web server>[-<os>][-<writable>]-<date>. Examples (do not blindly copy these labels):

  • 4-nginx-202509051009
  • 4.18-nginx-202509051009
  • 4.18.0-nginx-202509051009 Or for the previous major release:
  • 3-nginx-alpine-202509051009
  • 3.3-nginx-alpine-202509051009
  • 3.3.7-nginx-alpine-202509051009

Rolling Tags

Rolling tags are updated whenever a new stable tag release occurs. Rolling tags can be practical but should not be used in production.

Rolling Tags are composed of:

  • web server variant
  • OS variant (optional)
  • writable (optional, nginx only)

The stable tag format is <web server>[-<os>][-<writable>]. Examples:

  • nginx
  • apache-alpine

LTS Tags

LTS (Long-Term Support) tags are stable tags pointing to a designated LTS release. They are updated less frequently than stable tags and are intended for users who prioritize stability over new features.

LTS Tags are composed of:

  • CRS version, in the format <minor> or <minor>.<patch>
  • web server variant
  • OS variant (optional)
  • lts suffix

The LTS tag format is <CRS version>-<web server>[-<os>]-lts. Examples:

  • 4.25-nginx-lts
  • 4.25.0-nginx-lts
  • 4.25-apache-lts
  • 4.25.0-apache-alpine-lts

OS Variants

  • nginx โ€“ latest stable ModSecurity v3 on Nginx 1.30.1 official stable base image, and latest stable OWASP CRS 4.27.0
  • Apache httpd โ€“ last stable ModSecurity v2 on Apache 2.4.67 official stable base image, and latest stable OWASP CRS 4.27.0

Read-only Root Filesystem

Important

Read-only filesystem variants are currently only available for images based on nginx.

By default, the root filesystem of our containers are writable. We also provide images that are set up to run on a read-only filesystem for enhanced security.

Examples:

  • nginx-read-only
  • nginx-alpine-read-only

Notes regarding Openresty version of this image

  • The version was removed as no maintainer was found.

Supported architectures

Our builds are based on the official Apache httpd, nginx and Openresty images, which means we can only support the architectures they support.

We currently provide images for the following architectures:

  • linux/amd64
  • linux/arm64
  • linux/i386

Building

If you want to see the targets of the build, use:

docker buildx bake -f ./docker-bake.hcl --print

To build for any platforms of your choosing, just use this example:

docker buildx create --use --platform linux/amd64,linux/i386,linux/arm64
docker buildx bake -f docker-bake.hcl

To build a specific target for a single platform only (replace target and platform strings in the example with your choices):

docker buildx bake -f docker-bake.hcl --set "*.platform=linux/amd64" nginx-alpine-writable

Notes regarding Openresty version of the image

Openresty image builds currently support only these architectures:

  • linux/amd64
  • linux/arm64

Container Health Checks

๐Ÿ†• We add healthchecks to the images, so that containers return HTTP status code 200 from the /healthz endpoint. When a container has a healthcheck specified, it has a health status in addition to its normal status. This status is initially starting. Whenever a health check passes, it becomes healthy (whatever state it was previously in). After a certain number of consecutive failures, it becomes unhealthy. See https://docs.docker.com/engine/reference/builder/#healthcheck for more information.

CRS Versions

Hey, I used some specific git version with the containers? What happened?

You can achieve the same results just by getting any version you want, and using docker volumes. See this example:

git clone https://github.com/coreruleset/coreruleset.git myrules
cd myrules
git checkout ac2a0d1
docker run -p 8080:8080 -ti -e BLOCKING_PARANOIA=4 -v rules:/opt/owasp-crs/rules:ro --rm owasp/modsecurity-crs

Quick reference

What is ModSecurity

ModSecurity is an open source, cross platform Web Application Firewall (WAF) engine for Apache, IIS and Nginx. It has a robust event-based programming language which provides protection from a range of attacks against web applications and allows for HTTP traffic monitoring, logging and real-time analysis.

SSL files naming breaking change

SSL related variables have been renamed to highlight they are a path to a file, so docker doesn't complain about sensitive usage in the case of variables ending in _KEY.

Nginx based images breaking change

โš ๏ธ WARNING
Nginx based images are now based on upstream nginx. This changed the way the config file for nginx is generated.

If using the Nginx environment variables is not enough for your use case, you can mount your own nginx.conf file as the new template for generating the base config.

An example can be seen in the docker-compose file.

๐Ÿ’ฌ What happens if I want to make changes in a different file, like /etc/nginx/conf.d/default.conf? You mount your local file, e.g. nginx/default.conf as the new template: /etc/nginx/templates/conf.d/default.conf.template. You can do this similarly with other files. Files in the templates directory will be copied and subdirectories will be preserved.

Both nginx and httpd containers now run with an unprivileged user. This means that we cannot bind to ports below 1024, so you might need to correct your PORT and SSL_PORT settings. Now the defaults for both nginx and httpd are 8080 and 8443.

Nginx port_in_redirect breaking change

Warning

port_in_redirect is set to off via NGINX_PORT_IN_REDIRECT in the http block (applies globally, including any custom server blocks you mount).

Previously, nginx's default port_in_redirect on caused the internal listening port (e.g., 8080 or 8443) to be included in redirect Location headers (e.g., when nginx adds a trailing slash: /address โ†’ http://example.com:8080/address/). This broke setups where the container is behind a reverse proxy and the external port differs from the internal port.

With port_in_redirect off (the default), nginx omits the port from redirect URLs, so clients follow redirects using the correct external port. If you relied on the port being included in nginx-generated redirects, set NGINX_PORT_IN_REDIRECT=on.

Common ENV Variables

These variables are common to image variants and will set defaults based on the image name.

NameDescriptionhttpd defaultnginx / Openresty default (if different)
ACCESSLOGLocation of the custom log file/var/log/apache2/access.log/var/log/nginx/access.log
BACKENDPartial URL for the remote server of the ProxyPass (httpd) and proxy_pass (nginx) directiveshttp://localhost:80-
ERRORLOGLocation of the error log file/proc/self/fd/2-
LOGLEVELMinimum level for log messages to be logged to the error logwarn-
METRICS_ALLOW_FROMA single range of IP addresses that can access the metrics127.0.0.0/255.0.0.0 ::1/128127.0.0.0/24
METRICS_DENY_FROMA range of IP addresses that cannot access the metricsAllall
METRICSLOGLocation of metrics log file/dev/null-
PROXY_SSL_CERT_FILEA string indicating the path to the PEM-encoded X.509 certificate data file or token identifier of the proxied server/usr/local/apache2/conf/proxy.crt/etc/nginx/conf/proxy.crt
PROXY_SSL_CERT_KEY_FILEA string indicating the path to the PEM-encoded private key file of the proxied server/usr/local/apache2/conf/proxy.key/etc/nginx/conf/proxy.key
PROXY_SSL_CIPHERSA string indicating the cipher suite to connect to the backend via TLS"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"-
PROXY_SSL_PROTOCOLSTLS protocols to enable for the connection to the backend"all -SSLv3 -TLSv1 -TLSv1.1"TLSv1.2 TLSv1.3
PROXY_SSLSSL Proxy Engine Operation Switchoff-
PROXY_SSL_VERIFYA string value indicating the type of proxy server Certificate verificationnoneoff
PROXY_TIMEOUTNumber of seconds for proxied requests to time out6060s
SERVER_NAMEThe server namelocalhost-
SSL_CERT_FILEA string indicating the path to the PEM-encoded X.509 certificate data file or token identifier of the proxied server/usr/local/apache2/conf/server.crt/etc/nginx/conf/server.crt
SSL_CERT_KEY_FILEA string indicating the path to the PEM-encoded private key file of the proxied server/usr/local/apache2/conf/server.key/etc/nginx/conf/server.key
SSL_CIPHERSA string indicating the cipher suite for incoming TLS connections"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"-
SSL_OCSP_STAPLINGEnable / disable OCSP staplingOnon
SSL_PROTOCOLSTLS protocols to enable for the connection to the backend"all -SSLv3 -TLSv1 -TLSv1.1"TLSv1.2 TLSv1.3

Apache ENV Variables

NameDescription
APACHE_ALWAYS_TLS_REDIRECTA string value indicating if http should redirect to https (Allowed values: on, off. Default: off)
APACHE_ERRORLOG_FORMATA string value indicating the ErrorLogFormat that Apache should use. (Default: '"[%{u}t] [%-m:%l] [pid %P:tid %T] %7F: %E: [client\ %a] %M% ,\ referer\ %{Referer}i"'
APACHE_LOGFORMATA string value indicating the LogFormat that apache should use. (Default: '"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""' (combined). Tip: use single quotes outside your double quoted format string.) โš ๏ธ Do not add a `
APACHE_METRICS_LOGFORMATA string value indicating the LogFormat that the additional log apache metrics should use. (Default:'"%h %l %u %t "%r" %>s %b "%{Referer}i" "%{User-agent}i""' (combined). Tip: use single quotes outside your double quoted format string.) โš ๏ธ Do not add a `
BACKEND_WSA string indicating the IP/URL of the WebSocket service (Default: ws://localhost:8081)
H2_DIRECTA string indicating whether unencrypted HTTP/2 connections are allowed without upgrading from HTTP/1.1. This mode is also called "prior knowledge. (Allowed values: on, off. Default: on)
H2_PROTOCOLSA string value indicating the protocols supported by the HTTP/2 module (Default: h2 h2c http/1.1)
MUTEXConfigure mutex and lock file directory for all specified mutexes (see Mutex) (Default: default)
PORTAn int value indicating the port where the webserver is listening to
PROXY_ERROR_OVERRIDEA string indicating that errors from the backend services should be overridden by this proxy server (see ProxyErrorOverride directive). (Allowed values: on, off. Default: on)
PROXY_PRESERVE_HOSTA string indicating the use of incoming Host HTTP request header for proxy request (Default: on)
PROXY_SSL_CA_CERT_FILEA string indicating the path to the PEM-encoded list of accepted CA certificates for the proxied server (Default: /etc/ssl/certs/ca-certificates.crt)
PROXY_SSL_CHECK_PEER_NAMEA string indicating if the host name checking for remote server certificates is to be enabled (Default: on)
REMOTEIP_INT_PROXYA string indicating the client intranet IP addresses trusted to present the RemoteIPHeader value (Default: 10.1.0.0/16)
REMOTEIP_HEADERA string indicating the header to use for RemoteIPHeader value (Default: X-Forwarded-For)
REQ_HEADER_FORWARDED_PROTOA string indicating the transfer protocol of the initial request (Default: https)
SERVER_ADMINA string value indicating the address where problems with the server should be e-mailed (Default: root@localhost)
SERVER_SIGNATUREA string value configuring the footer on server-generated documents (Allowed values: On, Off, EMail. Default: Off)
SERVER_TOKENSOption defining the server information presented to clients in the Server HTTP response header. Also see MODSEC_SERVER_SIGNATURE. (Allowed values: Full, Prod[uctOnly], Major, Minor, Min[imal], OS. Default: Full).
SSL_ENGINEA string indicating the SSL Engine Operation Switch (Default: on)
SSL_HONOR_CIPHER_ORDERA string indicating if the server should honor the cipher list provided by the client (Allowed values: on, off. Default: off)
SSL_PORTPort number where the SSL enabled webserver is listening
SSL_SESSION_TICKETSA string to enable or disable the use of TLS session tickets (RFC 5077). (Default: off)
TIMEOUTNumber of seconds before receiving and sending timeout (Default: 60)
WORKER_CONNECTIONSMaximum number of MPM request worker processes (Default: 400)

Note

Apache access and metric logs can be disabled by exporting the nologging=1 environment variable, or using ACCESSLOG=/dev/null and METRICSLOG=/dev/null.

Nginx ENV Variables

NameDescription
CORS_HEADER_403_ALLOW_ORIGINThe value of the Access-Control-Allow-Origin header for 403 responses. Determines which origins can access the response. (Default: "*").
CORS_HEADER_403_ALLOW_METHODSThe value of the Access-Control-Request-Method header for 403 responses. Determines the allowed request methods for the resource. Default: "GET, POST, PUT, DELETE, OPTIONS"
CORS_HEADER_403_CONTENT_TYPEThe value of the Content-Type header for 403 responses. Default: ("text/html")
CORS_HEADER_403_MAX_AGEThe value of the Access-Control-Max-Age header for 403 responses. The number of seconds that preflight requests for this resource may be cached by the browser. (Default: 3600)
DNS_SERVERDeprecated. Use RESOLVERS.
HTTP2A string value indicating whether HTTP/2 should be enabled (for all locations) (Allowed values: on, off. Default: on)
KEEPALIVE_TIMEOUTNumber of seconds for a keep-alive client connection to stay open on the server side (Default: 60s)
NGINX_ALWAYS_TLS_REDIRECTA string value indicating if http should redirect to https (Allowed values: on, off. Default: off)
NGINX_PORT_IN_REDIRECTControls nginx's port_in_redirect directive in the http block. When off, nginx omits the internal port (e.g., 8080) from redirect URLs โ€” correct for most reverse-proxy deployments. Set to on only if you need nginx to include its listening port in redirects. (Allowed values: on, off. Default: off)
NGINX_X_FORWARDED_PORTA string indicating the port of the initial request, sent as the X-Forwarded-Port header to the upstream backend. Can be set to a fixed port (e.g., 443) when the container is behind a reverse proxy. (Default: $server_port)
NGINX_X_FORWARDED_PROTOA string indicating the transfer protocol of the initial request (Default: $scheme)
PORTAn int value indicating the port where the webserver is listening to
PROXY_SSL_VERIFY_DEPTHAn integer value indicating the verification depth for the client certificate chain (Default: 1)
REAL_IP_HEADERName of the header containing the real IP value(s) (Default: X-REAL-IP). See real_ip_header
REAL_IP_PROXY_HEADERName of the header containing $remote_addr to be passed to proxy (Default: X-REAL-IP). See proxy_set_header
REAL_IP_RECURSIVEA string value indicating whether to use recursive replacement on addresses in REAL_IP_HEADER (Allowed values: on, off. Default: on). See real_ip_recursive
RESOLVERSA string of one or more DNS server IP addresses (IPv4 or IPv6, space separated, with optional port number. See nginx docs). The name servers are used to resolve names of upstream servers into addresses. If this variable is not set, the nameserver entry from /etc/resolv.conf will be used. For localhost backend the variable should not be set (Default: not defined)
RESOLVER_CONFIGA string of options for the resolver directive (see nginx docs) (Default: valid=5s)
SERVER_TOKENSA boolean value for enabling / disabling emission of server identifying information in the Server HTTP response header and on error pages. (Allowed values: on, off, build. Default: off).
SET_REAL_IP_FROMA string of comma separated IP, CIDR, or UNIX domain socket addresses that are trusted to replace addresses in REAL_IP_HEADER (Default: 127.0.0.1). See set_real_ip_from
SSL_DH_BITSA numeric value indicating the size (in bits) to use for the generated DH-params file (Default 2048)
SSL_PORTPort number where the SSL enabled webserver is listening
SSL_PREFER_CIPHERSA string value indicating if the server ciphers should be preferred over client ciphers when using the SSLv3 and TLS protocols (Allowed values: on, off. Default: off)
SSL_VERIFYA string value indicating if the client certificates should be verified (Allowed values: on, off. Default: off)
SSL_VERIFY_DEPTHAn integer value indicating the verification depth for the client certificate chain (Default: 1)
WORKER_CONNECTIONSMaximum number of simultaneous connections that can be opened by a worker process (Default: 1024)

Openresty ENV Variables

Openresty uses the same environment variables as the nginx version.

ModSecurity ENV Variables

All these variables impact in configuration directives in the modsecurity engine running inside the container. The reference manual has the extended documentation, and for your reference we list the specific directive we change when you modify the ENV variables for the container.

NameDescription
MODSEC_ARGUMENT_SEPARATORA character to use as the separator for application/x-www-form-urlencoded content. (Default: &). :warning: Do not touch unless you really know what you are doing. See SecArgumentSeparator
MODSEC_ARGUMENTS_LIMITAn integer indicating the maximum number of arguments that can be processed before setting the REQBODY_ERROR variable (Default 1000). See SecArgumentsLimit
MODSEC_AUDIT_ENGINEA string used to configure the audit engine, which logs complete transactions (Default: RelevantOnly). Accepted values: On, Off, RelevantOnly. See SecAuditEngine for additional information.
MODSEC_AUDIT_LOGA string indicating the path to the main audit log file or the concurrent logging index file (Default: /dev/stdout)
MODSEC_AUDIT_LOG_FORMATA string indicating the output format of the AuditLogs (Default: JSON). Accepted values: JSON, Native. See SecAuditLogFormat for additional information.
MODSEC_AUDIT_LOG_PARTSA string that defines which parts of each transaction are going to be recorded in the audit log (Default: 'ABIJDEFHZ'). See SecAuditLogParts for the accepted values.
MODSEC_AUDIT_LOG_RELEVANT_STATUSA regular expression string that defines the http error codes that are relevant for audit logging (Default: `"^(?:5
MODSEC_AUDIT_LOG_TYPEA string indicating the type of audit logging mechanism to be used (Default: Serial). Accepted values: Serial, Concurrent (HTTPS works only on Nginx - v3). See SecAuditLogType for additional information.
MODSEC_COOKIE_FORMATThe cookie format used (Default: 0 use Netscape cookies) :warning: Do not touch unless you really know what you are doing. See SecCookieFormat.
MODSEC_AUDIT_STORAGE_DIRA string indicating the directory where concurrent audit log entries are to be stored (Default: /var/log/modsecurity/audit/)
MODSEC_DATA_DIRA string indicating the path where persistent data (e.g., IP address data, session data, and so on) is to be stored (Default: /tmp/modsecurity/data)
MODSEC_DEBUG_LOGA string indicating the path to the ModSecurity debug log file (Default: /dev/null)
MODSEC_DEBUG_LOGLEVELAn integer indicating the verboseness of the debug log data (Default: 0). Accepted values: 0 - 9. See SecDebugLogLevel.
MODSEC_DEFAULT_PHASE1_ACTIONModSecurity string with the contents for the default action in phase 1 (Default: 'phase:1,log,auditlog,pass,tag:\'\${MODSEC_TAG}\'')
MODSEC_DEFAULT_PHASE2_ACTIONModSecurity string with the contents for the default action in phase 2 (Default: 'phase:2,log,auditlog,pass,tag:\'\${MODSEC_TAG}\'')
MODSEC_DISABLE_BACKEND_COMPRESSIONA string indicating whether or not to disable backend compression (Default: On). Allowed values: On, Off. See SecDisableBackendCompression for more. Only supported in ModSecurity 2.x, will have no effect on 3.x
MODSEC_PCRE_MATCH_LIMITAn integer value indicating the limit for the number of internal executions in the PCRE function (Default: 100000) (Only valid for Apache - v2). See SecPcreMatchLimit
MODSEC_PCRE_MATCH_LIMIT_RECURSIONAn integer value indicating the limit for the depth of recursion when calling PCRE function (Default: 100000)
MODSEC_REQ_BODY_ACCESSA string value allowing ModSecurity to access request bodies (Default: On). Allowed values: On, Off. See SecRequestBodyAccess for more information.
MODSEC_REQ_BODY_JSON_DEPTH_LIMITAn integer value indicating the maximum JSON request depth (Default: 512). See SecRequestBodyJsonDepthLimit for additional information.
MODSEC_REQ_BODY_LIMIT_ACTIONA string value for the action when SecRequestBodyLimit is reached (Default: Reject). Accepted values: Reject, ProcessPartial. See SecRequestBodyLimitAction for additional information.
MODSEC_REQ_BODY_LIMITAn integer value indicating the maximum request body size accepted for buffering (Default: 13107200). See SecRequestBodyLimit for additional information.
MODSEC_REQ_BODY_NOFILES_LIMITAn integer indicating the maximum request body size ModSecurity will accept for buffering (Default: 131072). See SecRequestBodyNoFilesLimit for more information.
MODSEC_RESP_BODY_ACCESSA string value allowing ModSecurity to access response bodies (Default: On). Allowed values: On, Off. See SecResponseBodyAccess for more information.
MODSEC_RESP_BODY_LIMIT_ACTIONA string value for the action when SecResponseBodyLimit is reached (Default: ProcessPartial). Accepted values: Reject, ProcessPartial. See SecResponseBodyLimitAction for additional information.
MODSEC_RESP_BODY_LIMITAn integer value indicating the maximum response body size accepted for buffering (Default: 1048576)
MODSEC_RESP_BODY_MIMETYPEA string with the list of mime types that will be analyzed in the response (Default: 'text/plain text/html text/xml'). You might consider adding application/json documented here.
MODSEC_RULE_ENGINEA string value enabling ModSecurity itself (Default: On). Accepted values: On, Off, DetectionOnly. See SecRuleEngine for additional information.
MODSEC_SERVER_SIGNATURESets the directive SecServerSignature and instructs ModSecurity to change the data presented in the "Server:" response header token when Apache ServerTokens directive is set to Full. Also see Apache SERVER_TOKENS. Only supported in ModSecurity 2.x, will have no effect on 3.x. (Default: Apache).
MODSEC_STATUS_ENGINEA string used to configure the status engine, which sends statistical information (Default: Off). Accepted values: On, Off. See SecStatusEngine for additional information.
MODSEC_TAGA string indicating the default tag action, which will be inherited by the rules in the same configuration context (Default: modsecurity)
MODSEC_TMP_DIRA string indicating the path where temporary files will be created (Default: /tmp/modsecurity/tmp)
MODSEC_TMP_SAVE_UPLOADED_FILESA string indicating if temporary uploaded files are saved (Default: On) (only relevant in Apache - ModSecurity v2)
MODSEC_UNICODE_MAPPINGThe unicode Code Point to use form the default file(Default: 20127). See SecUnicodeMapFile
MODSEC_UPLOAD_DIRA string indicating the path where intercepted files will be stored (Default: /tmp/modsecurity/upload)
MODSEC_UPLOAD_FILE_MODE(Default: 0600)
MODSEC_UPLOAD_KEEP_FILESConfigures whether or not the intercepted files will be kept after transaction is processed. (Default: RelevantOnly on Apache, Off on nginx) Accepted values: On, Off, RelevantOnly (only modsec2). See SecUploadKeepFiles and libmodsecurity3

CRS specific

NameDescription
ALLOWED_HTTP_VERSIONSA string indicating the allowed_http_versions (Default: HTTP/1.0 HTTP/1.1 HTTP/2 HTTP/2.0)
ALLOWED_METHODSA string indicating the allowed_methods (Default: GET HEAD POST OPTIONS)
ALLOWED_REQUEST_CONTENT_TYPEA string indicating the allowed_request_content_type (Default: |application/x-www-form-urlencoded| |multipart/form-data| |multipart/related| |text/xml| |application/xml| |application/soap+xml| |application/json| |application/cloudevents+json| |application/cloudevents-batch+json|)
ALLOWED_REQUEST_CONTENT_TYPE_CHARSETA string indicating the allowed_request_content_type_charset (Default: |utf-8| |iso-8859-1| |iso-8859-15| |windows-1252|)
ANOMALY_INBOUNDAn integer indicating the inbound_anomaly_score_threshold (Default: 5)
ANOMALY_OUTBOUNDAn integer indicating the outbound_anomaly_score_threshold (Default: 4)
ARG_LENGTHAn integer indicating the arg_length (Default: unlimited)
ARG_NAME_LENGTHAn integer indicating the arg_name_length (Default: unlimited)
BLOCKING_PARANOIA(:new: Replaces PARANOIA in CRSv4) An integer indicating the paranoia level (Default: 1)
COMBINED_FILE_SIZESAn integer indicating the combined_file_sizes (Default: unlimited)
CRS_DISABLE_PLUGINSA boolean indicating whether plugins will be disabled (Only from v4 and up. Default: 0)
CRS_ENABLE_TEST_MARKERA boolean indicating whether to write test markers to the log file (Used for running the CRS test suite. Default: 0)
DETECTION_PARANOIA(:new: Replaces EXECUTING_PARANOIA in CRSv4) An integer indicating the detection_paranoia_level (Default: BLOCKING_PARANOIA)
ENFORCE_BODYPROC_URLENCODEDA boolean indicating the enforce_bodyproc_urlencoded (Default: 0)
EXECUTING_PARANOIAAn integer indicating the executing_paranoia_level (Default: PARANOIA)
MANUAL_MODEA boolean indicating that you are providing your own crs-setup.conf file mounted as volume. (Default: 0 == automatic mode). โš ๏ธ None of the following variables are used if you set it to 1.
MAX_FILE_SIZEAn integer indicating the max_file_size (Default: unlimited)
MAX_NUM_ARGSAn integer indicating the max_num_args (Default: unlimited)
PARANOIAAn integer from 1 through 4, indicating the paranoia level (Default: 1)
REPORTING_LEVELAn integer from 0 through 5, indicating the level of verbosity when reporting anomaly scores. See rule 900115 for details. (Default: 4)
RESTRICTED_EXTENSIONSA string indicating the restricted_extensions (Default: .asa/ .asax/ .ascx/ .axd/ .backup/ .bak/ .bat/ .cdx/ .cer/ .cfg/ .cmd/ .com/ .config/ .conf/ .cs/ .csproj/ .csr/ .dat/ .db/ .dbf/ .dll/ .dos/ .htr/ .htw/ .ida/ .idc/ .idq/ .inc/ .ini/ .key/ .licx/ .lnk/ .log/ .mdb/ .old/ .pass/ .pdb/ .pol/ .printer/ .pwd/ .rdb/ .resources/ .resx/ .sql/ .swp/ .sys/ .vb/ .vbs/ .vbproj/ .vsdisco/ .webinfo/ .xsd/ .xsx/)
RESTRICTED_HEADERS_BASICA string indicating the restricted_headers_basic (Default: /content-encoding/ /proxy/ /lock-token/ /content-range/ /if/ /x-http-method-override/ /x-http-method/ /x-method-override/)
RESTRICTED_HEADERS_EXTENDEDA string indicating the restricted_headers_extended (Default: /accept-charset/)
STATIC_EXTENSIONSA string indicating the static_extensions (Default: /.jpg/ /.jpeg/ /.png/ /.gif/ /.js/ /.css/ /.ico/ /.svg/ /.webp/)
TOTAL_ARG_LENGTHAn integer indicating the total_arg_length (Default: unlimited)
VALIDATE_UTF8_ENCODINGA boolean indicating the crs_validate_utf8_encoding (Default: 0)

TLS/HTTPS

Important


The default configuration generates a self signed certificate on first run. To use your own certificates (recommended) COPY or mount (-v) your server.crt and server.key into /usr/local/apache2/conf/ or /etc/nginx/conf/. Remember to publish the HTTPS port when running the image.

docker build -t my-modsec .
docker run -p 8443:8443 my-modsec

TLS is configured on port 8443 and enabled by default.

We use sane intermediate defaults taken from the Mozilla SSL config tool. Please review the defaults and choose the ones that best match your needs.

You can set the *_ALWAYS_TLS_REDIRECT environment variables to always redirect from http to https.

Proxy Configuration

The owasp/modsecurity-crs container images in their default configuration (i.e., without manual changes to / overrides of configuration files) act as reverse proxies and require a running backend at the address specified through the BACKEND environment variable.

Important

Make sure to set the BACKEND variable to an address where a web server is listening. Otherwise nothing useful will happen when you send requests to the owasp/modsecurity-crs container (at least not with the default configuration).

ModSecurity is often used in a reverse proxy setup with the following properties:

  • reverse proxy acts as public end point
  • reverse proxy performs TLS termination (necessary for ModSecurity to inspect content)
  • ModSecurity runs on the reverse proxy to filter traffic
  • only benign traffic is passed to the backend

This allows one to use ModSecurity without modifying the webserver hosting the underlying application and also protects web servers that ModSecurity cannot currently be embedded into.

Tips:

  • the application web server (the one receiving traffic from the reverse proxy) should not listen on a public interface. Only the reverse proxy should be exposed to the public. With Docker, this could mean setting up a network for both containers and only exposing the reverse proxy with -p 8080:8080, for example. docker compose takes care of this automatically. See the docker-compose.yaml for an example setup.
docker build -t my-modsec . -f
docker run -p 8080:8080 -e BACKEND=http://example.com my-modsec

ServerName

It is often convenient to set your server name (set to localhost by default). To do this simply use the SERVER_NAME environment variable.

docker build -t modsec .
docker run -p 8080:8080 -e SERVER_NAME=myhost my-modsec

ModSecurity CRS Tuning

There are two possible ways to pass ModSecurity CRS tuning rules to the container:

  • To map the ModSecurity tuning file(s) via volumes into the container during the run command
  • To copy the ModSecurity tuning file(s) into the created container and then start the container

Map ModSecurity tuning file via volume

docker run -dti --rm \
   -p 8080:8080 \
   -v /path/to/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf:/etc/modsecurity.d/owasp-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf \
   -v /path/to/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf:/etc/modsecurity.d/owasp-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf \
   owasp/modsecurity-crs:apache

Copy ModSecurity tuning file into created container

This example can be helpful when no volume mounts are possible (some CI pipelines).

docker create -ti --name modseccrs \
   -p 8080:8080 \
   owasp/modsecurity-crs:apache

docker cp /path/to/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf \
   modseccrs:/etc/modsecurity.d/owasp-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf

docker start modseccrs

Full docker run example of possible setup

The following example illustrates how to use docker run with some of the variables. Its purpose is illustration only and it should not be used to run a container in production.

Some important things to note:

  • Error and audit logs are enabled and mapped to files on the host, so that their contents are accessible and don't pollute the container filesystem. Docker requires these files to exist, otherwise they would be created as directories, hence the use of the touch ... commands.
  • For containers with read-only filesystems, the volumes might have to be specified differently, e.g., using tmpfs. Alternatively, if only one log output is required, the output could be redirected to stdout (/proc/self/fd/2).
  • The example expects a backend web server to be running at localhost:8081.
touch /tmp/host-fs-auditlog.log
touch /tmp/host-fs-errorlog.log
docker run \
   -dti \
   -p 8080:8080 \
   --rm \
   -v /tmp/host-fs-auditlog.log:/var/log/modsec_audit.log \
   -v /tmp/host-fs-errorlog.log:/var/log/modsec_error.log \
   -e MODSEC_AUDIT_ENGINE=on \
   -e MODSEC_AUDIT_LOG=/var/log/modsec_audit.log \
   -e LOGLEVEL=warn \
   -e ERRORLOG=/var/log/modsec_error.log \
   -e BLOCKING_PARANOIA=2 \
   -e DETECTION_PARANOIA=2 \
   -e ENFORCE_BODYPROC_URLENCODED=1 \
   -e ANOMALY_INBOUND=10 \
   -e ANOMALY_OUTBOUND=5 \
   -e ALLOWED_METHODS="GET POST PUT" \
   -e ALLOWED_REQUEST_CONTENT_TYPE="text/xml|application/xml|text/plain" \
   -e ALLOWED_REQUEST_CONTENT_TYPE_CHARSET="utf-8|iso-8859-1" \
   -e ALLOWED_HTTP_VERSIONS="HTTP/1.1 HTTP/2 HTTP/2.0" \
   -e RESTRICTED_EXTENSIONS=".cmd/ .com/ .config/ .dll/" \
   -e RESTRICTED_HEADERS="/proxy/ /if/" \
   -e STATIC_EXTENSIONS="/.jpg/ /.jpeg/ /.png/ /.gif/" \
   -e MAX_NUM_ARGS=128 \
   -e ARG_NAME_LENGTH=50 \
   -e ARG_LENGTH=200 \
   -e TOTAL_ARG_LENGTH=6400 \
   -e MAX_FILE_SIZE=100000 \
   -e COMBINED_FILE_SIZES=1000000 \
   -e TIMEOUT=60 \
   -e SERVER_ADMIN=root@localhost \
   -e SERVER_NAME=localhost \
   -e PORT=8080 \
   -e MODSEC_RULE_ENGINE=on \
   -e MODSEC_REQ_BODY_ACCESS=on \
   -e MODSEC_REQ_BODY_LIMIT=13107200 \
   -e MODSEC_REQ_BODY_NOFILES_LIMIT=131072 \
   -e MODSEC_RESP_BODY_ACCESS=on \
   -e MODSEC_RESP_BODY_LIMIT=524288 \
   -e MODSEC_PCRE_MATCH_LIMIT=1000 \
   -e MODSEC_PCRE_MATCH_LIMIT_RECURSION=1000 \
   -e VALIDATE_UTF8_ENCODING=1 \
   -e CRS_ENABLE_TEST_MARKER=1 \
   -e BACKEND="http://localhost:8081" \
   owasp/modsecurity-crs:apache

Kubernetes

:warning: If you see this error in your k8s deployment logs:

...
/docker-entrypoint.d/20-envsubst-on-templates.sh: 53: envsubst: Argument list too long

This happens because kubernetes is injecting service related environment variables. Adding enableServiceLinks: false in your pod spec, solves the problem:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  replicas: 1
  template:
    spec:
      enableServiceLinks: false
      containers:
        - name: my-container
          image: owasp/modsecurity-crs:4.8.0-nginx-202411071011