"""Tests for the PayloadGenerator module."""
import urllib.parse
import pytest
from intelliscan.modules.payload_gen import PayloadGenerator
def test_generate_includes_original():
gen = PayloadGenerator()
variants = gen.generate("' OR 1=1-- ", "sqli")
assert "' OR 1=1-- " in variants
def test_url_encoding_applied():
gen = PayloadGenerator()
variants = gen.generate("' OR 1=1-- ", "sqli")
encoded = urllib.parse.quote("' OR 1=1-- ", safe="")
assert encoded in variants
def test_double_url_encoding_applied():
gen = PayloadGenerator()
variants = gen.generate("' OR 1=1-- ", "sqli")
once = urllib.parse.quote("' OR 1=1-- ", safe="")
twice = urllib.parse.quote(once, safe="")
assert twice in variants
def test_comment_insertion_only_for_sqli():
gen = PayloadGenerator()
variants_sqli = gen.generate("' OR 1=1-- ", "sqli")
variants_xss = gen.generate("", "xss")
assert any("/**/" in v for v in variants_sqli)
assert not any("/**/" in v for v in variants_xss)
def test_html_entity_encode_only_for_xss():
"""HTML entity encoding applies to XSS payloads, not SQLi or LFI."""
gen = PayloadGenerator()
xss_variants = gen.generate("", "xss")
sqli_variants = gen.generate("' OR 1=1-- ", "sqli")
assert any("<" in v for v in xss_variants)
assert not any("<" in v for v in sqli_variants)
def test_whitespace_variation_produces_tab_and_comment():
gen = PayloadGenerator()
variants = gen.generate("SELECT * FROM users", "sqli")
assert any("\t" in v for v in variants)
assert any("/**/" in v for v in variants)
def test_lfi_skips_case_mutation():
"""Unix paths are case-sensitive; case mutation should not apply to LFI."""
gen = PayloadGenerator()
variants = gen.generate("/etc/passwd", "lfi")
case_mutated = [v for v in variants if v != v.lower() and v != v.upper()]
for v in case_mutated:
assert "%" in v
def test_generate_all_deduplicates():
gen = PayloadGenerator()
base = ["' OR 1=1-- ", "' OR 1=1-- "]
out = gen.generate_all(base, "sqli")
assert len(out) == len(set(out))
def test_generate_increases_payload_count():
gen = PayloadGenerator()
base = ["' OR 1=1-- "]
out = gen.generate_all(base, "sqli")
assert len(out) > len(base)
def test_record_feedback_and_technique_stats():
gen = PayloadGenerator()
for _ in range(10):
gen.record_feedback("url_encode", detected=True)
stats = gen.technique_stats()
assert stats["url_encode"]["block_rate"] == pytest.approx(1.0)
assert stats["url_encode"]["total"] == 10
def test_adaptive_skips_high_block_rate_technique():
"""Technique with >80% block rate and >=5 samples is excluded."""
gen = PayloadGenerator()
for _ in range(6):
gen.record_feedback("url_encode", detected=True)
skipped = gen._skipped_techniques()
assert "url_encode" in skipped