secubox-deb/packages/secubox-cve-triage/tests/test_generate.py
CyberMind-FR fedefd36a4 feat(cve-triage): secubox-cvectl waf-rules generate + vendored Nuclei subset
CLI (dry-run by default, --apply to write) orchestrates extract + presence +
emit. Ships a small vendored Nuclei subset (MIT, with LICENSE) of appliance/KEV/
URL-extractable templates + an offline maintainer curation script. Adds
python3-yaml to Depends. --apply refuses to write when the presence inventory is
incomplete (fail-safe).

Co-Authored-By: Gerald KERMA <devel@cybermind.fr>
2026-07-18 07:46:16 +02:00

93 lines
2.9 KiB
Python

# SPDX-License-Identifier: LicenseRef-CMSD-1.0
# Copyright (c) 2026 CyberMind — Gérald Kerma <devel@cybermind.fr>
# Source-Disclosed License — All rights reserved except as expressly granted.
# See LICENCE-CMSD-1.0.md for terms.
import textwrap
from api.wafgen.generate import generate
def _write(dir_, name, body):
(dir_ / name).write_text(textwrap.dedent(body))
def test_generate_keeps_appliance_absent_kev_and_rejects_the_rest(tmp_path):
subset = tmp_path / "nuclei-subset"
subset.mkdir()
# kept: appliance (paloalto), absent, KEV, clean path
_write(subset, "keep.yaml", """
id: CVE-2024-3400
info:
severity: critical
classification: {cve-id: CVE-2024-3400, cpe: "cpe:2.3:a:paloaltonetworks:pan-os:*"}
metadata: {vendor: paloaltonetworks, product: pan-os}
tags: cve,kev,rce
http:
- method: GET
path: ["{{BaseURL}}/api/v1/totp/user-backup"]
""")
# rejected: not KEV
_write(subset, "notkev.yaml", """
id: CVE-2024-1
info:
severity: high
metadata: {vendor: f5, product: big-ip}
tags: cve,rce
http:
- method: GET
path: ["{{BaseURL}}/x"]
""")
# rejected: raw
_write(subset, "raw.yaml", """
id: CVE-2024-2
info: {severity: high, metadata: {vendor: f5, product: big-ip}}
tags: cve,kev
http:
- raw: ["POST /x HTTP/1.1"]
unsafe: true
""")
kept, rejected = generate(subset, present=set(), present_complete=True)
assert [c.cve for c in kept] == ["CVE-2024-3400"]
rej_names = {name for name, _ in rejected}
assert "notkev.yaml" in rej_names and "raw.yaml" in rej_names
def test_present_product_is_rejected_by_the_oracle(tmp_path):
subset = tmp_path / "nuclei-subset"
subset.mkdir()
_write(subset, "f5.yaml", """
id: CVE-2023-46747
info:
severity: critical
classification: {cve-id: CVE-2023-46747, cpe: "cpe:2.3:a:f5:big-ip:*"}
metadata: {vendor: f5, product: big-ip}
tags: cve,kev
http:
- method: GET
path: ["{{BaseURL}}/mgmt/tm/util/bash"]
""")
# f5 is somehow present → not generated, and recorded as a rejection reason.
kept, rejected = generate(subset, present={"f5"}, present_complete=True)
assert kept == []
assert any("present" in reason.lower() for _, reason in rejected)
def test_incomplete_inventory_generates_nothing(tmp_path):
subset = tmp_path / "nuclei-subset"
subset.mkdir()
_write(subset, "f5.yaml", """
id: CVE-2023-46747
info:
severity: critical
classification: {cve-id: CVE-2023-46747}
metadata: {vendor: f5, product: big-ip}
tags: cve,kev
http:
- method: GET
path: ["{{BaseURL}}/mgmt/tm/util/bash"]
""")
kept, _ = generate(subset, present=set(), present_complete=False)
assert kept == []