Skip to content

Releases: dvershinin/gixy

v0.2.48

04 Jun 14:57

Choose a tag to compare

Fixed

  • Circular include directives no longer crash the parser (#113, fixed in #115). nginx configs with an include cycle β€” most commonly a file in /etc/nginx/conf.d/ whose body says include /etc/nginx/conf.d/*.conf; (the glob matches the including file itself), or A↔B mutual includes β€” used to send NginxParser into unbounded recursion. On Python 3.11+ with enough stack budget that surfaced as RecursionError; on others the cycle silently inflated the parsed tree with hundreds of duplicated directives. The parser now tracks the canonical path of every file currently being parsed and skips any include that re-enters one already on the stack, emitting a single Skipping circular include: … WARNING per cycle. Applies to both filesystem includes and nginx -T dump-mode includes.

Full changelog: https://github.com/dvershinin/gixy/blob/master/CHANGELOG.md

v0.2.47

23 May 04:09

Choose a tag to compare

Added

  • nginx_cves: New entry CVE-2026-9256 β€” heap memory buffer overflow in ngx_http_rewrite_module triggered by a configuration with overlapping captures, potentially resulting in arbitrary code execution in a worker process. Affects nginx OSS 0.1.17..1.31.0. Mitigation: upgrade to 1.31.1 (mainline) or 1.30.2 (stable). The check fires purely on --nginx-version= match β€” --nginx-version=1.31.0 (previously considered patched) now reports this CVE. Advisory: https://nvd.nist.gov/vuln/detail/CVE-2026-9256, nginx CHANGES-1.30: https://nginx.org/en/CHANGES-1.30. Credit: Mufeed VH of Winfunc Research.

Full changelog: https://github.com/dvershinin/gixy/blob/v0.2.47/CHANGELOG.md

v0.2.46

21 May 09:33

Choose a tag to compare

Fixed

  • origins false positive on host regexes anchored with ($|/) (#111): A regex like ^https?://example\.com($|/)(?P<path>.*) was reported as matching the bypass http://example.com$aaaaa.evil.com, even though that string does not actually match β€” the $ in ($|/) is the end-of-string anchor, not a literal $.

    Root cause was in gixy/core/regexp.py: AtToken.generate() emitted the raw ^ / $ characters, and when an end anchor lived inside an alternation whose group had sibling tokens (e.g. the trailing (?P<path>.*)), _gen_combinator happily produced candidates with $ stranded mid-string. The origins plugin then mutated these impossible-match candidates into bogus bypass URLs.

    Switched anchors to sentinel characters during generation; candidates with interior anchors are dropped at the top-level yielder before any plugin sees them. Semantically-equivalent regex rewrites now produce identical candidate sets.

    Thanks to @realpixelcode for the detailed reproduction and follow-up.

v0.2.45

19 May 17:28

Choose a tag to compare

Fixed

  • Named regex capture groups in if blocks: gixy no longer logs a spurious Can't find variable 'name' INFO for configs like if ($http_referer ~ "^https?://example\.com(?P<path>.*)") { set $x $path; }. Server-scope prepopulate was descending into IfBlock to evaluate inner set directives before the if's regex capture groups had been registered; the block's own provide_variables are now registered before recursion (#111).
  • Crash on Python 3.11+ for regexes generating invalid DNS labels: gixy/plugins/origins.py called candidate_match.encode("idna") without protection. Python >= 3.11 idna codec rejects strings with empty or over-long labels (e.g. a regex containing \.\. or a 64+ char run), aborting the entire audit with UnicodeError: label empty or too long. The call is now guarded; on failure the raw candidate is used and downstream parse_url decides (#111).

v0.2.44

17 May 15:36

Choose a tag to compare

Fixed

  • Builtin variable table refresh: Recognize 13 nginx variables that were missing from gixy/core/builtin_variables.py, eliminating spurious [variable] INFO Can't find variable … log lines. Added: $http3 (ngx_http_v3_module, #110), $proxy_protocol_addr and $realip_remote_addr (previously their doc comments were present but the keys were missing), $proxy_protocol_server_addr, $proxy_protocol_server_port, $proxy_protocol_tlv_* (PROXY protocol v2), $sent_trailer_*, $upstream_trailer_*, $connection_time, $request_port, $is_request_port, $limit_conn_status, $limit_req_status. List derived by diffing every ngx_(http|stream)_variable_t array in nginx 1.29.5 source against the existing builtin table, excluding entries flagged NGX_HTTP_VAR_NOHASH (internal-only, unreachable from configs).

v0.2.43

16 May 08:01

Choose a tag to compare

Added

  • New check: ssl_stapling_without_resolver β€” flags SSL servers where ssl_stapling on is in effect but no resolver directive is reachable in scope. Without a resolver nginx can't fetch the OCSP response and stapling silently fails; clients fall back to making their own OCSP queries, adding handshake latency and defeating the point of stapling. The check skips non-SSL servers, servers that override with ssl_stapling off, and any configuration where a resolver is visible in the server or an enclosing scope.
  • nginx_cves database expansion β€” the CVE advisor now ships every nginx Open Source CVE listed on nginx.org/en/security_advisories.html. 50 entries spanning 2009 through 2026, up from a single entry in v0.2.42. Config-pattern triggers cover the mp4, HTTP/2, HTTP/3/QUIC, resolver, SSL session reuse, dav, scgi/uwsgi, charset, mail, stream-OCSP, SPDY, and SSL/TLS directives; pure binary-level bugs (CVE-2013-2028 chunked parser, CVE-2009-2629 URI buffer underflow, ...) fire from the version match alone. Range subtraction at module load time removes per-branch post-fix tails β€” users on patched stable branches (1.26.3 vs CVE-2025-23419, 1.22.1 vs CVE-2022-41741, 1.16.1 vs CVE-2019-9511, ...) are no longer flagged for CVEs their version actually patches.

Changed

  • nginx_cves gating semantics β€” a CVE with a config-pattern trigger now fires only when the trigger directive is present. The previous version-only fallback was noisy at scale; mp4-module CVEs no longer flag configs that never load mp4. Pure binary-level CVEs (no trigger) continue to fire whenever the version matches.

Fixed

  • Variable scope tracking β€” recognize set-like directives (set, auth_request_set, perl_set, set_by_lua, root) across block scopes regardless of source order. Variables defined later in a server {} (or any parent) block are now visible to nested location {} blocks that reference them, matching nginx's parse-time variable registration. Eliminates false Can't find variable INFO logs (#100).

Full changelog: https://github.com/dvershinin/gixy/blob/master/CHANGELOG.md

v0.2.42

15 May 12:54

Choose a tag to compare

What's New

Added β€” nginx_cves: unified nginx CVE advisor

Pass --nginx-version=X.Y.Z and gixy will report every CVE whose affected range covers your installed version, with the upgrade target. CVEs that also have a config-trigger pattern (currently CVE-2026-42945) enrich the report with the offending directives, so you see both "your binary is vulnerable" and "your config triggers it here" at once.

Without --nginx-version, the check stays silent β€” gixy is config-static and has no view of the binary, so there is nothing safe to assert.

$ gixy --nginx-version=1.29.8 /etc/nginx/nginx.conf
[HIGH] Known nginx CVE affects your installed version.
CVE-2026-42945 ("NGINX Rift"): Heap overflow in ngx_http_rewrite_module.
Your installed version is vulnerable AND the trigger pattern is present
in this config. Fixed in: 1.30.1, 1.31.0 (Plus: R32 P6, R36 P4).

First database entry: CVE-2026-42945 ("NGINX Rift")

  • Severity: HIGH (CVSS 9.2)
  • Affected: nginx OSS 0.6.27..1.30.0; nginx Plus R32..R36
  • Fixed in: 1.30.1, 1.31.0; Plus R32 P6, R36 P4
  • Trigger pattern: a rewrite whose replacement contains both an unnamed PCRE backreference ($1..$9 or ${1}..${9}) and a literal ?, followed by another rewrite/if/set in the same parent context. The script engine compiles an under-sized destination buffer using one escaping method, then writes via NGX_ESCAPE_ARGS in a second pass β€” the difference overflows the heap.
  • Mitigation: switch to named captures ((?<name>...) referenced as ${name}), or upgrade.
  • Advisory: NVD CVE-2026-42945

Extending the database

Adding a future CVE is one append to _CVES in gixy/plugins/nginx_cves.py; if it has a config-pattern trigger, drop a small _check_cve_<id>(root) generator alongside it.

Tests

Includes a regression fixture (tests/integration/inline_return_with_map.conf) pinning the fix for #105 β€” variable resolution in multiline return directive bodies referencing variables defined by map blocks.


Install / upgrade: pip install -U gixy-ng Β· Docker: docker pull getpagespeed/gixy:v0.2.42

v0.2.41

10 Apr 18:40

Choose a tag to compare

What's New

New check: regex_exact_match

Detects regex locations like location ~ ^/path$ that match a single literal path and can be replaced with an exact-match location (location = /path) for better performance.

NGINX processes exact-match locations first and skips the regex engine entirely, making them significantly faster.

Before:

location ~ ^/api/health$ {
    return 200;
}

After:

location = /api/health {
    return 200;
}

Includes quick-fix support for IDE integrations. Only flags case-sensitive regex (~), not case-insensitive (~*), since = is always case-sensitive.

Full changelog

v0.2.40

18 Mar 12:51

Choose a tag to compare

Fixed

  • weak_ssl_tls: Suppress ssl_prefer_server_ciphers on warning when ssl_conf_command Options PrioritizeChaCha is configured β€” OpenSSL's SSL_OP_PRIORITIZE_CHACHA already addresses the underlying concern (#107).

v0.2.39

17 Mar 15:09

Choose a tag to compare

Fixed

  • quic_bpf_reuseport: Detect quic_bpf directive in the main context (top level) where NGINX docs place it, not only inside events {} (#104).