Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ def ctx(start: int) -> str:
tag = [PatternCategory.AGENT_SNOOPING.value]

for pattern, confidence in AS1_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand All @@ -149,7 +151,9 @@ def ctx(start: int) -> str:
)

for pattern, confidence in AS2_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand All @@ -165,7 +169,9 @@ def ctx(start: int) -> str:
)

for pattern, confidence in AS3_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,9 @@ def analyze(content: str, file_path: str, file_type: str) -> list[AnalyzerFindin

for rule_id, patterns in _RULES:
for pattern, base_confidence in patterns:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
lines = content.splitlines()
line_num = get_line_number(content, match.start())
match_line = lines[line_num - 1] if lines else content
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,9 @@ def ctx(start: int) -> str:
tag = [PatternCategory.DATA_EXFILTRATION.value]

for pattern, confidence in E1_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
adj = (
min(1.0, confidence + 0.1)
Expand Down Expand Up @@ -318,7 +320,9 @@ def ctx(start: int) -> str:
e2_patterns = E2_OTHER_PATTERNS

for pattern, confidence in e2_patterns:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand All @@ -333,7 +337,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in E3_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand All @@ -348,7 +354,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in E4_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand All @@ -364,7 +372,9 @@ def ctx(start: int) -> str:
)
# E5: cloud-storage exfiltration. Example filtering is delegated to the runner.
for pattern, confidence in E5_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def analyze(content: str, file_path: str, file_type: str) -> list[AnalyzerFindin
tag = [PatternCategory.DESERIALIZATION.value]
findings: list[AnalyzerFinding] = []
for rule_id, message, severity, regex, confidence in _COMPILED[language]:
for match in regex.finditer(content):
for match in static_runner.iter_paragraph_matches(regex, content):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,9 @@ def ctx(start: int) -> str:
tag = [PatternCategory.EXCESSIVE_AGENCY.value]

for pattern, confidence in EA1_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand All @@ -387,7 +389,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in EA2_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
context_text = ctx(match.start())
findings.append(
Expand All @@ -403,7 +407,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in EA3_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand All @@ -418,7 +424,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in EA4_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ def loc(ln: int) -> Location:
tag = [PatternCategory.PROMPT_INJECTION.value]

for pattern, confidence in DANGEROUS_ACTIONS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE | re.DOTALL):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE | re.DOTALL
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,9 @@ def ctx(start: int) -> str:
tag = [PatternCategory.MEMORY_POISONING.value]

for pattern, confidence in MP1_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand All @@ -307,7 +309,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in MP2_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
span = match.group(0)
if _is_layout_only_span(span):
continue
Expand All @@ -328,7 +332,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in MP3_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
if _is_benign_reset_state_coverage(content, match):
continue
line_num = get_line_number(content, match.start())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,9 @@ def ctx(start: int) -> str:
tag = [PatternCategory.OUTPUT_HANDLING.value]

for pattern, confidence in OH1_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
if pattern == _EXEC_OUTPUT_PATTERN and _is_javascript_regexp_literal_exec(
content, match, file_path, file_type
):
Expand Down Expand Up @@ -654,7 +656,9 @@ def ctx(start: int) -> str:
findings.extend(subprocess_findings)

for pattern, confidence in OH2_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand All @@ -669,7 +673,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in OH3_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,9 @@ def loc(ln: int) -> Location:
tag = [PatternCategory.PRIVILEGE_ESCALATION.value]

for pattern, confidence in PE1_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
context = get_context(content, match.start())
findings.append(
Expand All @@ -531,7 +533,9 @@ def loc(ln: int) -> Location:
)
)
for pattern, confidence in PE2_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
context = get_context(content, match.start())
finding_tags = list(tag)
Expand All @@ -550,7 +554,9 @@ def loc(ln: int) -> Location:
)
)
for pattern, confidence in PE3_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
if _is_bare_credential_store_noun(
content, match, file_type, fence_ranges, line_starts, line_ends
):
Expand Down Expand Up @@ -588,7 +594,9 @@ def loc(ln: int) -> Location:
# that match multiple patterns (e.g. DockerClient(base_url=".../docker.sock")).
pe4_best: dict[int, AnalyzerFinding] = {}
for pattern, confidence in PE4_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
context = get_context(content, match.start())
finding_tags = list(tag)
Expand All @@ -611,7 +619,9 @@ def loc(ln: int) -> Location:
# often matches multiple flags (e.g. --privileged + --cap-add=SYS_ADMIN).
pe5_best: dict[int, AnalyzerFinding] = {}
for pattern, confidence in PE5_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
context = get_context(content, match.start())
finding_tags = list(tag)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def _p2_pattern_matches(content: str, pattern: str) -> Iterator[re.Match[str]]:
"""Yield all structured matches or the first control signal on each line."""
compiled = re.compile(pattern, re.IGNORECASE | re.DOTALL)
if pattern not in _SINGLE_CHARACTER_P2_PATTERNS:
yield from compiled.finditer(content)
yield from static_runner.iter_paragraph_matches(compiled, content)
return

cursor = 0
Expand Down Expand Up @@ -260,7 +260,9 @@ def ctx(start: int) -> str:
tag = [PatternCategory.PROMPT_INJECTION.value]

for pattern, confidence in P1_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand Down Expand Up @@ -291,7 +293,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in P3_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand All @@ -306,7 +310,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in P4_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,9 @@ def ctx(start: int) -> str:
tag = [PatternCategory.ROGUE_AGENT.value]

for pattern, confidence in RA1_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
context = ctx(match.start())
if _is_negated_safety_constraint(content, match):
Expand All @@ -172,7 +174,9 @@ def ctx(start: int) -> str:
)
)
for pattern, confidence in RA2_PATTERNS:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
line_num = get_line_number(content, match.start())
findings.append(
AnalyzerFinding(
Expand Down
4 changes: 3 additions & 1 deletion src/skillspector/nodes/analyzers/static_patterns_ssrf.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ def add(
rule_id: str, message: str, severity: Severity, patterns: list[tuple[str, float]]
) -> None:
for pattern, confidence in patterns:
for match in re.finditer(pattern, content, re.IGNORECASE | re.MULTILINE):
for match in static_runner.iter_paragraph_matches(
pattern, content, re.IGNORECASE | re.MULTILINE
):
if rule_id == "SSRF1" and _is_defensive_reference(content, match):
continue
line_num = get_line_number(content, match.start())
Expand Down
Loading
Loading