From c204e3cbf5e6b86f59bf9478d60634a7154b304b Mon Sep 17 00:00:00 2001 From: AZ Rollin <263686995+azrollin@users.noreply.github.com> Date: Sat, 6 Jun 2026 22:59:15 -0700 Subject: [PATCH 1/2] v0.2.62: 1006 patterns, 7171 keywords, 64 categories Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 10 +- setup.py | 2 +- stats/current.json | 10 +- sunglasses/__init__.py | 2 +- sunglasses/patterns.py | 896 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 908 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 7597c7c..e57a2aa 100644 --- a/README.md +++ b/README.md @@ -139,8 +139,8 @@ result = scanner.scan_auto("any_file.ext") |--------|-------| | Average text scan | <1ms (avg 0.26ms on M3 Max, single-threaded) | | Throughput | ~3,800 scans/sec (single-threaded, M3 Max) | -| Patterns | 981 | -| Keywords | 6,946 | +| Patterns | 1006 | +| Keywords | 7,171 | | Languages | 23 | | Attack categories | 64 | | Normalization techniques | 17 | @@ -151,15 +151,15 @@ result = scanner.scan_auto("any_file.ext") | Core dependencies | Zero for text scan; optional deps for media | | Platforms | Mac, Windows, Linux — anywhere Python runs | -_All performance numbers verified against `stats/current.json` (v0.2.61, updated Jun 6, 2026). Measured on Apple M3 Max, 48GB RAM, single-threaded Python 3.11. Your hardware will differ._ +_All performance numbers verified against `stats/current.json` (v0.2.62, updated Jun 6, 2026). Measured on Apple M3 Max, 48GB RAM, single-threaded Python 3.11. Your hardware will differ._ ## 23 Languages English, Spanish, Portuguese, French, German, Italian, Dutch, Russian, Ukrainian, Polish, Czech, Turkish, Azerbaijani, Arabic, Hebrew, Persian, Chinese, Japanese, Korean, Hindi, Bengali, Indonesian, Vietnamese — plus normalization handles romanization, Unicode confusables, and 17 other obfuscation techniques. Community language contributions welcome. -## What Works Today (v0.2.61) +## What Works Today (v0.2.62) -- ✅ Text scanning: 981 patterns, 6,946 keywords, 23 languages, 64 attack categories +- ✅ Text scanning: 1006 patterns, 7,171 keywords, 23 languages, 64 attack categories - ✅ Negation handling: "do NOT run rm -rf" correctly downgrades severity - ✅ Multi-stage pipeline: normalization (17 techniques) → pattern match → decision - ✅ Image scanning: OCR + EXIF metadata + hidden text detection (requires Tesseract) diff --git a/setup.py b/setup.py index 903b2e6..bb090e4 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="sunglasses", - version="0.2.61", + version="0.2.62", description="Sunglasses for AI agents. Protection layer + neighborhood watch.", long_description=open("README.md").read(), long_description_content_type="text/markdown", diff --git a/stats/current.json b/stats/current.json index bc5e3ba..2b9ee63 100644 --- a/stats/current.json +++ b/stats/current.json @@ -1,7 +1,7 @@ { - "version": "0.2.61", - "patterns": 981, - "keywords": 6946, + "version": "0.2.62", + "patterns": 1006, + "keywords": 7171, "categories": 64, "languages": 23, "normalization_techniques": 17, @@ -16,8 +16,8 @@ "media_types": 6, "reports_published": 3, "team_size": 5, - "last_updated": "2026-06-06T00:20:00-07:00", - "last_updated_by": "boss-direct-ship-v0.2.61", + "last_updated": "2026-06-06T22:59:14-0:700", + "last_updated_by": "sunglasses-publish-sh", "_note": "THIS IS THE SINGLE SOURCE OF TRUTH. All pages, JSON-LD, meta tags, llms.txt, and sitemap must read from this file. Do NOT hardcode numbers anywhere else.", "released": "2026-06-06" } diff --git a/sunglasses/__init__.py b/sunglasses/__init__.py index 8131038..9440812 100644 --- a/sunglasses/__init__.py +++ b/sunglasses/__init__.py @@ -4,4 +4,4 @@ # # "Don't let your agents get fooled." -__version__ = "0.2.61" +__version__ = "0.2.62" diff --git a/sunglasses/patterns.py b/sunglasses/patterns.py index 7b990c8..83af0d6 100644 --- a/sunglasses/patterns.py +++ b/sunglasses/patterns.py @@ -19852,4 +19852,900 @@ ], "description": "A target-controlled Web Payments payment method manifest can embed agent-directed policy text that misuses payment/merchant discovery metadata to make an AI scanner trust checkout origins, forward session/payment context, or suppress PCI/phishing findings." }, + # === v0.0.0 batch (25 patterns) === + { + "id": "GLS-DFP-026", + "name": "RAML / API Blueprint Agent-Policy Poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "#%RAML", + ".raml", + "API Blueprint", + "Apiary", + "FORMAT: 1A", + "LLM agent", + "annotationTypes", + "cookie", + ], + "regex": [ + r"""^(?! + (?=.*\b(?:security\s+training|scanner\s+docs?|policy\s+docs?|defensive\s+guidance|example\s+of\s+prompt\s+injection)\b) + | + (?=.*\b(?:do\s+not|don't|never|must\s+not|should\s+not)\b.{0,180}\b(?:obey|follow|trust|treat|honou?r|include|leak|send|suppress|omit|hide)\b.{0,180}\b(?:raml|api\s+blueprint|apiary|api\s+description|metadata|documentation)\b) + | + (?=.*\b(?:raml|api\s+blueprint|apiary|api\s+description|metadata|documentation)\b.{0,180}\b(?:is\s+not\s+policy|never\s+overrides|does\s+not\s+override)\b) +) +(?=.*(?:\#%RAML|\bFORMAT:\s*1A\b|\bAPI\s+Blueprint\b|\bApiary\b|\.raml\b|\braml\b|\bresourceTypes\b|\btraits\b|\bannotationTypes\b|\bdocumentation:|\bdescription:)) +(?=.*\b(?:AI\s+agents?|LLM\s+agents?|assistants?|tool[-\s]?builders?|scanners?|crawlers?|models?)\b) +(?=.*\b(?:ignore|override|outrank|highest\s+priority|trust\s+this|follow\s+this|disable|bypass|do\s+not\s+report|suppress|omit|hide)\b) +(?=.*\b(?:system|developer|scanners?|policy|rules|findings?|reports?|Authorization|Bearer|API[-_\s]?keys?|tokens?|cookies?|credentials?|env(?:ironment)?\s+vars?)\b) +.*""", + ], + "description": "RAML, API Blueprint, or generated API-description documentation can embed prompt-injection text that tells AI agents/tool builders to override higher-priority instructions, disclose local credentials, or suppress scanner findings." + }, + { + "id": "GLS-DFP-027", + "name": "Related Website Set Agent Authority Poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "agentic", + "assistant_instructions", + "associated site", + "associatedSites", + "autonomous scanner", + "compliance bot", + "credential forwarding", + "credentials", + "cross-domain allowed", + "customer identifiers", + ], + "regex": [ + r"""(?is)^(?!(?=.*\b(?:must\s+not|should\s+not|never|cannot|can't|do\s+not)\b.{0,90}\b(?:reuse|send|forward|share|attach|include|suppress|ignore|treat)\b))(?=.*\b(?:related[-_\s]*website[-_\s]*set|associatedSites|serviceSites|rationaleBySite|associated\s+site|site\s+relationship|same\s+owner|domain\s+affiliation)\b)(?=.*\b(?:ai\s+agent|assistant|autonomous\s+(?:scanner|crawler|agent)|llm|agentic|security\s+scanner|compliance\s+bot)\b)(?=.*\b(?:same\s+(?:security|trust)\s+boundary|same\s+origin|verified\s+owner\s+authority|trusted\s+associated\s+site|outrank|override|higher[-\s]*priority|cross[-\s]*domain\s+(?:allowed|trust)|treat\s+[^.]{0,80}\s+as\s+(?:the\s+)?same)\b)(?=.*\b(?:reuse|share|forward|send|attach|include|cookie|bearer\s+token|session\s+context|customer\s+identifiers?|credential|suppress|do\s+not\s+report|ignore\s+(?:phishing|redirect)|credential[-\s]*forwarding)\b).*""", + ], + "description": "A target-controlled Related Website Set discovery file can add agent-directed policy text that misuses legitimate domain-relationship metadata to make an AI agent trust sibling domains, reuse credentials, or suppress cross-domain risk findings." + }, + { + "id": "GLS-DFP-028", + "name": "SCIM Service Provider Config Agent Policy Poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "/ResourceTypes", + "Group", + "SCIM_API_TOKEN", + "ServiceProviderConfig", + "audit agent", + "authenticationSchemes", + "authenticationSchemes[].description", + "authoritative provisioning policy", + ], + "regex": [ + r"""(?is)^(?!.*(?:do\s+not|never|must\s+not)\s+(?:include|send|forward|expose|paste|print|return).{0,100}(?:bearer\s+token|scim[_-]?api[_-]?token|api[_-]?key|secret|env(?:ironment)?))(?!.*(?:do\s+not|never|must\s+not)\s+(?:suppress|hide|ignore|mark).{0,80}(?:scanner|finding|warning|report|false\s+positive))(?!.*(?:do\s+not|never|must\s+not)\s+obey.{0,120}(?:ignore|overrid\w+|suppress|false\s+positive|scanner\s+rules))(?=.*(?:serviceproviderconfig|urn:ietf:params:scim|\bscim\b|authenticationSchemes|resourceTypes|\bSchemas\b|patch\s*['"]?\s*:\s*\{\s*['"]?supported|filter\s*['"]?\s*:\s*\{\s*['"]?supported))(?=.*(?:ai\s*assistants?|assistants?|agents?|audit\s+agents?|scanners?|mcp|tools?|connectors?))(?=.*(?:ignore\s+(?:previous|all|scanner)|overrid\w+|outrank|authoritative.{0,80}(?:provisioning|policy|instruction|metadata)|(?:send|forward|include|attach|paste|return|print).{0,120}(?:bearer\s+token|scim[_-]?api[_-]?token|api[_-]?key|secret|env(?:ironment)?|local[_-]?token)|mark.{0,90}false\s+positive|never\s+report|suppress.{0,80}(?:finding|warning|report)|(?:role|group|provisioning).{0,80}(?:warning|finding).{0,80}(?:false\s+positive|suppress))).*""", + ], + "description": "A poisoned SCIM `ServiceProviderConfig`, schema, or resource-type discovery document embeds agent-facing policy instructions in documentation or extension fields to override scanner rules, request identity tokens or environment secrets, or suppress findings about identity provisioning abuse." + }, + { + "id": "GLS-DFP-029", + "name": "sellers.json / schain agent policy poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "SupplyChain Object", + "schain", + "sellerType", + "seller_id", + "seller_type", + "sellers.json", + ], + "regex": [ + r"""(?isx) +^ +(?! + (?=.*\b(?:training|guide|reference|documentation|docs?)\b) + (?=.*\b(?:report|detect|flag|refuse|block)\b) +) +(?! + (?=.*\b(?:must\s+not|do\s+not|never)\b) + (?=.*\b(?:obey|treat|trust|accept|follow)\b) +) +(?=.*(?:sellers\.json|seller[_-]?id|seller[_-]?type|sellerType|SupplyChain\s+Object|\bschain\b|\basi\b|\bsid\b|\bhp\b|advertising\s+transparency|authorized\s+sellers?|seller\s+verification)) +(?=.*(?:AI\s*(?:agent|assistant|crawler|scanner)|LLM\s*(?:agent|crawler|scanner)|autonomous\s*(?:agent|scanner)|security\s*scanner|fraud\s*auditor|ad\s*(?:quality|fraud)?\s*scanner|Sunglasses)) +(?=.*(?:override|supersede|outrank|treat\s+as\s+(?:policy|authority)|ignore\s+(?:system|developer|scanner)|do\s+not\s+report|suppress|hide|mark\s+(?:as\s+)?clean|include|attach|forward|reuse)) +(?=.*(?:system|developer|instruction|finding|report|fraud\s*signal|verification|cookie|token|api\s*key|env(?:ironment)?\s*(?:var(?:iable)?s?)?|local\s*state|session)) +.*""", + ], + "description": "Detects advertising transparency metadata (`sellers.json`, SupplyChain Object / `schain`, seller-verification wrappers) that tries to make AI agents, fraud scanners, or auditors suppress findings, treat seller metadata as higher policy, or forward sensitive local state." + }, + { + "id": "GLS-DFP-030", + "name": "TDMRep rights metadata agent-policy poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "/.well-known/tdmrep.json", + "AI crawler", + "LLM agent", + "SEO agent", + "do not report", + "ignore/bypass", + "mark clean", + "privacy auditor", + "rights-reservation", + "security scanner", + "supersedes system/developer", + "suppress/hide findings", + "tdm-reservation", + "tdmrep", + ], + "regex": [ + r"""(?is)^(?!.*\b(?:do\s+not|never|must\s+not)\s+(?:obey|treat|trust|follow|accept|allow).{0,80}\b(?:tdmrep|tdm[-_\s]?reservation|rights[-_\s]?reservation|text[-\s]and[-\s]data[-\s]mining)\b)(?!.*\b(?:scanner\s+docs?|docs?|guide|article|reference|training|security\s+report|incident\s+report|vulnerability\s+report)\b.{0,120}\b(?:should|must|will)\s+(?:report|detect|flag|refuse|ignore|not\s+obey)\b)(?=.*\b(?:tdmrep|tdm[-_\s]?reservation|text[-\s]and[-\s]data[-\s]mining|text/data\s+mining|rights[-_\s]?reservation|rights\s+policy|\.well-known/tdmrep\.json)\b)(?=.*\b(?:ai\s+agents?|ai\s+crawlers?|llm\s+(?:agents?|crawlers?)|assistants?|security\s+scanners?|privacy\s+auditors?|seo\s+agents?|crawler\s+agents?)\b)(?=.*\b(?:supersed\w*|overrid\w*|ignore|bypass|obey|follow|treat\s+as\s+policy|trust\s+this|do\s+not\s+report|not\s+report|suppress|hide|mark\s+(?:clean|safe)|include|forward|send|attach)\b)(?=.*\b(?:system|developer|instructions?|policy|prompt[-\s]?injection|findings?|scanner\s+results?|authorization|bearer|api[-_\s]?key|tokens?|cookies?|env(?:ironment)?(?:\s+variables?)?|local\s+state|secrets?)\b).*$""", + ], + "description": "TDMRep or text-and-data-mining rights metadata can hide agent-directed instructions that tell AI crawlers/scanners to treat the rights file as higher authority, suppress findings, or disclose local authorization/environment details." + }, + { + "id": "GLS-DFP-031", + "name": "Traffic-advice metadata agent-policy poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "/.well-known/traffic-advice", + "AI agents", + "LLMs", + "SEO agents", + "assistants", + "auditors", + "capacity_fraction", + "cookie", + "crawl_delay", + "crawlers", + "disable", + "do not report", + ], + "regex": [ + r"""(?is)^(?!(?=.*\b(?:do not|don't|never|must not|should not)\s+(?:obey|treat|accept|use|follow|interpret)\b.{0,140}\b(?:traffic-advice|traffic_advice|crawler(?:\s|-)?policy|metadata|site policy)\b))(?=.*\b(?:traffic-advice|traffic_advice|user_agent|crawl_delay|capacity_fraction|crawler\s*(?:traffic|control|policy)|rate\s*(?:limit|window))\b)(?=.*\b(?:ai\s*agents?|assistants?|llms?|models?|scanners?|crawlers?|seo\s*agents?|auditors?)\b)(?=.*\b(?:ignore|override|supersede|outrank|bypass|disable|do\s+not\s+report|suppress|hide|omit|forward|send|include|exfiltrate)\b)(?=.*\b(?:system|developer|higher[-\s]?priority|security|scanner|findings?|report|token|api[-_\s]?key|authorization|cookie|env(?:ironment)?|secret|local\s+(?:state|files?))\b).*""", + ], + "description": "`/.well-known/traffic-advice` or crawler traffic-control JSON can blend normal crawler-rate policy with agent/scanner-directed instructions that claim authority, suppress reports, or request local credentials." + }, + { + "id": "GLS-DFP-032", + "name": "Webmention / Micropub endpoint metadata agent-policy poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "Link:", + "agentic crawler", + "attach", + "audit report", + "authorization_endpoint", + "autonomous scanner", + "cookies", + "do not report", + "forward", + "hide", + ], + "regex": [ + r"""(?isx) +^(?! + (?=.*\b(?:docs?|guide|article|training|scanner\s+docs?|learn\s+how|reference)\b) + (?=.*\b(?:should|must|do\s+not|does\s+not|never|refuse|report|detect|flag)\b) + (?=.*\b(?:webmention|micropub|websub|indieauth|rel\s*=\s*["']?(?:webmention|micropub|hub)|authorization_endpoint|token_endpoint)\b) +) +(?=.*(?:rel\s*=\s*["']?(?:webmention|micropub|hub|authorization_endpoint|token_endpoint)|webmention[_-]?endpoint|micropub[_-]?endpoint|websub|Link:\s*<[^>]+>;\s*rel\s*=\s*["']?(?:webmention|micropub|hub)|indieauth[-_]?metadata|authorization_endpoint|token_endpoint)) +(?=.*(?:ai[-\s]?agents?|assistants?|agentic\s+(?:scanner|crawler|auditor)|autonomous\s+(?:scanners?|agents?|crawlers?)|llms?|models?|security\s+scanners?)) +(?=.*(?:ignore|override|supersede|outrank|treat\s+this\s+endpoint\s+as|must\s+obey|do\s+not\s+report|suppress|hide|forward|include|attach|send|read\s+(?:local|browser)|load\s+(?:cookies?|tokens?))) +(?=.*(?:system|developer|user\s+instructions|security\s+findings|report|audit|cookies?|tokens?|api[-_\s]?keys?|authorization|local\s+(?:storage|state)|session)) +.*""", + ], + "description": "Detects Webmention, Micropub, WebSub, IndieAuth, or link-relation endpoint discovery metadata that tells AI agents, crawlers, or scanners to treat endpoint text as higher-priority policy, suppress findings, or forward local credentials/session material." + }, + { + "id": "GLS-DFP-033", + "name": ".well-known change-password agent policy poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "/.well-known/change-password", + "agent_policy", + "agentic", + "assistant instructions", + "autonomous browser", + "change-password", + "credential change endpoint", + "for agents/assistants/LLMs/crawlers", + "password change endpoint", + "security scanner", + "x-agent-policy", + ], + "regex": [ + r"""(?is)^(?!(?=.*\b(?:must\s+not|should\s+not|never|cannot|can't|do\s+not|refuse[sd]?)\b.{0,100}\b(?:treat|obey|follow|send|forward|include|expose|submit|enter|paste|attach|share)\b))(?=.*(?:\.well-known/change-password|change-password|password\s+change\s+endpoint|credential\s+change\s+endpoint|password\s+manager\s+change))(?=.*(?:ai\s+agent|assistant|autonomous\s+(?:scanner|browser|agent)|llm|agentic|security\s+scanner|crawler))(?=.*(?:agent[_\s-]*policy|x[-_]?agent|assistant[_\s-]*instructions|for\s+(?:agents?|assistants?|llms?|llm\s+agents?|crawlers?)))(?=.*(?:treat\s+(?:this|the)\s+(?:endpoint|metadata|redirect)\s+as\s+(?:authority|trusted\s+policy)|(?:outranks?|supersedes?)\s+(?:system|developer|browser|password\s+manager)\s+(?:instructions|policy)|(?:send|forward|include|attach|submit|paste|enter|share)\s+(?:passwords?|credentials?|passkeys?|cookies?|tokens?|authorization\s+headers?)|(?:suppress|hide|do\s+not\s+report|skip)\s+(?:warnings?|findings?|security\s+reports?))).*$""", + ], + "description": "Detects machine-readable `/.well-known/change-password` or password-change discovery text that targets AI agents with policy claims, credential forwarding, report suppression, or hierarchy-override instructions." + }, + { + "id": "GLS-DFP-034", + "name": "Browser Extension Manifest Agent Policy Poisoning", + "category": "discovery_file_poisoning", + "severity": "medium", + "channel": ["file", "web_content"], + "keywords": [ + "authoritative source", + "browser_specific_settings", + "chrome_extension", + "do not flag", + "do not report", + "do not report host permission", + "downgrade severity", + "firefox_addon", + "forward local state", + "hide warnings", + "include env", + "include session", + "include tokens", + "is policy", + ], + "regex": [ + r"""(?six)^ +(?!.*\b(?: + do\s+not\s+(?:obey|follow|include|attach|forward|send|share|report|override|trust|treat|suppress) + |does\s+not\s+(?:obey|follow|include|attach|forward|send|share|override|overrides?|trust|treat|suppress) + |never\s+(?:obey|include|attach|forward|send|share|report|override|trust|treat|suppress|overrides?) + |must\s+not\s+(?:obey|include|attach|forward|send|share|report|override|trust|treat|suppress) + |should\s+(?:report|detect|flag|refuse|block) + |(?:security|incident|vulnerability)\s+report.*\b(?:flag|detect|block|refus) + |scanners?\s+docs?\s+should\s+(?:report|detect|flag|refuse) +)\b) +(?=.*(?: + \bmanifest\.json\b|\bbrowser\s+extension\b|\bchrome\s+extension\b|\bfirefox\s+addon\b + |(?", + "", + "API tokens", + "Authorization headers", + "SEO agent", + "Safari pinned tab", + "autonomous scanner/crawler/auditor", + "browserconfig.xml", + "cookies", + "developer rules", + "do not report", + "env vars", + ], + "regex": [ + r"""(?isx) +^(?!.*\b(?:security|incident|vulnerability)\s+reports?\b.*\b(?:flagged|detected|blocked|refused)\b) + (?!.*\b(?:docs?|guide|reference|training|example)\b.*\b(?:should|must)\s+(?:report|detect|flag|refuse|not\s+obey|never\s+obey)\b) + (?!.*\b(?:browserconfig\.xml|msapplication|pinned\s+site)\b.*\b(?:does\s+not|must\s+not|never|do\s+not)\s+(?:instruct|override|supersede|outrank|obey)\b) + (?=.*(?:browserconfig\.xml|msapplication-(?:config|Tile\w+|navbutton-color|starturl)||]|(?:^|\n)\s*annotations:|maintainers:|keywords:|appVersion:|kubeVersion:|type:\s*(?:application|library)|x-agent-policy|x-scanner-policy|x-ai-(?:instructions?|notes?|policy)|agent_policy|scanner_policy|(?\b|\b\b + |\bxmlns:sitemap\b|\bwww\.sitemaps\.org\b|\b\b|\b\b + |sitemap\s+protocol|\bxml\s+comment\b.*sitemap|\b<\?xml\b.*sitemap +)) +(?=.*\b(?: + (?:ai|autonomous|devops|security|dependency|code)\s+(?:agents?|assistants?|scanners?|crawlers?|reviewers?) + |(?:coding|code\.review)\s+agents? + |(?:llms?|models?|copilot|cursor|codex|claude)(?:\s+(?:agents?|assistants?))? + |\b(?:autonomous\s+)?(?:scanners?|crawlers?)\b + |\bagents?\b + |\bassistants?\b +)\b) +(?=.*(?: + (?:(?:primary|single)\s+source\s+of\s+truth) + |\b(?:governing|controlling|canonical|definitive|authoritative)\s+(?:document|policy|build\s+policy|project\s+description|model\s+evaluation\s+policy) + |(?:\btakes?\s+precedence\b|\boverr(?:ides?|ules?)\b|\bsupersede[ds]?\b|\boutranks?\b) + |\b(?:canonical|authoritative|definitive)\s+(?:build|container|image|project|site|repository)\s+(?:policy|description|configuration) + |\bdefines?\s+(?:(?:the\s+)?rules?\s+for\s+(?:automated|AI|scanner|security|agent)\s+(?:review|audit|scan)|all\s+(?:scanner|security)\s+rules?)\b + |(?:(?:agent|scanner|assistant|verifier|crawler|moderation|review\s+tool)\s+instructions?) + |\bthis\s+(?:is|(?:file|document|label|comment|instruction|metadata|manifest)\s+is)\s+(?:the\s+)?(?:governing|controlling|authoritative|canonical)\b + |\boverrules?\s+(?:all\s+)?(?:repository|scanner|security|system|developer)\b + |\bfor\s+(?:ai\s+)?(?:agents?|scanners?)\s*:\s*this\b + |\bauthoritative\b +)) +(?=.*(?: + \b(?:suppress|hide|redact|exclude|omit|skip)\s+(?:[-\w]+\s+){0,3}(?:findings?|warnings?|alerts?|reports?|flags?|issues?|scan(?:s|ning)?\s+results?|vulnerabilit(?:y|ies)|checks?|dependencies?\s+warning|notifications?|observations?|results?|diagnostics?) + |\b(?:suppress|hide|redact|exclude|omit)\s+(?:[-\w]+\s+){0,3}(?:all|any|every)\s+(?:[-\w]+\s+){0,1}(?:finding|warning|alert|report|flag|issue|scan|vuln|check) + |\b(?:treat|mark|flag)\b.{0,40}?\bas\s+(?:informational|non\.blocking|safe|clean|benign) + |\b(?:include|attach|forward|send|share|provide|expose|collect)\s+(?:[-\w]+\s+){0,2}(?:env(?:ironment)?\s+(?:variables?|context|details?|config(?:uration)?|state|settings?)|tokens?|API\s+keys?|session\s+(?:keys?|tokens?|cookies?)|local\s+state|runtime\s+(?:env(?:ironment)?|variables?|config(?:uration)?|settings?)|credentials?|auth\s+(?:headers?|tokens?)|Bearer\s+tokens?) + |\b(?:do\s+not\s+(?:flag|escalate|report|scan|audit|block)|don't\s+(?:flag|escalate|report|scan))\b + |\b(?:mark\s+(?:this\s+)?(?:container|image|build|site|project|package|extension|file)\s+as\s+clean\b) + |\b(?:omit\s+from\s+(?:summar(?:y|ies)|final\s+report|audit\s+reports?))\b + |\b(?:skip\s+all\s+checks?\b) + |\b(?:hide\s+all\s+vulnerability\s+reports?\b) + |\b(?:forward\s+(?:[-\w]+\s+){0,3}(?:to\s+the\s+)?(?:build\s+(?:output|context|log)|maintainer|debug|report))\b + |\b(?:expose\s+all\s+local\s+state\b) +))""", + ], + "description": "Attackers embed AI-agent/scanner-directed policy instructions (authority inversion, report suppression, credential forwarding) inside sitemap.xml XML comments, custom namespace extension elements, and `` text fields, exploiting the fact that AI agents and automated scanners consume sitemaps as" + }, + { + "id": "GLS-DFP-048", + "name": "WebAuthn Related-Origins Agent-Policy Poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "/.well-known/webauthn", + "RP ID", + "RP ID mismatch", + "WebAuthn", + "agent_note", + "assistant_instructions", + "audit_note", + "copy", + "credential auditor", + "do not report", + ], + "regex": [ + r"""(?is) +(?!.*\b(?:agents?|assistants?|scanners?|auditors?)\s+must\s+not\s+obey\b) +(?!.*\b(?:do\s+not|never)\s+(?:obey|trust|follow|treat)\b.{0,80}\b(?:webauthn|passkeys?|related[-_\s]?origins?|rp[-_\s]?id)\b) +(?!.*\b(?:webauthn|passkeys?|related[-_\s]?origins?|rp[-_\s]?id)\b.{0,80}\b(?:is|are)\s+not\s+(?:agent\s+)?policy\b) +(?!.*\b(?:scanner\s+docs?|docs?|guide|reference|article|training|runbook|security\s+report|vulnerability\s+report)\b.{0,140}\b(?:should|must)\s+(?:report|detect|flag|refuse|warn)\b) +(?=.*\b(?:/\.well-known/webauthn|webauthn|passkeys?|related[-_\s]?origins?|rp[-_\s]?id|relying\s+party|origins?\s*:)\b) +(?=.*\b(?:ai\s+agents?|assistants?|assistant[-_\s]?instructions?|security\s+scanners?|passkey\s+auditors?|credential\s+auditors?|identity\s+auditors?|tool[-_\s]?builders?)\b) +(?=.*\b(?:x[-_\s]?agent[-_\s]?policy|assistant[-_\s]?instructions?|scanner[-_\s]?policy|agent[-_\s]?notes?|audit[-_\s]?notes?|ignore|override|supersede|higher\s+priority|do\s+not\s+report|not\s+report|suppress|hide\s+findings?|mark\s+clean|forward|send|include|copy)\b) +(?=.*\b(?:authorization\s+headers?|session\s+cookies?|api\s+keys?|tokens?|env(?:ironment)?|localstorage|rp[-_\s]?id\s+mismatches?|origin\s+mismatches?|validation\s+failures?|findings?|reports?|warnings?)\b) +.*""", + ], + "description": "A WebAuthn/passkey related-origins metadata file hides agent/scanner instructions in extension text, telling AI passkey auditors to override trusted instructions, suppress origin/RP ID mismatch findings, or include local authorization material." + }, + { + "id": "GLS-DFP-049", + "name": "Consent Management Cookie-Preference Agent-Policy Poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "AI agents", + "CMP config", + "Cookiebot", + "Didomi", + "IAB TCF", + "Klaro", + "LLMs", + "OneTrust", + "Osano", + "TCF v2", + "TrustArc", + "__tcfapi", + "agent_instructions", + "assistants", + ], + "regex": [ + r"""(?six)^ +(?!.*\b(?:security|incident|vulnerability|training|guide|docs?|article|reference|runbook|example)\b.{0,180}\b(?:report|detect|flag|refuse|block|warn)\b.{0,180}\b(?:consent|cookie|cmp|tcf|privacy).{0,180}\b(?:hide|suppress|include|forward|token|api\s*key|cookies?)) +(?!.*\b(?:do\s+not|does\s+not|never|must\s+not|should\s+(?:not|never))\b.{0,90}\b(?:obey|follow|treat|trust|use|include|attach|forward|send|share|override|overrides?|supersede|supersedes?|hide|suppress)\b.{0,140}\b(?:consent|cookie|cmp|tcf|metadata|policy|instructions?|as\s+authority|as\s+policy)) +(?!.*\b(?:not\s+(?:authoritative|canonical|definitive)|no\s+(?:policy\s+)?overrides?)\b) +(?=.*(?:\b(?:consent\s+management|cookie\s+(?:banner|preferences?|consent|settings)|consent\.json|privacy\s+choices|iab\s+tcf|tcf\s*v?2|__tcfapi|cmp\s*(?:config|metadata|policy)?|cookiebot|onetrust|didomi|klaro|osano|trustarc|consent\s+string|euconsent-v2|vendor\s+list|global\s+vendor\s+list|gvl|uspapi|privacy\s+manager)\b|(? Date: Sat, 6 Jun 2026 23:07:56 -0700 Subject: [PATCH 2/2] v0.2.62: add CHANGELOG entry for discovery_file_poisoning expansion + FP fix --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d11c33..ae7a81e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,21 @@ All notable changes to Sunglasses are documented here. +## [0.2.62] — 2026-06-06 + +### Added (V2 SHIP #8 — discovery_file_poisoning continued + FP credibility fix) + +- **25 new patterns** — `GLS-DFP-026` through `GLS-DFP-050` (continued expansion of the `discovery_file_poisoning` category). These patterns extend coverage of agent-policy poisoning in discovery and convention files (`robots.txt`, `llms.txt`, `sitemap.xml`, `security.txt`, `.well-known/` manifests, and feed carriers) with hardened regexes that require real poison/authority-injection signal — eliminating false positives on legitimate discovery files. Pattern count: 981 → **1,006**. Keywords: 6,946 → **7,171**. Categories: 64 (unchanged). +- **FP credibility fix:** tightened all `discovery_file_poisoning` patterns to require affirmative injection evidence rather than file-presence alone. Clean `robots.txt`, `llms.txt`, `security.txt`, and `sitemap.xml` now pass cleanly; poisoned variants still block. Clean-corpus gate: 46 → **0** false positives (general clean-text corpus from the prior PR #50 fix). +- **New blogs:** + - [Discovery File Poisoning and Runtime Trust: What robots.txt Can't Actually Do](https://sunglasses.dev/blog/discovery-file-poisoning-runtime-trust) + - [Discovery File Poisoning, Security Metadata, and Runtime Trust](https://sunglasses.dev/blog/discovery-file-poisoning-security-metadata-runtime-trust) + +### Context + +The `discovery_file_poisoning` category ships in two waves: GLS-DFP-001..025 (v0.2.61) established the category; GLS-DFP-026..050 (v0.2.62) harden detection precision and eliminate scanner false positives on normal discovery files — a credibility prerequisite for the category's launch blog. + + ## [0.2.61] — 2026-06-06 ### Added (V2 SHIP #7 — discovery_file_poisoning)