Skip to content

Commit 52529ee

Browse files
committed
Enhance add_header_redefinition plugin to support case-insensitive header allowlist; update documentation with new CLI options #34
1 parent 302fbeb commit 52529ee

File tree

10 files changed

+131
-6
lines changed

10 files changed

+131
-6
lines changed

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,28 @@ Total issues:
114114

115115
Or something else, you can find all other `gixy` arguments with the help command: `gixy --help`
116116

117+
### Plugin options
118+
119+
Some plugins expose options which you can set via CLI flags or config file. CLI flags follow the pattern `--<PluginName>-<option>` with dashes, while config file uses `[PluginName]` sections with dashed keys.
120+
121+
- `origins`:
122+
- `--origins-domains domains`: Comma-separated list of trusted registrable domains. Use `*` to disable third‑party checks. Example: `--origins-domains example.com,foo.bar`. Default: `*`.
123+
- `--origins-https-only true|false`: When true, only the `https` scheme is considered valid for `Origin`/`Referer`. Default: `false`.
124+
- `--origins-lower-hostname true|false`: Normalize hostnames to lowercase before validation. Default: `true`.
125+
126+
- `add_header_redefinition`:
127+
- `--add-header-redefinition-headers headers`: Comma-separated allowlist of header names (case-insensitive). When set, only dropped headers from this list will be reported; when unset, all dropped headers are reported. Example: `--add-header-redefinition-headers x-frame-options,content-security-policy`. Default: unset (report all).
128+
129+
Examples (config file):
130+
```
131+
[origins]
132+
domains = example.com, example.org
133+
https-only = true
134+
135+
[add_header_redefinition]
136+
headers = x-frame-options, content-security-policy
137+
```
138+
117139
You can also make `gixy` use pipes (stdin), like so:
118140

119141
```bash

docs/en/plugins/addheaderredefinition.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,13 @@ There are several ways to solve this problem:
6363
- use [ngx_headers_more](https://nginx-extras.getpagespeed.com/modules/headers-more/) module.
6464

6565
--8<-- "en/snippets/nginx-extras-cta.md"
66+
67+
### CLI and config options
68+
69+
- `--add-header-redefinition-headers headers` (Default: unset): Comma-separated, case-insensitive allowlist of headers to report when dropped. When unset, all dropped parent headers are reported. Example: `--add-header-redefinition-headers x-frame-options,content-security-policy`.
70+
71+
Config file example:
72+
```
73+
[add_header_redefinition]
74+
headers = x-frame-options, content-security-policy
75+
```

docs/en/plugins/origins.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,19 @@ The most common errors with this configuration are:
1010
> Notice: by default, Gixy doesn't check regexes for third-party origins matching.
1111
> You can pass a list of trusted domains by using the option `--origins-domains example.com,foo.bar`. When enabled, Gixy recognizes origins by registrable domain (via Public Suffix List) and will flag regexes that allow off-domain values.
1212
13+
### CLI and config options
14+
15+
- `--origins-domains domains` (Default: `*`): Comma-separated list of trusted registrable domains. Use `*` to disable third‑party checks. Example: `--origins-domains example.com,foo.bar`.
16+
- `--origins-https-only true|false` (Default: `false`): When true, only the `https` scheme is considered valid for `Origin`/`Referer`.
17+
- `--origins-lower-hostname true|false` (Default: `true`): Normalize hostnames to lowercase before validation.
18+
19+
Config file example:
20+
```
21+
[origins]
22+
domains = example.com, example.org
23+
https-only = true
24+
```
25+
1326
## How can I find it?
1427
"Eazy"-breezy:
1528
- you have to find all the `if` directives that are in charge of `$http_origin` or `$http_referer` check;

docs/ru/plugins/addheaderredefinition.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,13 @@ new-headers
6363
- использовать модуль [ngx_headers_more](https://nginx-extras.getpagespeed.com/modules/headers-more/).
6464

6565
Каждый из способов имеет свои преимущества и недостатки, какой предпочесть зависит от ваших потребностей.
66+
67+
### Опции CLI и конфигурации
68+
69+
- `--add-header-redefinition-headers headers` (По умолчанию: не задано): Список заголовков (без учета регистра) через запятую, по которым будет вестись отчет при их «сбросе». Если опция не задана, будет отчет по всем сброшенным заголовкам. Пример: `--add-header-redefinition-headers x-frame-options,content-security-policy`.
70+
71+
Пример в конфиге:
72+
```
73+
[add_header_redefinition]
74+
headers = x-frame-options, content-security-policy
75+
```

docs/ru/plugins/origins.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,20 @@
88
- разрешение не доверенных third-party доменов.
99

1010
> По умолчанию Gixy не проверяет регулярные выражения на предмет матчинга third-party доменов, так как не знает кому можно верить.
11-
Передать список доверенных доменом можно при помощи опции `--origins-domains example.com,foo.bar`
11+
Список доверенных доменов можно передать с помощью опции `--origins-domains example.com,foo.bar`. При включении проверка выполняется на уровне регистрируемого домена (по Public Suffix List).
12+
13+
### Опции CLI и конфигурации
14+
15+
- `--origins-domains domains` (По умолчанию: `*`): Список доверенных доменов через запятую. `*` — отключить проверку third‑party доменов. Пример: `--origins-domains example.com,foo.bar`.
16+
- `--origins-https-only true|false` (По умолчанию: `false`): Если `true`, валиден только протокол `https` в `Origin`/`Referer`.
17+
- `--origins-lower-hostname true|false` (По умолчанию: `true`): Приводить имена хостов к нижнему регистру перед проверкой.
18+
19+
Пример в конфиге:
20+
```
21+
[origins]
22+
domains = example.com, example.org
23+
https-only = true
24+
```
1225

1326
## Как самостоятельно обнаружить?
1427
Все довольно "просто":

docs/zh/plugins/addheaderredefinition.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,13 @@ new-headers
6363
- 使用 [ngx_headers_more](https://nginx-extras.getpagespeed.com/modules/headers-more/) 模块。
6464

6565
--8<-- "zh/snippets/nginx-extras-cta.md"
66+
67+
### 命令行与配置选项
68+
69+
- `--add-header-redefinition-headers headers`(默认:未设置):以逗号分隔的响应头白名单(不区分大小写)。设置后,仅当这些头在子级被“丢弃”时才会报告;未设置则报告所有被丢弃的头。示例:`--add-header-redefinition-headers x-frame-options,content-security-policy`
70+
71+
配置示例:
72+
```
73+
[add_header_redefinition]
74+
headers = x-frame-options, content-security-policy
75+
```

docs/zh/plugins/origins.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,19 @@
1010
> 注意:默认情况下,Gixy 不会检查正则是否允许第三方来源。
1111
> 你可以通过 `--origins-domains example.com,foo.bar` 传入可信域名列表。启用后,Gixy 会基于 Public Suffix List 以“可注册域”为单位识别来源,并标记那些放行域外值的正则。
1212
13+
### 命令行与配置选项
14+
15+
- `--origins-domains domains`(默认:`*`):以逗号分隔的可信可注册域名列表。使用 `*` 关闭第三方检查。示例:`--origins-domains example.com,foo.bar`
16+
- `--origins-https-only true|false`(默认:`false`):为 `true` 时,仅允许 `https` 协议的 `Origin`/`Referer`
17+
- `--origins-lower-hostname true|false`(默认:`true`):校验前将主机名转换为小写。
18+
19+
配置示例:
20+
```
21+
[origins]
22+
domains = example.com, example.org
23+
https-only = true
24+
```
25+
1326
## 如何发现?
1427
"简单粗暴" 的办法:
1528
- 找到所有对 `$http_origin``$http_referer` 进行校验的 `if` 指令;

gixy/cli/main.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,31 @@ def _init_logger(debug=False):
2727
LOG.debug("logging initialized")
2828

2929

30-
def _create_plugin_help(option):
30+
def _create_plugin_help(plugin_cls, opt_key, option):
31+
"""Build help text for a plugin option, including usage hints and default.
32+
33+
Attempts to use plugin-provided descriptions via optional
34+
`options_help` mapping on the plugin class.
35+
"""
3136
if isinstance(option, (tuple, list, set)):
3237
default = ",".join(list(option))
38+
usage_hint = "Comma-separated list."
3339
else:
3440
default = str(option)
41+
usage_hint = None
42+
43+
if isinstance(option, bool):
44+
usage_hint = "Boolean (true/false)."
45+
46+
# Plugin-specific description if provided
47+
base_desc = ""
48+
if hasattr(plugin_cls, "options_help"):
49+
options_help = plugin_cls.options_help
50+
if isinstance(options_help, dict):
51+
base_desc = options_help.get(opt_key, "")
3552

36-
return "Default: {0}".format(default)
53+
parts = [p for p in [base_desc, usage_hint, "Default: {0}".format(default)] if p]
54+
return " ".join(parts)
3755

3856

3957
def _get_cli_parser():
@@ -126,7 +144,7 @@ def _get_cli_parser():
126144
metavar=opt_key,
127145
dest=dst_name,
128146
type=opt_type,
129-
help=_create_plugin_help(opt_val),
147+
help=_create_plugin_help(plugin_cls, opt_key, opt_val),
130148
)
131149

132150
return parser

gixy/plugins/add_header_redefinition.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,22 @@ class add_header_redefinition(Plugin):
1818
'See documentation: https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header')
1919
help_url = 'https://github.com/dvershinin/gixy/blob/master/docs/en/plugins/addheaderredefinition.md'
2020
directives = ['server', 'location', 'if']
21+
# headers: optional set/list/tuple of header names to scope reporting to
22+
# When empty, all dropped headers are reported. Case-insensitive; values are
23+
# normalized to lowercase and compared to lowercase header names from config.
2124
options = {'headers': set()}
25+
options_help = {
26+
'headers': 'Only report dropped headers from this allowlist. Case-insensitive. Comma-separated list, e.g. "x-frame-options,content-security-policy".'
27+
}
2228

2329
def __init__(self, config):
2430
super(add_header_redefinition, self).__init__(config)
25-
self.interesting_headers = self.config.get('headers')
31+
raw_headers = self.config.get('headers')
32+
# Normalize configured headers to lowercase set for case-insensitive matching
33+
if isinstance(raw_headers, (list, tuple, set)):
34+
self.interesting_headers = set(h.lower().strip() for h in raw_headers if h and isinstance(h, str))
35+
else:
36+
self.interesting_headers = set()
2637
# Define secure headers that should escalate severity
2738
self.secure_headers = [
2839
'x-frame-options',
@@ -48,7 +59,7 @@ def audit(self, directive):
4859

4960
diff = parent_headers - actual_headers
5061

51-
if len(self.interesting_headers):
62+
if self.interesting_headers:
5263
diff = diff & self.interesting_headers
5364

5465
if len(diff):

gixy/plugins/origins.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ class origins(Plugin):
5353
'https_only': False,
5454
'lower_hostname': True
5555
}
56+
options_help = {
57+
'domains': 'Comma-separated list of trusted registrable domains. Use * to disable third-party checks. Example: "example.com,foo.bar".',
58+
'https_only': 'Boolean. Only allow https scheme in origins/referers when true.',
59+
'lower_hostname': 'Boolean. Normalize hostnames to lowercase prior to validation.'
60+
}
5661

5762
def __init__(self, config):
5863
super(origins, self).__init__(config)

0 commit comments

Comments
 (0)