mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-02 07:11:49 +00:00
fix(tirith): suppress .app lookalike_tld false positives in warn verdicts
Tirith flags .app domains with a lookalike_tld finding because the TLD "can be confused with file extensions". This is a false positive for legitimate production APIs (e.g. api.example.app, lark.app). Add _is_app_tld_finding() and a post-parse suppression block in check_command_security(): if the only finding(s) on a warn verdict are lookalike_tld entries for .app, downgrade the action to allow. Mixed findings (e.g. .app + shortened_url) and block verdicts are unaffected. Non-.app lookalike_tld findings (.zip, .exe, etc.) are preserved. Add 15 regression tests covering: .app-only suppression, mixed-finding preservation, non-.app TLD preservation, block-verdict invariance, and the helper's field-name and case-insensitivity behaviour. Closes #24461
This commit is contained in:
parent
1634397ddb
commit
fae0fa4325
2 changed files with 149 additions and 0 deletions
|
|
@ -771,4 +771,33 @@ def check_command_security(command: str) -> dict:
|
|||
elif action == "warn":
|
||||
summary = "security warning detected (details unavailable)"
|
||||
|
||||
# Suppress warn verdicts that consist solely of a lookalike_tld finding for
|
||||
# the .app TLD. .app is a legitimate gTLD used by many production services
|
||||
# and the "can be confused with file extensions" heuristic generates false
|
||||
# positives for normal API calls. Any other finding (including other
|
||||
# lookalike_tld entries for non-.app TLDs) preserves the warn action.
|
||||
if action == "warn" and findings:
|
||||
non_suppressible = [f for f in findings if not _is_app_tld_finding(f)]
|
||||
if not non_suppressible:
|
||||
action = "allow"
|
||||
findings = []
|
||||
summary = ""
|
||||
|
||||
return {"action": action, "findings": findings, "summary": summary}
|
||||
|
||||
|
||||
def _is_app_tld_finding(finding: dict) -> bool:
|
||||
"""Return True if this finding is a lookalike_tld warning for the .app TLD only.
|
||||
|
||||
Checks the rule_id and inspects common value/detail field names that
|
||||
Tirith may use to carry the TLD string.
|
||||
"""
|
||||
if not isinstance(finding, dict):
|
||||
return False
|
||||
if finding.get("rule_id") != "lookalike_tld":
|
||||
return False
|
||||
for field in ("value", "tld", "detail", "description", "message"):
|
||||
val = finding.get(field)
|
||||
if val is not None and ".app" in str(val).lower():
|
||||
return True
|
||||
return False
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue