All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- New check:
regex_exact_match: Detects regex locations likelocation ~ ^/path$that can be replaced with exact-matchlocation = /pathfor better performance. Includes quick-fix support for IDE integrations.
weak_ssl_tls: Suppressssl_prefer_server_ciphers onwarning whenssl_conf_command Options PrioritizeChaChais configured — OpenSSL'sSSL_OP_PRIORITIZE_CHACHAalready addresses the underlying concern (#107).
quic_bpf_reuseport: Detectquic_bpfdirective in the main context (top level) where NGINX docs place it, not only insideevents {}(#104).
quic_bpf_reuseport: Improved fix description to mention nginx-mod as an alternative to disablingquic_bpf.
- New check:
quic_bpf_reuseport: Detects dangerous combination ofquic_bpf on+reuseporton QUIC listeners + multiple workers that silently drops ~50% of QUIC connections afternginx -s reload(#104, nginx/nginx#425).
- Documentation: Fixed malformed Docker command in README and documentation (missing space before
nginx:alpine). - Documentation: Updated outdated
/plugins/paths to/checks/with kebab-case naming across all README and doc index files. - Documentation: Added missing
status_page_exposedcheck to the Access Control section in English documentation index. - CI/CD: Changed PyPI publish workflow trigger from
release: createdtorelease: publishedfor consistency with Docker publish workflow. - Code: Fixed double period typo in
gixy/core/variable.pydocstring.
status_page_exposedfalse positive: Servers listening only on Unix sockets (e.g.listen unix:/run/nginx/status.sock) no longer trigger the missing IP restrictions warning, since Unix domain sockets are inherently inaccessible from the network (#101).
- HSTS false positive:
security_headers on;(ngx_security_headers module) is now recognized as providing HSTS — no longer flags "Missing HSTS header". - HSTS false positive:
more_set_headerssettingStrict-Transport-Securityis now recognized as providing HSTS. ssl_prefer_server_ciphersfalse positive: Inverted the check —onis now flagged (LOW) instead ofoff(MEDIUM). All authoritative sources (Mozilla, nginx maintainers) recommendofffor modern cipher lists.
- Parser: Use
parse_string()API directly instead of temporary file workaround, now that ngxparse supports it.
- Dependency: Switched from
crossplanetongxparsefor NGINX config parsing. ngxparse is a maintained fork with bug fixes and the same API.
- Parser: Fixed tokenization of adjacent braced variables like
${var1}${var2}in map directives (ngxparse 0.5.16).
- Terminology: User-facing documentation now uses "checks" instead of "plugins" for clarity and consistency.
- CLI:
--checksis now the primary flag for selecting checks to run (--testsremains as a backward-compatible alias). - Configuration: Config files now prefer
checks = ...overtests = ...(both still work for backward compatibility). - Help URLs: Plugin help URLs are now auto-generated from class names using kebab-case slugs (e.g.,
http_splitting→/checks/http-splitting/). - Documentation URLs: All check documentation moved from
/plugins/to/checks/path with kebab-case naming.
- Pre-commit hooks: Removed hardcoded filesystem paths; hooks now work in any environment.
- Documentation front-matter: Fixed missing/short SEO metadata in Chinese documentation files.
- Plugin base class now auto-generates
help_urlproperty from class name (no manual URL definition needed). - Plugins can override with
_help_urlclass attribute for external documentation links. - Pre-commit check validates documentation file existence instead of URL format.
- New plugin:
hsts_header: Detects missing or weakStrict-Transport-Security(HSTS) configuration on HTTPS servers. - New plugin:
http2_misdirected_request: Detectsdefault_server+ HTTP/2 +ssl_reject_handshake onsetups missing a defensivelocation / { return 421; }.
weak_ssl_tlsscope clarified: HSTS checks were moved out tohsts_header(TLS protocols/ciphers and cipher preference remain inweak_ssl_tls).
- HSTS false positives: HSTS checks now correctly skip
ssl_reject_handshake on;servers (they cannot emit HTTP response headers).
- New plugin:
weak_ssl_tls: Detects weak SSL/TLS configurations including:- Insecure protocols (SSLv2, SSLv3, TLSv1, TLSv1.1)
- Weak cipher suites (NULL, DES, RC4, EXPORT, etc.)
- Missing or weak HSTS headers
ssl_prefer_server_ciphers offconfiguration
- Auto-fix mode: New
--fixand--fix-dry-runCLI options to automatically apply fixes for detected issues. Creates.bakbackup files by default (disable with--no-backup). - Python 3.6 pre-commit check: Full test suite now runs with Python 3.6 on every commit to ensure compatibility with minimum supported version.
- README overhaul: Reorganized plugin documentation into categorized table format with links to official docs.
scripts/test_py36.shnow runs the full test suite instead of a subset of tests.
- Added missing HSTS header to staging server in
wordpress_production.confintegration test.
- Checkstyle XML output format: New
-f checkstyleformatter for CI/CD integration. Works natively with Jenkins, GitLab CI, GitHub Actions (reviewdog), Bitbucket Pipelines, and SonarQube. Maps severities: HIGH→error, MEDIUM→warning, LOW→info. - Bandit security scanner: Added to pre-commit for local security scanning before push.
- Hardcoded IP address check: Custom pre-commit hook (
check_hardcoded_ips.py) mirrors SonarCloud rule S1313 for local detection of hardcoded IPs. - Path filters for CI: GitHub Actions workflow now skips tests when only docs/configs change.
- Documentation updated (en/ru/zh) to list
checkstyleas available output format.
- Added
# NOSONARand# noseccomments to suppress false positives from security scanners (SonarCloud, Bandit) for intentional patterns like test URLs, Jinja2 autoescape for CLI output, and test IP addresses.
- Python 3.6 compatibility: Fixed AST parsing in
check_plugin_help_urls.pyto useast.Str(Python 3.6/3.7) instead ofast.Constant(Python 3.8+).
- Python 3.6 compatibility: Removed type comments that referenced undefined names (
List,Tuple,Optional).
- Pre-commit configuration with Python 3.6 syntax checking using pyenv.
- CI job
py36-compatto verify scripts work on Python 3.6 minimum version.
- Quick Fix Support: Plugins now return machine-readable fix suggestions in JSON output for IDE integration.
Fixclass ingixy.core.issuewithtitle,search,replace, and optionaldescriptionfields.- Plugins can use
self.make_fix()helper to create fixes. - JSON formatter includes
fixesarray for each issue.
- Plugin fixes implemented:
version_disclosure: Setserver_tokens offhost_spoofing: Replace$http_hostwith$hostadd_header_content_type: Usedefault_typeinstead ofadd_header Content-Typeallow_without_deny: Adddeny all;after allow directivesvalid_referers: Removenonefrom refererserror_log_off: Set proper error_log pathresolver_external: Use internal DNS resolverlow_keepalive_requests: Increase keepalive_requests to 10000
- Pre-commit hooks: Added
.pre-commit-config.yamlwith plugin help_url validation. - CI checks: Enhanced GitHub Actions workflow with plugin validation checks.
version_disclosureplugin no longer double-reports whenserver_tokens onis at http level.- Plugin help_url validation script now correctly handles edge cases.
- All plugin
help_urlattributes now consistently point tohttps://gixy.getpagespeed.com/plugins/.
- ReDoS detection rewrite: Complete rewrite of
regex_redosplugin using Python's built-insre_parsemodule - no external dependencies required. Detects nested quantifiers (exponential O(2^n)), overlapping alternatives (polynomial O(n²)), and adjacent greedy quantifiers. - nginx 1.29.3 support:
add_header_redefinitionplugin now respectsadd_header_inherit on;directive. - Integration testing: Added comprehensive WordPress production config (~380 lines) as integration test to catch false positives.
- Documentation: Added missing
try_files_is_evil_too.md, updated plugin list in index.md (now 25 plugins). ifblock variable capture:ifblocks with regex conditions (~,~*) now properly expose capture groups as variables with correct boundary inheritance.
- ReDoS plugin now covers
location,if,rewrite,server_name, andmapdirectives. - Documentation updated for
add_header_redefinitionwith nginx 1.29.3+ solution. - Expanded regex_redos.md with detailed vulnerability patterns and examples.
- Code quality improvements: explicit
autoescape=Falsefor Jinja2 (plain text output), noqa comments for intentional test patterns and random module usage. - Legacy code cleanup in regexp.py: replaced alternation with character class, merged string concatenation, improved comments.
- Rich console formatter: New beautiful terminal output with colors, panels, and progress indicators using the Rich library. Automatically enabled in TTY when
richis installed. Install withpip install gixy-ng[rich]. - Line numbers in output: Issues now display the line number and file path where they were detected.
- Security score: The rich console formatter shows a security score (0-100) based on issue severity.
- Directives now track
lineandfileattributes for better error reporting. - New CLI tests for plugin options, boolean flag parsing, and module invocation.
- Formatter tests for the new rich console output.
- Parser refactored:
parse()method is now an alias forparse_string()for backward compatibility. - Parser internals cleaned up with new
_build_tree_from_parsed()method that handles both file and dump parsing uniformly. - Line number propagation through the parser pipeline for accurate issue location reporting.
- README.md now lists all available plugins including
default_server_flag,hash_without_default, andreturn_bypasses_allow_deny. - Rich console formatter tests now skip gracefully when
richlibrary is not installed. - CLI default formatter selection now correctly checks if
rich_consoleis actually registered (all rich submodules available), preventing argparse failures with partial rich installations. - Lua blocks (
content_by_lua_block, etc.) now include line number information for accurate issue location reporting. - Fixed
TypeError: argument of type 'NoneType' is not iterableinadd_header_multilineplugin when header value is None (#35).
- Added optional
rich>=13.0.0dependency for enhanced terminal output.
See GitHub Releases for previous changelog entries.