stamparm/maltrail · error

forwarded-for regex

Error message

forwarded-for regex

What it means

Statics::build compiles the forwarded-for header regex (CF-Connecting-IP|True-Client-IP|X-Forwarded-For) with regex::bytes::RegexBuilder and panics with "forwarded-for regex" if build() returns Err. Since the pattern is a hard-coded literal, failure indicates a regex-crate construction problem (e.g. a compile-size limit or unsupported configuration combination), not bad user input.

Solutions

  1. Include the underlying regex::Error in the panic message to identify the real cause
  2. Raise RegexBuilder size_limit if the error is a compiled-size overflow
  3. Check the regex crate version/feature flags for changes affecting bytes::Regex with unicode(false)
  4. If the pattern were ever dynamic, validate it with RegexBuilder::new(..).build() at config-load time

Example fix

// before
.build()
.expect("forwarded-for regex"),
// after
.build()
.unwrap_or_else(|e| panic!("forwarded-for regex failed to compile: {e}")),
Defensive patterns

Strategy: try-catch

Validate before calling

regex::bytes::RegexBuilder::new(r"\b(CF-Connecting-IP|True-Client-IP|X-Forwarded-For):\s*([0-9.]+)").case_insensitive(true).unicode(false).build().map(|_| ()).map_err(|e| format!("forwarded-for regex: {e}"))?;

Try / catch

let re = builder.build().unwrap_or_else(|e| panic!("forwarded-for regex: {e}"));

Prevention

When it happens

Trigger: Statics::build() runs and regex::bytes::RegexBuilder::new(r"\b(CF-Connecting-IP|True-Client-IP|X-Forwarded-For):\s*([0-9.]+)").case_insensitive(true).unicode(false).build() returns Err — typically size_limit exceeded or a crate-level issue.

Common situations: Running in a build where the regex size_limit was lowered globally; a regex crate regression when upgrading; unusual feature-flag combinations disabling syntax used by the pattern.

Related errors


AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13). Data as JSON: /api/errors/135a271c9efd4f54. Report an issue: GitHub.

Appendix: source

Thrown at sensor/src/settings.rs:320

            suspicious_http_request,
            suspicious_http_path,
            code_execution,
            param_value: pyre::compile(r"(\w+=)[^&=]+"),
            proxy_probe_path: pyre::compile(r"(http://[^/]+/)(.+)"),
            proxy_probe_host: pyre::compile(r"(http://)([^/(]+)"),
            // `unicode(false)` is what makes the Aho-Corasick pre-condition below EXACT rather
            // than merely usually right. `the retired Python sensor, sensor.py:804` compiles this as a BYTES pattern
            // with `re.I`, and in Python that folds ASCII only; the crate's default folds
            // Unicode, so `(?i)k` here also matched U+212A KELVIN SIGN and `\b`/`\s` were
            // Unicode classes. That accepted a header Python's `re` would not, and it would have
            // slipped past an ASCII pre-filter. ASCII on both sides now agrees with the oracle.
            forwarded_for: regex::bytes::RegexBuilder::new(
                r"\b(CF-Connecting-IP|True-Client-IP|X-Forwarded-For):\s*([0-9.]+)",
            )
            .case_insensitive(true)
            .unicode(false)
            .build()
            .expect("forwarded-for regex"),
            forwarded_for_pre_condition: ac_nocase(&["CF-Connecting-IP:", "True-Client-IP:", "X-Forwarded-For:"]),

            pre_condition: ac(SUSPICIOUS_HTTP_REQUEST_PRE_CONDITION),
            proxy_probe_pre_condition: ac(SUSPICIOUS_PROXY_PROBE_PRE_CONDITION),
            whitelist_request_paths: ac(WHITELIST_HTTP_REQUEST_PATHS),
            whitelist_direct_download: ac(WHITELIST_DIRECT_DOWNLOAD_KEYWORDS),
            whitelist_long_domain: ac(WHITELIST_LONG_DOMAIN_NAME_KEYWORDS),
            local_subdomain_lookups: ac(LOCAL_SUBDOMAIN_LOOKUPS),
            condense_on_info: ac(CONDENSE_ON_INFO_KEYWORDS),

            ignore_dns_query_suffixes: IGNORE_DNS_QUERY_SUFFIXES.iter().copied().collect(),
            suspicious_content_types: SUSPICIOUS_CONTENT_TYPES.iter().copied().collect(),
            suspicious_download_extensions: SUSPICIOUS_DIRECT_DOWNLOAD_EXTENSIONS.iter().copied().collect(),
        }
    }
}

/// `IPPROTO_LUT` lookup (protocol number -> Maltrail label).

View on GitHub (pinned to 77cfb06d76)