Skip to content

Commit 303f62b

Browse files
committed
fix: apply comments from code review
Signed-off-by: Felipe Zipitria <felipe.zipitria@owasp.org>
1 parent 8c2ba37 commit 303f62b

3 files changed

Lines changed: 146 additions & 118 deletions

File tree

tests/test_actions.py

Lines changed: 123 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@
1111
- deprecatevar: Grammar expects ID, docs show complex syntax (var=time/lifetime)
1212
- setuid/setsid/setrsc: Grammar expects STRING, may cause quoting issues
1313
14-
Reference: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual-(v2.x)-Actions
14+
Reference: https://github.com/owasp-modsecurity/ModSecurity/wiki/Reference-Manual-(v2.x)-Actions
1515
"""
16+
import pytest
1617
from secrules_parsing import parser
1718

1819

@@ -591,6 +592,7 @@ def test_action_sanitise_matched() -> None:
591592
assert matches == 1
592593

593594

595+
@pytest.mark.xfail(reason="Grammar limitation: sanitiseMatchedBytes only accepts INT, docs show ranges (1/4) or standalone")
594596
def test_action_sanitise_matched_bytes() -> None:
595597
"""
596598
Test sanitiseMatchedBytes action
@@ -601,16 +603,16 @@ def test_action_sanitise_matched_bytes() -> None:
601603
SecRule ARGS "@rx secret" "id:1,sanitiseMatchedBytes:10,deny"
602604
"""
603605
parsed_rule = parser.process_from_str(rule_text)
604-
if isinstance(parsed_rule, dict):
605-
# Grammar doesn't support this correctly, skip
606-
assert True, "Grammar limitation - sanitiseMatchedBytes needs fixing"
607-
else:
608-
matches = 0
609-
for rule in parsed_rule.rules:
610-
for action in rule.actions:
611-
if hasattr(action, 'sanitizematchedbytes') and action.sanitizematchedbytes == 10:
612-
matches += 1
613-
assert matches == 1
606+
# Assert parse success - will fail if grammar doesn't support this
607+
assert not isinstance(parsed_rule, dict), \
608+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
609+
610+
matches = 0
611+
for rule in parsed_rule.rules:
612+
for action in rule.actions:
613+
if hasattr(action, 'sanitizematchedbytes') and action.sanitizematchedbytes == 10:
614+
matches += 1
615+
assert matches == 1
614616

615617

616618
def test_action_sanitise_arg() -> None:
@@ -627,6 +629,7 @@ def test_action_sanitise_arg() -> None:
627629
assert matches == 1
628630

629631

632+
@pytest.mark.xfail(reason="Grammar bug: sanitiseRequestHeader expects STRING but docs show unquoted")
630633
def test_action_sanitise_request_header() -> None:
631634
"""
632635
Test sanitiseRequestHeader action
@@ -637,18 +640,19 @@ def test_action_sanitise_request_header() -> None:
637640
SecRule ARGS "@rx attack" "id:1,sanitiseRequestHeader:\\\"Authorization\\\",deny"
638641
"""
639642
parsed_rule = parser.process_from_str(rule_text)
640-
if isinstance(parsed_rule, dict):
641-
# Grammar bug - mark as known issue
642-
assert True, "Grammar issue with sanitiseRequestHeader - needs STRING quoting fix"
643-
else:
644-
matches = 0
645-
for rule in parsed_rule.rules:
646-
for action in rule.actions:
647-
if hasattr(action, 'sanitizerequestheader'):
648-
matches += 1
649-
assert matches == 1
643+
# Assert parse success - will fail due to grammar bug
644+
assert not isinstance(parsed_rule, dict), \
645+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
646+
647+
matches = 0
648+
for rule in parsed_rule.rules:
649+
for action in rule.actions:
650+
if hasattr(action, 'sanitizerequestheader'):
651+
matches += 1
652+
assert matches == 1
650653

651654

655+
@pytest.mark.xfail(reason="Grammar bug: sanitiseResponseHeader expects STRING but docs show unquoted")
652656
def test_action_sanitise_response_header() -> None:
653657
"""
654658
Test sanitiseResponseHeader action
@@ -659,16 +663,16 @@ def test_action_sanitise_response_header() -> None:
659663
SecRule ARGS "@rx attack" "id:1,sanitiseResponseHeader:\\\"Set-Cookie\\\",deny"
660664
"""
661665
parsed_rule = parser.process_from_str(rule_text)
662-
if isinstance(parsed_rule, dict):
663-
# Grammar bug - mark as known issue
664-
assert True, "Grammar issue with sanitiseResponseHeader - needs STRING quoting fix"
665-
else:
666-
matches = 0
667-
for rule in parsed_rule.rules:
668-
for action in rule.actions:
669-
if hasattr(action, 'sanitizeresponseheader'):
670-
matches += 1
671-
assert matches == 1
666+
# Assert parse success - will fail due to grammar bug
667+
assert not isinstance(parsed_rule, dict), \
668+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
669+
670+
matches = 0
671+
for rule in parsed_rule.rules:
672+
for action in rule.actions:
673+
if hasattr(action, 'sanitizeresponseheader'):
674+
matches += 1
675+
assert matches == 1
672676

673677

674678
# Response Actions
@@ -688,6 +692,7 @@ def test_action_status() -> None:
688692
assert matches == 1
689693

690694

695+
@pytest.mark.xfail(reason="Grammar bug: redirect action parsing issue with escaped quotes")
691696
def test_action_redirect() -> None:
692697
"""
693698
Test redirect action
@@ -697,17 +702,19 @@ def test_action_redirect() -> None:
697702
SecRule ARGS "@rx attack" "id:1,redirect:\\\"https://example.com/blocked\\\",deny"
698703
"""
699704
parsed_rule = parser.process_from_str(rule_text)
700-
if isinstance(parsed_rule, dict):
701-
assert True, "Grammar may need STRING quoting adjustment for redirect"
702-
else:
703-
matches = 0
704-
for rule in parsed_rule.rules:
705-
for action in rule.actions:
706-
if hasattr(action, 'redirect'):
707-
matches += 1
708-
assert matches == 1
705+
# Assert parse success - will fail due to grammar bug
706+
assert not isinstance(parsed_rule, dict), \
707+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
708+
709+
matches = 0
710+
for rule in parsed_rule.rules:
711+
for action in rule.actions:
712+
if hasattr(action, 'redirect'):
713+
matches += 1
714+
assert matches == 1
709715

710716

717+
@pytest.mark.xfail(reason="Grammar bug: proxy action parsing issue with escaped quotes")
711718
def test_action_proxy() -> None:
712719
"""
713720
Test proxy action
@@ -717,20 +724,22 @@ def test_action_proxy() -> None:
717724
SecRule ARGS "@rx safe" "id:1,proxy:\\\"http://backend.example.com\\\",pass"
718725
"""
719726
parsed_rule = parser.process_from_str(rule_text)
720-
if isinstance(parsed_rule, dict):
721-
assert True, "Grammar may need STRING quoting adjustment for proxy"
722-
else:
723-
matches = 0
724-
for rule in parsed_rule.rules:
725-
for action in rule.actions:
726-
if hasattr(action, 'proxy'):
727-
matches += 1
728-
assert matches == 1
727+
# Assert parse success - will fail due to grammar bug
728+
assert not isinstance(parsed_rule, dict), \
729+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
730+
731+
matches = 0
732+
for rule in parsed_rule.rules:
733+
for action in rule.actions:
734+
if hasattr(action, 'proxy'):
735+
matches += 1
736+
assert matches == 1
729737

730738

731739
# Execution Actions
732740

733741

742+
@pytest.mark.xfail(reason="Grammar bug: exec expects STRING (quoted), docs show unquoted paths")
734743
def test_action_exec() -> None:
735744
"""
736745
Test exec action
@@ -741,15 +750,16 @@ def test_action_exec() -> None:
741750
SecRule ARGS "@rx attack" "id:1,exec:\\\"/usr/local/bin/alert.sh\\\",deny"
742751
"""
743752
parsed_rule = parser.process_from_str(rule_text)
744-
if isinstance(parsed_rule, dict):
745-
assert True, "Grammar bug - exec expects STRING but should accept unquoted paths per ModSecurity docs"
746-
else:
747-
matches = 0
748-
for rule in parsed_rule.rules:
749-
for action in rule.actions:
750-
if hasattr(action, 'exec'):
751-
matches += 1
752-
assert matches == 1
753+
# Assert parse success - will fail due to grammar bug
754+
assert not isinstance(parsed_rule, dict), \
755+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
756+
757+
matches = 0
758+
for rule in parsed_rule.rules:
759+
for action in rule.actions:
760+
if hasattr(action, 'exec'):
761+
matches += 1
762+
assert matches == 1
753763

754764

755765
# Special Actions
@@ -797,6 +807,7 @@ def test_action_append() -> None:
797807
assert matches == 1
798808

799809

810+
@pytest.mark.xfail(reason="Grammar bug: prepend action parsing issue with escaped quotes")
800811
def test_action_prepend() -> None:
801812
"""
802813
Test prepend action
@@ -807,17 +818,19 @@ def test_action_prepend() -> None:
807818
SecRule ARGS "@rx attack" "id:1,prepend:\\\"<!-- Blocked -->\\\",deny"
808819
"""
809820
parsed_rule = parser.process_from_str(rule_text)
810-
if isinstance(parsed_rule, dict):
811-
assert True, "Grammar may need adjustment for prepend STRING handling"
812-
else:
813-
matches = 0
814-
for rule in parsed_rule.rules:
815-
for action in rule.actions:
816-
if hasattr(action, 'prepend'):
817-
matches += 1
818-
assert matches == 1
821+
# Assert parse success - will fail due to grammar bug
822+
assert not isinstance(parsed_rule, dict), \
823+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
824+
825+
matches = 0
826+
for rule in parsed_rule.rules:
827+
for action in rule.actions:
828+
if hasattr(action, 'prepend'):
829+
matches += 1
830+
assert matches == 1
819831

820832

833+
@pytest.mark.xfail(reason="Grammar bug: setuid action parsing issue with escaped quotes")
821834
def test_action_setuid() -> None:
822835
"""
823836
Test setuid action
@@ -828,17 +841,19 @@ def test_action_setuid() -> None:
828841
SecRule ARGS "@rx attack" "id:1,setuid:\\\"user123\\\",deny"
829842
"""
830843
parsed_rule = parser.process_from_str(rule_text)
831-
if isinstance(parsed_rule, dict):
832-
assert True, "Grammar may need STRING quoting adjustment for setuid"
833-
else:
834-
matches = 0
835-
for rule in parsed_rule.rules:
836-
for action in rule.actions:
837-
if hasattr(action, 'setuid'):
838-
matches += 1
839-
assert matches == 1
844+
# Assert parse success - will fail due to grammar bug
845+
assert not isinstance(parsed_rule, dict), \
846+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
847+
848+
matches = 0
849+
for rule in parsed_rule.rules:
850+
for action in rule.actions:
851+
if hasattr(action, 'setuid'):
852+
matches += 1
853+
assert matches == 1
840854

841855

856+
@pytest.mark.xfail(reason="Grammar bug: setsid action parsing issue with escaped quotes")
842857
def test_action_setsid() -> None:
843858
"""
844859
Test setsid action
@@ -849,17 +864,19 @@ def test_action_setsid() -> None:
849864
SecRule ARGS "@rx attack" "id:1,setsid:\\\"session456\\\",deny"
850865
"""
851866
parsed_rule = parser.process_from_str(rule_text)
852-
if isinstance(parsed_rule, dict):
853-
assert True, "Grammar may need STRING quoting adjustment for setsid"
854-
else:
855-
matches = 0
856-
for rule in parsed_rule.rules:
857-
for action in rule.actions:
858-
if hasattr(action, 'setsid'):
859-
matches += 1
860-
assert matches == 1
867+
# Assert parse success - will fail due to grammar bug
868+
assert not isinstance(parsed_rule, dict), \
869+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
870+
871+
matches = 0
872+
for rule in parsed_rule.rules:
873+
for action in rule.actions:
874+
if hasattr(action, 'setsid'):
875+
matches += 1
876+
assert matches == 1
861877

862878

879+
@pytest.mark.xfail(reason="Grammar bug: setrsc action parsing issue with escaped quotes")
863880
def test_action_setrsc() -> None:
864881
"""
865882
Test setrsc action
@@ -869,17 +886,19 @@ def test_action_setrsc() -> None:
869886
SecRule ARGS "@rx attack" "id:1,setrsc:\\\"resource789\\\",deny"
870887
"""
871888
parsed_rule = parser.process_from_str(rule_text)
872-
if isinstance(parsed_rule, dict):
873-
assert True, "Grammar may need STRING quoting adjustment for setrsc"
874-
else:
875-
matches = 0
876-
for rule in parsed_rule.rules:
877-
for action in rule.actions:
878-
if hasattr(action, 'setrsc'):
879-
matches += 1
880-
assert matches == 1
889+
# Assert parse success - will fail due to grammar bug
890+
assert not isinstance(parsed_rule, dict), \
891+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
892+
893+
matches = 0
894+
for rule in parsed_rule.rules:
895+
for action in rule.actions:
896+
if hasattr(action, 'setrsc'):
897+
matches += 1
898+
assert matches == 1
881899

882900

901+
@pytest.mark.xfail(reason="Grammar bug: xmlns action parsing issue with escaped quotes")
883902
def test_action_xmlns() -> None:
884903
"""
885904
Test xmlns action
@@ -890,15 +909,16 @@ def test_action_xmlns() -> None:
890909
SecRule ARGS "@rx attack" "id:1,xmlns:\\\"http://example.com/ns\\\",deny"
891910
"""
892911
parsed_rule = parser.process_from_str(rule_text)
893-
if isinstance(parsed_rule, dict):
894-
assert True, "Grammar may need adjustment for xmlns - should support namespace=URI syntax"
895-
else:
896-
matches = 0
897-
for rule in parsed_rule.rules:
898-
for action in rule.actions:
899-
if hasattr(action, 'xmlns'):
900-
matches += 1
901-
assert matches == 1
912+
# Assert parse success - will fail due to grammar bug
913+
assert not isinstance(parsed_rule, dict), \
914+
f"Parse failed: {parsed_rule.get('message', 'Unknown error')}"
915+
916+
matches = 0
917+
for rule in parsed_rule.rules:
918+
for action in rule.actions:
919+
if hasattr(action, 'xmlns'):
920+
matches += 1
921+
assert matches == 1
902922

903923

904924
# Transient (ctl:) Actions

tests/test_conftest_examples.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
assert_parse_success,
2020
get_rules_by_type,
2121
find_action_by_attribute,
22-
count_actions_by_attribute,
2322
has_transformation,
2423
)
2524

0 commit comments

Comments
 (0)