Skip to content

Commit 58025af

Browse files
committed
Enhance hash_without_default plugin to handle map and geo blocks without default values #82
1 parent 395cefe commit 58025af

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

gixy/plugins/hash_without_default.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import gixy
22
from gixy.plugins.plugin import Plugin
3+
from gixy.directives.directive import MapDirective
4+
from gixy.directives.block import MapBlock, GeoBlock
35

46
class hash_without_default(Plugin):
57
summary = "Detect when a hash block (map, geo) is used without a default value."
@@ -12,10 +14,43 @@ def __init__(self, config):
1214
super(hash_without_default, self).__init__(config)
1315

1416
def audit(self, directive):
17+
# Collect entries from this block, following includes when present
18+
if isinstance(directive, MapBlock):
19+
entries = list(directive.gather_map_directives(directive.children))
20+
elif isinstance(directive, GeoBlock):
21+
entries = list(directive.gather_geo_directives(directive.children))
22+
else:
23+
entries = directive.children
24+
1525
found_default = False
16-
for child in directive.children:
17-
if child.src_val == 'default' and child.dest_val is not None:
26+
for child in entries:
27+
if isinstance(child, MapDirective) and child.src_val == 'default' and child.dest_val is not None:
1828
found_default = True
1929
break
20-
if not found_default:
21-
self.add_issue(directive=[directive] + directive.children, reason="Missing default value in {0} ${1}".format(directive.name, directive.variable))
30+
31+
if found_default:
32+
return
33+
34+
# Special-case: for map blocks, a single mapping entry without an explicit default
35+
# is commonly used to intentionally yield an empty string for all other cases.
36+
# This is especially useful with limit_req/limit_conn where empty keys disable limits.
37+
# In that scenario, requiring an explicit default creates noise. Therefore, only warn
38+
# for map when there are two or more mapping entries and no explicit default.
39+
if directive.name == 'map':
40+
entries_count = 0
41+
for child in entries:
42+
if not isinstance(child, MapDirective):
43+
continue
44+
if child.src_val == 'default':
45+
continue
46+
entries_count += 1
47+
48+
# Do not warn for single-entry maps without default
49+
if entries_count <= 1:
50+
return
51+
52+
# geo continues to require an explicit default regardless of entries count
53+
self.add_issue(
54+
directive=[directive] + directive.children,
55+
reason="Missing default value in {0} ${1}".format(directive.name, directive.variable),
56+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
http {
22
map $host $hostmap {
33
example.com value;
4+
example.org other;
45
}
56
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
http {
2+
map $request_method $post_binary_remote_addr {
3+
POST $binary_remote_addr;
4+
}
5+
}
6+
7+

0 commit comments

Comments
 (0)