title, keywords, description
| title | keywords | description | |||||
|---|---|---|---|---|---|---|---|
| Nginx Rewrite Compatibility Migration |
|
Secure migration plugin for nginx rewrite + set |
Features
The nginx-rewrite-compatible plugin provides the common behavior of nginx rewrite + set, including path rewrites, query append or replacement, capture-group variable storage, and optional variable propagation to upstream services through request headers.
It is designed as a secure migration alternative when moving from Nginx to Higress, so users do not need to keep relying on the rewrite path affected by CVE-2026-42945.
Security Background
CVE-2026-42945 is a long-standing heap overflow issue related to the interaction between Nginx rewrite and set. The vulnerable pattern is:
- A
rewriterule uses a replacement containing?, so URI and query string are updated during one rewrite pass. - A later
setstill references capture groups such as$1or$2. - The state kept across rewrite passes becomes inconsistent, so
setreads capture-group metadata from a mismatched state and eventually triggers out-of-bounds access and heap corruption.
The Higress WASM approach does not have this problem because:
- Each request is handled in an isolated WASM request context.
- This plugin performs match, rewrite, variable extraction, and upstream propagation in one request callback instead of relying on Nginx's multi-pass rewrite state machine.
- Capture-group data lives only inside the current request and request properties, so there is no cross-pass state leakage.
Runtime Properties
Plugin execution phase: UNSPECIFIED
Plugin execution priority: 100
Configuration Fields
| Field Name | Type | Required | Default | Description |
|---|---|---|---|---|
rules |
array of object | Yes | - | Ordered rewrite rules |
rules
| Field Name | Type | Required | Default | Description |
|---|---|---|---|---|
regex |
string | Yes | - | Regular expression that matches the request path without the query string |
replacement |
string | Yes | - | New path template. Supports capture references such as $1 and $2 |
query_append |
string | No | - | Query fragment appended to the existing query string. Supports $1, $2 |
query_template |
string | No | - | Query template that replaces the existing query string. Supports $1, $2 |
set_vars |
array of object | No | - | Stores capture groups as request-scoped variables, or rewrites query/header/cookie based on variable prefixes |
pass_to_upstream |
bool | No | false |
Whether variables from the current rule should also be written into upstream request headers |
mode |
string | No | last |
Rule flow mode. Supported values: break, last |
Notes:
query_appendandquery_templateare mutually exclusive.mode: breakstops evaluation after the current matching rule.mode: lastcontinues evaluating the following rules with the rewritten path.- In
set_vars, thearg_prefix rewrites a request query parameter,http_rewrites a request header,cookie_rewrites a request cookie, and any other name is stored withproxywasm.SetProperty([]string{"nginx_rewrite_compatible","vars",name}). - For
http_, the header name is derived by removing the prefix and converting underscores to hyphens. - When
pass_to_upstream: true, variables are also written tox-higress-rewrite-var-<name>.
set_vars
| Field Name | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Variable name. arg_/http_/cookie_ mean query parameter, header, and cookie updates respectively; other names become custom properties |
capture_group |
int | Yes | Capture-group index. 0 means the whole match and 1 means the first group |
Nginx Mapping Table
1. Simple Path Rewrite
Nginx:
rewrite ^/old/(.*)$ /new/$1;
Plugin:
rules:
- regex: ^/old/(.*)$
replacement: /new/$1
2. Capture-Group Replacement
Nginx:
rewrite ^/product/([0-9]+)$ /detail/$1;
Plugin:
rules:
- regex: ^/product/([0-9]+)$
replacement: /detail/$1
3. Query String Operations
Append query:
rewrite ^/api/(.*)$ /internal?migrated=true;
rules:
- regex: ^/api/(.*)$
replacement: /internal
query_append: migrated=true
Replace query:
rewrite ^/x/(.*)/(.*)$ /y?a=$1&b=$2;
rules:
- regex: ^/x/(.*)/(.*)$
replacement: /y
query_template: a=$1&b=$2
4. Special Variable Prefixes
rules:
- regex: "^/api/(.*)/(.*)$"
replacement: "/internal"
set_vars:
- name: original_path
capture_group: 1
- name: http_x_original
capture_group: 1
- name: arg_source
capture_group: 2
- name: cookie_track_id
capture_group: 1
Semantics:
original_pathis stored as a request property and can be read later withGetProperty(["nginx_rewrite_compatible","vars","original_path"]).http_x_originalsets the request headerx-original.arg_sourcesets the query parametersource.cookie_track_idsets the cookietrack_id.
5. Variable Preservation and Propagation
Nginx:
rewrite ^/api/(.*)$ /internal?migrated=true;
set $original_endpoint $1;
Plugin:
rules:
- regex: ^/api/(.*)$
replacement: /internal
query_append: migrated=true
set_vars:
- name: original_endpoint
capture_group: 1
pass_to_upstream: true
6. Multiple Rules
Nginx:
rewrite ^/stage/(.*)$ /mid/$1;
rewrite ^/mid/(.*)$ /final/$1;
Plugin:
rules:
- regex: ^/stage/(.*)$
replacement: /mid/$1
mode: last
- regex: ^/mid/(.*)$
replacement: /final/$1
7. break / last
Nginx break:
rewrite ^/stage/(.*)$ /mid/$1 break;
rules:
- regex: ^/stage/(.*)$
replacement: /mid/$1
mode: break
Nginx last:
rewrite ^/stage/(.*)$ /mid/$1 last;
rewrite ^/mid/(.*)$ /final/$1;
rules:
- regex: ^/stage/(.*)$
replacement: /mid/$1
mode: last
- regex: ^/mid/(.*)$
replacement: /final/$1
Example
rules:
- regex: ^/api/(.*)$
replacement: /internal
query_append: migrated=true
set_vars:
- name: original_endpoint
capture_group: 1
- name: http_x_original_endpoint
capture_group: 1
- name: arg_source
capture_group: 1
- name: cookie_track_id
capture_group: 1
pass_to_upstream: true
mode: break
- regex: ^/old/(.*)$
replacement: /new/$1
- regex: ^/x/(.*)/(.*)$
replacement: /y
query_template: a=$1&b=$2
set_vars:
- name: first
capture_group: 1
- name: second
capture_group: 2