From 3e22f976c757911d5918ec3aba28fc2f18e331d9 Mon Sep 17 00:00:00 2001 From: Noel Saw Date: Fri, 26 Jun 2026 10:21:01 -0700 Subject: [PATCH] =?UTF-8?q?feat(scanner):=20ts-type-suppression=20detector?= =?UTF-8?q?=20=E2=80=94=20flags=20@ts-ignore/@ts-nocheck/bare=20@ts-expect?= =?UTF-8?q?-error=20(advisory,=20.ts/.tsx)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Marathon-dogfood build (xyz-3-agents-swarm harness): codex builder + agy reviewer (Approved). Advisory LOW-severity grep pattern, .ts/.tsx only, additive. Detects 3/3 suppression directives on the fixture; documented `@ts-expect-error // reason` excluded. First WPCC slice of issue #129. Committed manually because the marathon's cross-repo auto-commit skipped the new untracked files (harness bug; build itself passed gate + review). --- dist/PATTERN-LIBRARY.json | 30 ++++++++++++---- dist/PATTERN-LIBRARY.md | 35 ++++++++++--------- dist/patterns/ts-type-suppression.json | 40 ++++++++++++++++++++++ dist/tests/fixtures/ts-type-suppression.ts | 26 ++++++++++++++ dist/tests/run-fixture-tests.sh | 11 ++++++ 5 files changed, 118 insertions(+), 24 deletions(-) create mode 100644 dist/patterns/ts-type-suppression.json create mode 100644 dist/tests/fixtures/ts-type-suppression.ts diff --git a/dist/PATTERN-LIBRARY.json b/dist/PATTERN-LIBRARY.json index 6844d88..d995830 100644 --- a/dist/PATTERN-LIBRARY.json +++ b/dist/PATTERN-LIBRARY.json @@ -1,27 +1,27 @@ { "version": "1.0.0", - "generated": "2026-04-16T19:47:39Z", + "generated": "2026-06-26T16:56:07Z", "summary": { - "total_patterns": 56, - "enabled": 56, + "total_patterns": 57, + "enabled": 57, "disabled": 0, "by_severity": { "CRITICAL": 20, "HIGH": 17, "MEDIUM": 14, - "LOW": 4 + "LOW": 5 }, "by_category": { "performance": 22,"Performance": 5,"duplication": 5,"reliability": 6,"security": 14 }, "by_pattern_type": { - "php": 45, + "php": 46, "headless": 6, "nodejs": 4, "javascript": 1 }, "mitigation_detection_enabled": 7, - "heuristic_patterns": 18, + "heuristic_patterns": 19, "definitive_patterns": 38 }, "patterns": [ @@ -560,7 +560,7 @@ "mitigation_detection": false, "heuristic": false, "file": "php-hardcoded-credentials.json", - "search_pattern": "\\$[A-Za-z0-9_]*(password|passwd|secret|token|api_key|apikey|auth_token)[A-Za-z0-9_]*[[:space:]]*=[[:space:]]*['\"][^'\"]{8,}['\"]|\\$[A-Z0-9_]*(PASSWORD|PASSWD|SECRET|TOKEN|API_KEY|AUTH_TOKEN)[A-Z0-9_]*[[:space:]]*=[[:space:]]*['\"][^'\"]{8,}['\"]|define[[:space:]]*\\([[:space:]]*['\"][A-Z0-9_]*(SECRET|TOKEN|PASSWORD|KEY|API)[A-Z0-9_]*['\"][[:space:]]*,[[:space:]]*['\"][^'\"]{8,}['\"]|\"Authorization\"[[:space:]]*=>[[:space:]]*\"Bearer[[:space:]]+[A-Za-z0-9._-]{16,}\"", + "search_pattern": "\\$[A-Za-z0-9_]*(password|passwd|pwd|secret|token|api_key|apikey|auth_token|private_key|client_secret)[A-Za-z0-9_]*[[:space:]]*=[[:space:]]*['\"][^'\"]{8,}['\"]|\\$[A-Z0-9_]*(PASSWORD|PASSWD|PWD|SECRET|TOKEN|API_KEY|AUTH_TOKEN|PRIVATE_KEY|CLIENT_SECRET)[A-Z0-9_]*[[:space:]]*=[[:space:]]*['\"][^'\"]{8,}['\"]|define[[:space:]]*\\([[:space:]]*['\"][A-Z0-9_]*(SECRET|TOKEN|PASSWORD|KEY|API)[A-Z0-9_]*['\"][[:space:]]*,[[:space:]]*['\"][^'\"]{8,}['\"]|\"Authorization\"[[:space:]]*=>[[:space:]]*\"Bearer[[:space:]]+[A-Za-z0-9._-]{16,}\"", "file_patterns": ["*.php"] }, { @@ -699,6 +699,22 @@ "validator_script": "validators/transient-expiration-check.sh", "validator_args": [] }, +{ + "id": "ts-type-suppression", + "version": "1.0.0", + "enabled": true, + "category": "typescript", + "severity": "LOW", + "title": "TypeScript type-system suppression directives", + "description": "Detects TypeScript suppression directives that bypass the type checker in .ts and .tsx files.", + "detection_type": "direct", + "pattern_type": "php", + "mitigation_detection": false, + "heuristic": true, + "file": "ts-type-suppression.json", + "search_pattern": "^[[:space:]]*//[[:space:]]*@ts-ignore([[:space:]]|$)|^[[:space:]]*//[[:space:]]*@ts-nocheck([[:space:]]|$)|^[[:space:]]*//[[:space:]]*@ts-expect-error[[:space:]]*$", + "file_patterns": ["*.ts", "*.tsx"] +}, { "id": "unbounded-numberposts", "version": "1.0.0", diff --git a/dist/PATTERN-LIBRARY.md b/dist/PATTERN-LIBRARY.md index ad8cbf7..2241209 100644 --- a/dist/PATTERN-LIBRARY.md +++ b/dist/PATTERN-LIBRARY.md @@ -1,33 +1,33 @@ # Pattern Library Registry **Auto-generated by Pattern Library Manager** -**Last Updated:** 2026-03-24 01:34:38 UTC +**Last Updated:** 2026-06-26 16:55:18 UTC --- ## 📊 Summary Statistics ### Total Patterns -- **Total:** 56 patterns -- **Enabled:** 56 patterns +- **Total:** 57 patterns +- **Enabled:** 57 patterns - **Disabled:** 0 patterns ### By Severity | Severity | Count | Percentage | |----------|-------|------------| -| CRITICAL | 20 | 35.7% | -| HIGH | 17 | 30.4% | -| MEDIUM | 14 | 25.0% | -| LOW | 4 | 7.1% | +| CRITICAL | 20 | 35.1% | +| HIGH | 17 | 29.8% | +| MEDIUM | 14 | 24.6% | +| LOW | 5 | 8.8% | ### By Type | Type | Count | Percentage | |------|-------|------------| -| Definitive | 38 | 67.9% | -| Heuristic | 18 | 32.1% | +| Definitive | 38 | 66.7% | +| Heuristic | 19 | 33.3% | ### Advanced Features -- **Mitigation Detection Enabled:** 7 patterns (12.5%) +- **Mitigation Detection Enabled:** 7 patterns (12.3%) - **False Positive Reduction:** 60-70% on mitigated patterns ### By Category @@ -38,7 +38,7 @@ - **security:** 14 patterns ### By Pattern Type -- **PHP/WordPress:** 45 patterns +- **PHP/WordPress:** 46 patterns - **Headless WordPress:** 6 patterns - **Node.js/Server-Side JS:** 4 patterns - **Client-Side JavaScript:** 1 patterns @@ -110,6 +110,7 @@ - **duplicate-capability-strings** 🔍 - Duplicate capability strings across files - **duplicate-storage-keys** 🔍 - Duplicate localStorage/sessionStorage keys across files - **timezone-sensitive-code** 🔍 - Timezone-sensitive patterns (current_time/date) +- **ts-type-suppression** 🔍 - TypeScript type-system suppression directives --- @@ -124,26 +125,26 @@ ### Key Selling Points -1. **Comprehensive Coverage:** 56 detection patterns across 5 categories -2. **Multi-Platform Support:** PHP/WordPress (45), Headless WordPress (6), Node.js (4), JavaScript (1) +1. **Comprehensive Coverage:** 57 detection patterns across 5 categories +2. **Multi-Platform Support:** PHP/WordPress (46), Headless WordPress (6), Node.js (4), JavaScript (1) 3. **Enterprise-Grade Accuracy:** 7 patterns with AI-powered mitigation detection (60-70% false positive reduction) 4. **Severity-Based Prioritization:** 20 CRITICAL + 17 HIGH severity patterns catch the most dangerous issues -5. **Intelligent Analysis:** 38 definitive patterns + 18 heuristic patterns for comprehensive code review +5. **Intelligent Analysis:** 38 definitive patterns + 19 heuristic patterns for comprehensive code review ### One-Liner Stats -> **56 detection patterns** | **7 with AI mitigation** | **60-70% fewer false positives** | **Multi-platform: PHP, Headless, Node.js, JS** +> **57 detection patterns** | **7 with AI mitigation** | **60-70% fewer false positives** | **Multi-platform: PHP, Headless, Node.js, JS** ### Feature Highlights - ✅ **20 CRITICAL** OOM and security patterns - ✅ **17 HIGH** performance and security patterns - ✅ **7 patterns** with context-aware severity adjustment -- ✅ **18 heuristic** patterns for code quality insights +- ✅ **19 heuristic** patterns for code quality insights - ✅ **Multi-platform:** WordPress, Headless, Node.js, JavaScript --- -**Generated:** 2026-03-24 01:34:38 UTC +**Generated:** 2026-06-26 16:55:18 UTC **Version:** 1.0.0 **Tool:** Pattern Library Manager diff --git a/dist/patterns/ts-type-suppression.json b/dist/patterns/ts-type-suppression.json new file mode 100644 index 0000000..45e98ed --- /dev/null +++ b/dist/patterns/ts-type-suppression.json @@ -0,0 +1,40 @@ +{ + "id": "ts-type-suppression", + "version": "1.0.0", + "enabled": true, + "detection_type": "direct", + "category": "typescript", + "severity": "LOW", + "title": "TypeScript type-system suppression directives", + "description": "Detects TypeScript suppression directives that bypass the type checker in .ts and .tsx files.", + "rationale": "Type-system suppression comments hide real typing problems, weaken refactors, and make unsafe assumptions harder to audit. Documented exceptions should stay explicit and rare.", + "detection": { + "type": "grep", + "file_patterns": ["*.ts", "*.tsx"], + "patterns": [ + { + "id": "ts-ignore-directive", + "pattern": "^[[:space:]]*//[[:space:]]*@ts-ignore([[:space:]]|$)", + "description": "Flags @ts-ignore directives because they silence the type checker without an explicit contract." + }, + { + "id": "ts-nocheck-directive", + "pattern": "^[[:space:]]*//[[:space:]]*@ts-nocheck([[:space:]]|$)", + "description": "Flags @ts-nocheck directives because they disable type checking for the file." + }, + { + "id": "ts-expect-error-directive", + "pattern": "^[[:space:]]*//[[:space:]]*@ts-expect-error[[:space:]]*$", + "description": "Flags bare @ts-expect-error directives that do not explain why the suppression is needed." + } + ], + "exclude_patterns": [ + "^ *// *@ts-expect-error +[^ ].*$" + ] + }, + "test_fixture": { + "path": "dist/tests/fixtures/ts-type-suppression.ts", + "expected_violations": 3, + "notes": "Fixture covers @ts-ignore, @ts-nocheck, and bare @ts-expect-error while sparing documented suppressions and string literals." + } +} diff --git a/dist/tests/fixtures/ts-type-suppression.ts b/dist/tests/fixtures/ts-type-suppression.ts new file mode 100644 index 0000000..080f526 --- /dev/null +++ b/dist/tests/fixtures/ts-type-suppression.ts @@ -0,0 +1,26 @@ +type UserRecord = { + id: number; + name: string; +}; + +const cleanUser: UserRecord = { id: 1, name: "Ada" }; +const cleanIds: number[] = [cleanUser.id]; +const directiveAsText = "// @ts-ignore inside a string should not match"; + +// BAD: hides a bad assignment without explanation. +// @ts-ignore +const ignoredAssignment: string = 42; + +// BAD: disables type checking for the file segment. +// @ts-nocheck +const uncheckedLiteral: boolean = "false"; + +// BAD: bare suppression with no explanation. +// @ts-expect-error +const undocumentedExpectation: string = 99; + +// GOOD: documented suppression with an explanation. +// @ts-expect-error needs upstream fix #123 +const documentedExpectation: string = 99; + +export { cleanIds, directiveAsText, documentedExpectation, ignoredAssignment, uncheckedLiteral, undocumentedExpectation }; diff --git a/dist/tests/run-fixture-tests.sh b/dist/tests/run-fixture-tests.sh index 953ccab..dc060d4 100755 --- a/dist/tests/run-fixture-tests.sh +++ b/dist/tests/run-fixture-tests.sh @@ -167,6 +167,11 @@ CRON_INTERVAL_EXPECTED_ERRORS=1 # 1 error with 3 findings (lines 15, 24, 33) CRON_INTERVAL_EXPECTED_WARNINGS_MIN=0 CRON_INTERVAL_EXPECTED_WARNINGS_MAX=0 +# ts-type-suppression.ts - TypeScript suppression directives should warn once +TS_TYPE_SUPPRESSION_EXPECTED_ERRORS=0 +TS_TYPE_SUPPRESSION_EXPECTED_WARNINGS_MIN=1 +TS_TYPE_SUPPRESSION_EXPECTED_WARNINGS_MAX=1 + # ============================================================ # Helper Functions # ============================================================ @@ -369,12 +374,18 @@ if [ ! -f "$FIXTURES_DIR/ajax-safe.php" ]; then exit 1 fi +if [ ! -f "$FIXTURES_DIR/ts-type-suppression.ts" ]; then + echo -e "${RED}Error: ts-type-suppression.ts fixture not found${NC}" + exit 1 +fi + # Run tests (passing: errors, warnings_min, warnings_max) run_test "$FIXTURES_DIR/antipatterns.php" "$ANTIPATTERNS_EXPECTED_ERRORS" "$ANTIPATTERNS_EXPECTED_WARNINGS_MIN" "$ANTIPATTERNS_EXPECTED_WARNINGS_MAX" || true run_test "$FIXTURES_DIR/clean-code.php" "$CLEAN_CODE_EXPECTED_ERRORS" "$CLEAN_CODE_EXPECTED_WARNINGS_MIN" "$CLEAN_CODE_EXPECTED_WARNINGS_MAX" || true run_test "$FIXTURES_DIR/ajax-antipatterns.php" "$AJAX_PHP_EXPECTED_ERRORS" "$AJAX_PHP_EXPECTED_WARNINGS_MIN" "$AJAX_PHP_EXPECTED_WARNINGS_MAX" || true run_test "$FIXTURES_DIR/ajax-antipatterns.js" "$AJAX_JS_EXPECTED_ERRORS" "$AJAX_JS_EXPECTED_WARNINGS_MIN" "$AJAX_JS_EXPECTED_WARNINGS_MAX" || true run_test "$FIXTURES_DIR/ajax-safe.php" "$AJAX_SAFE_EXPECTED_ERRORS" "$AJAX_SAFE_EXPECTED_WARNINGS_MIN" "$AJAX_SAFE_EXPECTED_WARNINGS_MAX" || true +run_test "$FIXTURES_DIR/ts-type-suppression.ts" "$TS_TYPE_SUPPRESSION_EXPECTED_ERRORS" "$TS_TYPE_SUPPRESSION_EXPECTED_WARNINGS_MIN" "$TS_TYPE_SUPPRESSION_EXPECTED_WARNINGS_MAX" || true # ============================================================ # JSON Output Format Test