mirror of
https://github.com/usestrix/strix.git
synced 2026-10-16 04:28:23 +00:00
fix(coverage): count a joined/CamelCase class name as coverage
A row recorded as "DirectoryTraversal" or "XSLeaks" normalizes to one token, which whole-word matching missed, so finish_scan/coverage.json could report tested work as a gap. _entry_is_about now also matches a phrasing's words joined into one token as a fallback - still a whole-token check, never a substring. The branch is additive: it can only turn a gap into a cover, never the reverse, so it introduces no false gap.
This commit is contained in:
parent
b4018019fb
commit
2a76196f78
2 changed files with 22 additions and 2 deletions
|
|
@ -333,10 +333,19 @@ def _entry_is_about(entry: dict[str, Any], phrasings: list[list[str]]) -> bool:
|
|||
|
||||
A phrasing matches when every one of its words appears as a **word** in the
|
||||
row (``risk_area`` + ``surface``) — not as a substring, so "brute force"
|
||||
never counts as ``rce`` coverage and "corridor" never as ``idor``.
|
||||
never counts as ``rce`` coverage and "corridor" never as ``idor``. As a
|
||||
fallback it also matches the phrasing's words joined into one token, so a
|
||||
row that recorded a joined / CamelCase name the normalizer kept whole
|
||||
("DirectoryTraversal" -> "directorytraversal", "XSLeaks" -> "xsleaks")
|
||||
still counts — still a whole-token check, never a substring.
|
||||
"""
|
||||
words = set(_normalized(f"{entry.get('risk_area', '')} {entry.get('surface', '')}").split())
|
||||
return any(all(_term_in_words(term, words) for term in terms) for terms in phrasings)
|
||||
for terms in phrasings:
|
||||
if all(_term_in_words(term, words) for term in terms):
|
||||
return True
|
||||
if len(terms) > 1 and _term_in_words("".join(terms), words):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def _entry_authored_by(entry: dict[str, Any], owner_ids: set[str]) -> bool:
|
||||
|
|
|
|||
|
|
@ -104,6 +104,17 @@ def test_substring_match_does_not_hide_a_gap() -> None:
|
|||
assert skill.replace("_", " ") in classes, (skill, surface, risk, classes)
|
||||
|
||||
|
||||
def test_joined_camelcase_name_counts_as_coverage() -> None:
|
||||
"""A row recorded as a joined/CamelCase class name ('DirectoryTraversal')
|
||||
still counts, via the joined-token fallback — no substring matching."""
|
||||
doc = _document(
|
||||
entries=[_entry(risk_area="DirectoryTraversal reviewed", surface="/download")],
|
||||
agent_graph=_graph(metadata={"agent-1": {"skills": ["path_traversal_lfi_rfi"]}}),
|
||||
)
|
||||
|
||||
assert not [g for g in doc["gaps"] if g["kind"] == "unrecorded_risk_class"]
|
||||
|
||||
|
||||
def test_simple_plural_still_counts_as_coverage() -> None:
|
||||
"""Whole-word matching tolerates a trivial plural, so 'passwords' /
|
||||
'credentials' still cover weak_password_detection."""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue