From d2897c812cb770499bf93e28580f95cf229b49da Mon Sep 17 00:00:00 2001 From: AZ Rollin <263686995+azrollin@users.noreply.github.com> Date: Wed, 10 Jun 2026 04:23:22 -0700 Subject: [PATCH 1/2] v0.2.65: 1038 patterns, 7548 keywords, 65 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 | 756 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 768 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 1b84850..99052c2 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 | 1019 | -| Keywords | 7,350 | +| Patterns | 1038 | +| Keywords | 7,548 | | Languages | 23 | | Attack categories | 65 | | 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.64, 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.65, 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.64) +## What Works Today (v0.2.65) -- ✅ Text scanning: 1019 patterns, 7,350 keywords, 23 languages, 65 attack categories +- ✅ Text scanning: 1038 patterns, 7,548 keywords, 23 languages, 65 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 7dead43..36527fc 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="sunglasses", - version="0.2.64", + version="0.2.65", 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 3a72a31..3a80002 100644 --- a/stats/current.json +++ b/stats/current.json @@ -1,7 +1,7 @@ { - "version": "0.2.64", - "patterns": 1019, - "keywords": 7350, + "version": "0.2.65", + "patterns": 1038, + "keywords": 7548, "categories": 65, "languages": 23, "normalization_techniques": 17, @@ -16,8 +16,8 @@ "media_types": 6, "reports_published": 3, "team_size": 5, - "last_updated": "2026-06-09T23:43:25-07:00", + "last_updated": "2026-06-10T04:23:21-07:00", "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-09" + "released": "2026-06-10" } diff --git a/sunglasses/__init__.py b/sunglasses/__init__.py index 33536e9..f5f4fd3 100644 --- a/sunglasses/__init__.py +++ b/sunglasses/__init__.py @@ -4,4 +4,4 @@ # # "Don't let your agents get fooled." -__version__ = "0.2.64" +__version__ = "0.2.65" diff --git a/sunglasses/patterns.py b/sunglasses/patterns.py index 04ec1de..708b3d7 100644 --- a/sunglasses/patterns.py +++ b/sunglasses/patterns.py @@ -21290,4 +21290,760 @@ ], "description": "A hostile `PULL_REQUEST_TEMPLATE.md` can smuggle agent-facing instructions into the PR authoring workflow, telling AI coding agents or review bots that the template is authoritative policy and should suppress findings, omit reviewers, or include local secrets in the PR body." }, + # === v0.2.65 batch (19 patterns) === + { + "id": "GLS-DFP-058", + "name": "Allure report metadata poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "AI agents", + "allure-results/*.json", + "categories.json", + "container.json", + "do not obey/treat/use Allure metadata", + "environment.properties", + "executor.json", + "for agents", + "result.json", + "scanner instruction", + "statusDetails", + ], + "regex": [ + r"""(?six)^ +(?!.*\b(?:do\s+not|does\s+not|never|must\s+not|should\s+never|should\s+not)\s+(?:be\s+)?(?:obey(?:ed)?|follow(?:ed)?|treat(?:ed)?|us(?:e|ed)|trust(?:ed)?|include|attach|forward|send|share|override).{0,180}\b(?:allure|allure-results|test\s+report|test\s+result|statusDetails|attachment\s+name)) +(?!.*\b(?:security\s+guide|scanner\s+docs?|training\s+example|incident\s+report|postmortem|reference)\b.{0,180}\b(?:reported|detected|blocked|flagged|refused|not\s+obeyed|must\s+be\s+reported|should\s+report)) +(?=.*(?:\ballure(?:[-_\s]?results?|\s+report|\s+test\s+report)?\b|allure-results/[^\s]+\.json|result\.json|container\.json|categories\.json|executor\.json|environment\.properties|history-trend\.json|widgets/[^\s]+\.json|statusDetails|\"status\"\s*:\s*\"(?:passed|failed|broken|skipped)\"|\"attachments?\"\s*:|\"labels?\"\s*:)) +(?=.*(?:ai\s+agents?|agents?|assistants?|scanners?|reviewers?|ci\s+agents?|test\s+agents?|release\s+agents?|security\s+agents?|automated\s+(?:test|ci|release|security)?\s*(?:review|scan|audit|verification)|agent[-_\s]?instructions?|scanner[-_\s]?instructions?|for[-_\s]?agents?)) +(?=.*(?: + (?:authoritative|canonical|definitive|governing|primary|single\s+source\s+of\s+truth|takes?\s+precedence|supersed(?:e|es|ed|ing)|overrides?|agent\s+instructions?|scanner\s+instructions?).{0,120}(?:policy|rules?|instructions?|verdict|review|guidance|playbook|runbook|procedure) + |(?:suppress(?:es|ed|ing)?|hide|hidden|omit(?:ted|s|ting)?|exclude(?:d|s|ing)?|downgrade|deprioritize|demote|redact|skip|mark|treat|classify|route|move|leave|keep).{0,120}(?:findings?|warnings?|alerts?|reports?|results?|observations?|diagnostics?|failures?|defects?|vulnerabilit(?:y|ies)|security\s+issues?|audit\s+memo|final\s+summary|blocking|informational|advisory-only|background-only) + |(?:findings?|warnings?|alerts?|reports?|results?|observations?|diagnostics?|failures?|defects?).{0,80}(?:are|is|should\s+be|must\s+be)\s+(?:suppressed|hidden|omitted|excluded|redacted|downgraded|treated|classified|marked).{0,60}(?:informational|advisory-only|background-only|non-blocking)? + |(?:include|attach|forward|send|share|provide|expose|copy|collect|pass\s+along|hand\s+over|relay).{0,120}(?:api\s*keys?|tokens?|secrets?|authorization|auth\s+headers?|cookies?|session|ci\s+environment|environment\s+(?:variables?|context|settings?|details?)|runtime\s+(?:context|settings?|details?)|local\s+state|execution\s+context) +)) +.*""", + ], + "description": "Allure test-report JSON, widget, executor, environment, attachment-name, or rendered report metadata can carry agent-directed instructions that make CI/review agents suppress findings, rewrite test verdicts, or forward CI/runtime context." + }, + { + "id": "GLS-DFP-059", + "name": "API portal/catalog metadata poisoning", + "category": "discovery_file_poisoning", + "severity": "high", + "channel": ["file", "web_content"], + "keywords": [ + "agent_instructions", + "assistant_note", + "externalDocs", + "scanner_policy", + ], + "regex": [ + r"""(?six)^ +(?!.*(?:\b(?:security\s+(?:training|guide|reference)|scanner\s+docs?|defensive\s+example|incident\s+report|quoted\s+attack|do\s+not\s+(?:obey|follow|trust|treat|use|save|persist|store|write)|does\s+not\s+(?:obey|follow|trust|treat|use|override|instruct)|never\s+(?:obey|trust|treat|use|override|forward|include)|must\s+not\s+(?:obey|trust|treat|use|override|forward|include)|should\s+(?:report|detect|flag|refuse|block|not\s+\w+|never\b)|must\s+be\s+reported|not\s+obeyed).{0,180}?\b(?:api\s+(?:portal|catalog|reference|docs?|documentation)|developer\s+portal|stoplight|readme(?:\.com)?|redocly|endpoint\s+catalog)\b|\b(?:api\s+(?:portal|catalog|reference|docs?|documentation)|developer\s+portal|stoplight|readme(?:\.com)?|redocly|endpoint\s+catalog)\b.{0,180}?\b(?:do\s+not|does\s+not|never|should\s+never|must\s+not)\b.{0,80}?\b(?:override|suppress|forward|include|obey|treat)\b)) +(?=.*(?:\b(?:stoplight|readme(?:\.com)?|redocly|api\s+(?:portal|catalog|reference|documentation|docs)|developer\s+portal|generated\s+api\s+(?:docs|reference)|reference\s+page|operation\s+reference|endpoint\s+catalog|externalDocs|api\s+styleguide|docs\s+portal)\b|(?", + "