Gixy reads your nginx configuration the way nginx does — following
include directives and globs — and reports what it finds. Each check below
links either to a full fix guide here, or to its reference page in the
documentation.
nginx -T > nginx-dump.conf
gixy nginx-dump.conf
HIGH
Exploitable, or actively breaking something. Fix these first.
| Check | What it means |
|---|---|
| alias_traversal | A location without a trailing slash plus alias lets attackers read files above the intended directory. |
| allow_without_deny | allow rules with no closing deny all; restrict nothing at all. |
| http_splitting | Unescaped variables in headers or redirects allow CRLF injection into the response. |
| if_is_evil | if inside location can silently skip directives or crash the worker. |
| nginx_cves | Your nginx version is affected by a published CVE. |
| origins | An Origin or Referer validation regex matches domains you do not control. |
| quic_bpf_reuseport | quic_bpf with reuseport silently drops QUIC connections after every reload. |
| regex_redos | A regex in your config can be forced into catastrophic backtracking. |
| resolver_external | Using a public DNS resolver exposes internal lookups and enables cache poisoning. |
| ssl_ecdh_curve | A post-quantum group name without the ? prefix stops nginx from starting. |
| ssrf | A user-controlled value reaches proxy_pass, allowing requests to internal services. |
| valid_referers | none in valid_referers accepts any request that simply omits the header. |
| version_disclosure | server_tokens is leaking your exact nginx version. |
| weak_ssl_tls | Obsolete protocols or ciphers are still enabled. |
MEDIUM
Real problems that need a trigger, plus silent failures where a feature you enabled is not working.
| Check | What it means |
|---|---|
| error_log_off | error_log off; does not disable logging -- it writes to a file named off. |
| hash_without_default | A map or geo block with no default yields an empty string on no match. |
| host_spoofing | The Host header is passed upstream unvalidated and can be forged. |
| hsts_header | HSTS is missing, short-lived, or scoped too narrowly. |
| invalid_regex | A capture group is referenced that the regex never defines. |
| missing_resolver | A proxy target is resolved once at start-up and then never again. |
| proxy_pass_normalized | A path after the host in proxy_pass decodes %2F before proxying. |
| return_bypasses_allow_deny | return answers the request before allow/deny is applied. |
| ssl_stapling_without_resolver | OCSP stapling is on but has no resolver, so it silently does nothing. |
| status_page_exposed | stub_status is reachable by anyone. |
| try_files_is_evil_too | try_files without open_file_cache adds a stat() storm per request. |
| worker_rlimit_nofile_vs_connections | worker_rlimit_nofile is too low for the configured worker_connections. |
LOW
Correctness and efficiency issues. Worth cleaning up, rarely urgent.
| Check | What it means |
|---|---|
| add_header_content_type | add_header cannot set Content-Type -- use default_type. |
| add_header_multiline | Multi-line headers are deprecated and parsed inconsistently by clients. |
| add_header_redefinition | A nested add_header silently drops every header set by the parent. |
| default_server_flag | Several servers share a listen socket with no default_server, so the winner is arbitrary. |
| http2_misdirected_request | No return 421 safeguard for coalesced HTTP/2 connections. |
| low_keepalive_requests | keepalive_requests is below 1000, forcing needless reconnects. |
| regex_exact_match | A regex location does the work of a cheaper exact match. |
| ssl_stapling_letsencrypt | OCSP stapling for a Let's Encrypt certificate is a no-op since 2025-08-06. |
| unanchored_regex | An unanchored regex scans the whole string on every request. |
Reading a finding
A Gixy finding has four parts, and the last two are the ones to read carefully:
- Check name — matches the plugin, and the pages above.
- Severity — how bad it is if it applies to you.
- Reason — why your config tripped it, not the generic description.
- Pseudo config — the reconstructed directives responsible, with the file and line. This is where you go to fix it.
Filter by severity when triaging a large configuration:
# MEDIUM and above
gixy -l 2 nginx-dump.conf
# Machine-readable, for CI
gixy -f json nginx-dump.conf
Suppressing a check
When a finding genuinely does not apply, silence it explicitly rather than ignoring the output — a scan people have learned to skim is a scan that has stopped working:
# Skip one check
gixy --skips=http_splitting nginx-dump.conf
# Or in gixy.cfg
[main]
skips = http_splitting,try_files_is_evil_too