attocode-code-intel 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- attocode_code_intel-0.1.0.dist-info/METADATA +221 -0
- attocode_code_intel-0.1.0.dist-info/RECORD +345 -0
- attocode_code_intel-0.1.0.dist-info/WHEEL +4 -0
- attocode_code_intel-0.1.0.dist-info/entry_points.txt +2 -0
- attocode_code_intel-0.1.0.dist-info/licenses/LICENSE +21 -0
- attocode_intel/GUIDELINES.md +432 -0
- attocode_intel/__init__.py +52 -0
- attocode_intel/_internal/__init__.py +1 -0
- attocode_intel/_internal/errors/__init__.py +126 -0
- attocode_intel/_internal/integrations/__init__.py +1 -0
- attocode_intel/_internal/integrations/context/__init__.py +1 -0
- attocode_intel/_internal/integrations/context/architecture_drift.py +354 -0
- attocode_intel/_internal/integrations/context/ast_chunker.py +202 -0
- attocode_intel/_internal/integrations/context/ast_service.py +1483 -0
- attocode_intel/_internal/integrations/context/blob_oid.py +423 -0
- attocode_intel/_internal/integrations/context/cache_manifest.py +221 -0
- attocode_intel/_internal/integrations/context/cas.py +466 -0
- attocode_intel/_internal/integrations/context/code_analyzer.py +528 -0
- attocode_intel/_internal/integrations/context/codebase_ast.py +1461 -0
- attocode_intel/_internal/integrations/context/codebase_context.py +1736 -0
- attocode_intel/_internal/integrations/context/cross_mode.py +263 -0
- attocode_intel/_internal/integrations/context/cross_references.py +616 -0
- attocode_intel/_internal/integrations/context/embedding_rotation.py +597 -0
- attocode_intel/_internal/integrations/context/embeddings.py +282 -0
- attocode_intel/_internal/integrations/context/frecency.py +427 -0
- attocode_intel/_internal/integrations/context/fuzzy.py +320 -0
- attocode_intel/_internal/integrations/context/hierarchical_explorer.py +331 -0
- attocode_intel/_internal/integrations/context/hydration.py +90 -0
- attocode_intel/_internal/integrations/context/index_repair.py +87 -0
- attocode_intel/_internal/integrations/context/index_store.py +586 -0
- attocode_intel/_internal/integrations/context/memory_store.py +602 -0
- attocode_intel/_internal/integrations/context/module_resolution.py +52 -0
- attocode_intel/_internal/integrations/context/query_constraints.py +361 -0
- attocode_intel/_internal/integrations/context/query_history.py +417 -0
- attocode_intel/_internal/integrations/context/reranker.py +351 -0
- attocode_intel/_internal/integrations/context/semantic_search.py +2931 -0
- attocode_intel/_internal/integrations/context/syntax_evidence.py +94 -0
- attocode_intel/_internal/integrations/context/systemone_ranker.py +245 -0
- attocode_intel/_internal/integrations/context/temporal_coupling.py +411 -0
- attocode_intel/_internal/integrations/context/trigram_index.py +820 -0
- attocode_intel/_internal/integrations/context/trigram_regex.py +171 -0
- attocode_intel/_internal/integrations/context/ts_parser.py +2199 -0
- attocode_intel/_internal/integrations/context/vector_store.py +795 -0
- attocode_intel/_internal/integrations/feature_flags/__init__.py +357 -0
- attocode_intel/_internal/integrations/lsp/__init__.py +1 -0
- attocode_intel/_internal/integrations/lsp/client.py +1140 -0
- attocode_intel/_internal/integrations/mcp/__init__.py +1 -0
- attocode_intel/_internal/integrations/mcp/client.py +253 -0
- attocode_intel/_internal/integrations/security/__init__.py +1 -0
- attocode_intel/_internal/integrations/security/custom_rules.py +176 -0
- attocode_intel/_internal/integrations/security/dataflow.py +522 -0
- attocode_intel/_internal/integrations/security/dependency_audit.py +303 -0
- attocode_intel/_internal/integrations/security/matcher.py +44 -0
- attocode_intel/_internal/integrations/security/patterns.py +724 -0
- attocode_intel/_internal/integrations/security/scanner.py +351 -0
- attocode_intel/_internal/integrations/utilities/__init__.py +1 -0
- attocode_intel/_internal/integrations/utilities/ignore.py +64 -0
- attocode_intel/_internal/integrations/utilities/token_estimate.py +51 -0
- attocode_intel/_internal/tricks/__init__.py +1 -0
- attocode_intel/_internal/tricks/recursive_context.py +357 -0
- attocode_intel/_internal/types/__init__.py +1 -0
- attocode_intel/_internal/types/events.py +289 -0
- attocode_intel/_internal/types/severity.py +15 -0
- attocode_intel/_shared.py +341 -0
- attocode_intel/analysis_coverage.py +56 -0
- attocode_intel/api/__init__.py +1 -0
- attocode_intel/api/access.py +32 -0
- attocode_intel/api/app.py +247 -0
- attocode_intel/api/auth/__init__.py +128 -0
- attocode_intel/api/auth/api_keys.py +61 -0
- attocode_intel/api/auth/context.py +34 -0
- attocode_intel/api/auth/jwt.py +66 -0
- attocode_intel/api/auth/oauth.py +146 -0
- attocode_intel/api/auth/passwords.py +15 -0
- attocode_intel/api/deps.py +351 -0
- attocode_intel/api/knowledge_bridge.py +13 -0
- attocode_intel/api/mcp_transport.py +51 -0
- attocode_intel/api/middleware.py +411 -0
- attocode_intel/api/models.py +698 -0
- attocode_intel/api/providers/__init__.py +1 -0
- attocode_intel/api/providers/db_provider.py +1106 -0
- attocode_intel/api/providers/local_provider.py +476 -0
- attocode_intel/api/providers/remote_provider.py +740 -0
- attocode_intel/api/repository_source.py +21 -0
- attocode_intel/api/routes/__init__.py +1 -0
- attocode_intel/api/routes/_pin_helper.py +158 -0
- attocode_intel/api/routes/activity.py +148 -0
- attocode_intel/api/routes/adr.py +102 -0
- attocode_intel/api/routes/analysis.py +515 -0
- attocode_intel/api/routes/api_keys.py +170 -0
- attocode_intel/api/routes/auth.py +428 -0
- attocode_intel/api/routes/branches.py +262 -0
- attocode_intel/api/routes/cross_repo_search.py +198 -0
- attocode_intel/api/routes/embeddings.py +386 -0
- attocode_intel/api/routes/files.py +132 -0
- attocode_intel/api/routes/files_v2.py +388 -0
- attocode_intel/api/routes/gc.py +322 -0
- attocode_intel/api/routes/git_v2.py +433 -0
- attocode_intel/api/routes/graph.py +174 -0
- attocode_intel/api/routes/graph_viz.py +160 -0
- attocode_intel/api/routes/health.py +62 -0
- attocode_intel/api/routes/history.py +175 -0
- attocode_intel/api/routes/jobs.py +84 -0
- attocode_intel/api/routes/learning.py +205 -0
- attocode_intel/api/routes/lsp.py +272 -0
- attocode_intel/api/routes/notify.py +623 -0
- attocode_intel/api/routes/operations.py +27 -0
- attocode_intel/api/routes/orgs.py +924 -0
- attocode_intel/api/routes/preferences.py +100 -0
- attocode_intel/api/routes/presence.py +42 -0
- attocode_intel/api/routes/projects.py +116 -0
- attocode_intel/api/routes/repos.py +47 -0
- attocode_intel/api/routes/search.py +180 -0
- attocode_intel/api/routes/snapshots.py +614 -0
- attocode_intel/api/routes/webhooks.py +313 -0
- attocode_intel/api/routes/websocket.py +116 -0
- attocode_intel/api/static/graph.html +239 -0
- attocode_intel/api/utils.py +96 -0
- attocode_intel/artifacts/__init__.py +45 -0
- attocode_intel/artifacts/hashing.py +230 -0
- attocode_intel/artifacts/provenance.py +190 -0
- attocode_intel/artifacts/retrieval_pin.py +159 -0
- attocode_intel/audit.py +59 -0
- attocode_intel/bug_finder.py +206 -0
- attocode_intel/bundle.py +80 -0
- attocode_intel/catalog.py +242 -0
- attocode_intel/change_review.py +75 -0
- attocode_intel/cli.py +3062 -0
- attocode_intel/community.py +63 -0
- attocode_intel/confidence/__init__.py +144 -0
- attocode_intel/confidence/jev.py +234 -0
- attocode_intel/confidence/llm.py +330 -0
- attocode_intel/confidence/redact.py +44 -0
- attocode_intel/confidence/settings.py +74 -0
- attocode_intel/config.py +256 -0
- attocode_intel/crypto.py +31 -0
- attocode_intel/db/__init__.py +7 -0
- attocode_intel/db/base.py +33 -0
- attocode_intel/db/engine.py +61 -0
- attocode_intel/db/models.py +529 -0
- attocode_intel/entrypoint.py +185 -0
- attocode_intel/focused_evidence.py +130 -0
- attocode_intel/freshness.py +154 -0
- attocode_intel/gateway.py +734 -0
- attocode_intel/git/__init__.py +7 -0
- attocode_intel/git/credentials.py +75 -0
- attocode_intel/git/manager.py +493 -0
- attocode_intel/git/models.py +96 -0
- attocode_intel/git/storage.py +98 -0
- attocode_intel/graph_query_parser.py +761 -0
- attocode_intel/helpers.py +712 -0
- attocode_intel/indexing/__init__.py +29 -0
- attocode_intel/indexing/debouncer.py +136 -0
- attocode_intel/indexing/delta_indexer.py +151 -0
- attocode_intel/indexing/full_indexer.py +323 -0
- attocode_intel/indexing/incremental.py +240 -0
- attocode_intel/indexing/parser.py +403 -0
- attocode_intel/indexing/summarizer.py +264 -0
- attocode_intel/installer.py +1896 -0
- attocode_intel/knowledge.py +269 -0
- attocode_intel/local_knowledge.py +77 -0
- attocode_intel/migrations/alembic.ini +36 -0
- attocode_intel/migrations/env.py +71 -0
- attocode_intel/migrations/script.py.mako +27 -0
- attocode_intel/migrations/versions/001_initial_schema.py +219 -0
- attocode_intel/migrations/versions/002_branch_version_and_embeddings.py +61 -0
- attocode_intel/migrations/versions/003_embedding_uniqueness_and_cascade.py +51 -0
- attocode_intel/migrations/versions/004_audit_events.py +38 -0
- attocode_intel/migrations/versions/005_user_preferences.py +30 -0
- attocode_intel/migrations/versions/006_google_oauth.py +27 -0
- attocode_intel/migrations/versions/007_pgvector_embeddings.py +28 -0
- attocode_intel/migrations/versions/008_symbol_references.py +37 -0
- attocode_intel/migrations/versions/009_webhook_secret_encryption.py +25 -0
- attocode_intel/migrations/versions/010_add_commits_table.py +40 -0
- attocode_intel/migrations/versions/011_commit_changed_files.py +25 -0
- attocode_intel/migrations/versions/012_branch_merged_at.py +25 -0
- attocode_intel/migrations/versions/013_revoked_tokens.py +32 -0
- attocode_intel/migrations/versions/014_blame_hunks.py +40 -0
- attocode_intel/migrations/versions/015_commit_file_stats.py +40 -0
- attocode_intel/migrations/versions/016_embedding_provenance_columns.py +179 -0
- attocode_intel/migrations/versions/017_provenance_table.py +102 -0
- attocode_intel/migrations/versions/018_repo_snapshots.py +178 -0
- attocode_intel/migrations/versions/019_symref_caller.py +42 -0
- attocode_intel/migrations/versions/020_shared_knowledge.py +29 -0
- attocode_intel/onboarding.py +258 -0
- attocode_intel/output.py +178 -0
- attocode_intel/precision.py +133 -0
- attocode_intel/presence.py +160 -0
- attocode_intel/probe.py +110 -0
- attocode_intel/project_dir.py +97 -0
- attocode_intel/pubsub.py +113 -0
- attocode_intel/query_ranking.py +242 -0
- attocode_intel/readiness.py +972 -0
- attocode_intel/redis.py +51 -0
- attocode_intel/reference_pages.py +60 -0
- attocode_intel/remote.py +131 -0
- attocode_intel/repo_ranker.py +246 -0
- attocode_intel/request_context.py +82 -0
- attocode_intel/rules/__init__.py +28 -0
- attocode_intel/rules/ci.py +320 -0
- attocode_intel/rules/combinators.py +293 -0
- attocode_intel/rules/enricher.py +127 -0
- attocode_intel/rules/evolution.py +452 -0
- attocode_intel/rules/executor.py +531 -0
- attocode_intel/rules/filters/__init__.py +5 -0
- attocode_intel/rules/filters/pipeline.py +151 -0
- attocode_intel/rules/formatter.py +198 -0
- attocode_intel/rules/hygiene.py +242 -0
- attocode_intel/rules/importers/__init__.py +1 -0
- attocode_intel/rules/importers/semgrep.py +382 -0
- attocode_intel/rules/loader.py +292 -0
- attocode_intel/rules/marketplace.py +375 -0
- attocode_intel/rules/metavar.py +181 -0
- attocode_intel/rules/model.py +317 -0
- attocode_intel/rules/packs/__init__.py +1 -0
- attocode_intel/rules/packs/community/_license_templates/Apache-2.0.txt +176 -0
- attocode_intel/rules/packs/community/_license_templates/MIT.txt +21 -0
- attocode_intel/rules/packs/community/bandit-python/LICENSE +176 -0
- attocode_intel/rules/packs/community/bandit-python/NOTICE +13 -0
- attocode_intel/rules/packs/community/bandit-python/PORTING.md +23 -0
- attocode_intel/rules/packs/community/bandit-python/manifest.yaml +14 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B105-hardcoded-password.yaml +23 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B303-weak-md5.yaml +21 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B304-weak-des.yaml +20 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B307-use-of-eval.yaml +22 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B324-weak-sha1.yaml +21 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B501-no-cert-validation.yaml +23 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B602-shell-true.yaml +22 -0
- attocode_intel/rules/packs/community/bandit-python/rules/B608-sqli.yaml +22 -0
- attocode_intel/rules/packs/community/eslint-typescript/LICENSE +21 -0
- attocode_intel/rules/packs/community/eslint-typescript/NOTICE +13 -0
- attocode_intel/rules/packs/community/eslint-typescript/PORTING.md +23 -0
- attocode_intel/rules/packs/community/eslint-typescript/manifest.yaml +14 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/eqeqeq.yaml +20 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-eval.yaml +22 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-implied-eval.yaml +20 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-new-func.yaml +21 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-throw-literal.yaml +19 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-var.yaml +20 -0
- attocode_intel/rules/packs/community/eslint-typescript/rules/no-with.yaml +18 -0
- attocode_intel/rules/packs/community/gosec-go/LICENSE +176 -0
- attocode_intel/rules/packs/community/gosec-go/NOTICE +13 -0
- attocode_intel/rules/packs/community/gosec-go/PORTING.md +23 -0
- attocode_intel/rules/packs/community/gosec-go/manifest.yaml +14 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G101-hardcoded-credentials.yaml +22 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G102-bind-all-interfaces.yaml +21 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G103-unsafe-block.yaml +21 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G201-sql-format.yaml +21 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G304-file-inclusion.yaml +23 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G401-weak-cipher.yaml +20 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G402-tls-min-version.yaml +20 -0
- attocode_intel/rules/packs/community/gosec-go/rules/G501-md5-import.yaml +21 -0
- attocode_intel/rules/packs/examples/cpp/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/cpp/rules/security.yaml +90 -0
- attocode_intel/rules/packs/examples/cpp/rules/structural.yaml +42 -0
- attocode_intel/rules/packs/examples/csharp/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/csharp/rules/security.yaml +69 -0
- attocode_intel/rules/packs/examples/csharp/rules/structural.yaml +42 -0
- attocode_intel/rules/packs/examples/go/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/go/rules/performance.yaml +136 -0
- attocode_intel/rules/packs/examples/go/rules/security.yaml +48 -0
- attocode_intel/rules/packs/examples/go/rules/structural.yaml +58 -0
- attocode_intel/rules/packs/examples/go/taint/sanitizers.yaml +24 -0
- attocode_intel/rules/packs/examples/go/taint/sinks.yaml +51 -0
- attocode_intel/rules/packs/examples/go/taint/sources.yaml +26 -0
- attocode_intel/rules/packs/examples/java/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/java/rules/correctness.yaml +55 -0
- attocode_intel/rules/packs/examples/java/rules/structural.yaml +48 -0
- attocode_intel/rules/packs/examples/java/taint/sinks.yaml +37 -0
- attocode_intel/rules/packs/examples/java/taint/sources.yaml +21 -0
- attocode_intel/rules/packs/examples/kotlin/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/kotlin/rules/correctness.yaml +50 -0
- attocode_intel/rules/packs/examples/kotlin/rules/structural.yaml +38 -0
- attocode_intel/rules/packs/examples/php/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/php/rules/security.yaml +66 -0
- attocode_intel/rules/packs/examples/php/rules/structural.yaml +41 -0
- attocode_intel/rules/packs/examples/python/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/python/rules/performance.yaml +90 -0
- attocode_intel/rules/packs/examples/python/rules/structural.yaml +55 -0
- attocode_intel/rules/packs/examples/ruby/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/ruby/rules/security.yaml +73 -0
- attocode_intel/rules/packs/examples/ruby/rules/structural.yaml +41 -0
- attocode_intel/rules/packs/examples/rust/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/rust/rules/correctness.yaml +51 -0
- attocode_intel/rules/packs/examples/rust/rules/structural.yaml +49 -0
- attocode_intel/rules/packs/examples/typescript/manifest.yaml +4 -0
- attocode_intel/rules/packs/examples/typescript/rules/performance.yaml +70 -0
- attocode_intel/rules/packs/examples/typescript/rules/structural.yaml +48 -0
- attocode_intel/rules/packs/pack_loader.py +244 -0
- attocode_intel/rules/plugins/__init__.py +1 -0
- attocode_intel/rules/plugins/plugin_loader.py +132 -0
- attocode_intel/rules/profiling.py +332 -0
- attocode_intel/rules/registry.py +213 -0
- attocode_intel/rules/sarif.py +187 -0
- attocode_intel/rules/synthesis.py +420 -0
- attocode_intel/rules/testing.py +326 -0
- attocode_intel/server.py +734 -0
- attocode_intel/service.py +3416 -0
- attocode_intel/sharing.py +57 -0
- attocode_intel/storage/__init__.py +6 -0
- attocode_intel/storage/branch_overlay.py +352 -0
- attocode_intel/storage/content_store.py +220 -0
- attocode_intel/storage/dependency_store.py +143 -0
- attocode_intel/storage/diff_engine.py +187 -0
- attocode_intel/storage/embedding_store.py +594 -0
- attocode_intel/storage/provenance_store.py +137 -0
- attocode_intel/storage/security_scanner_db.py +164 -0
- attocode_intel/storage/symbol_store.py +160 -0
- attocode_intel/structural_evidence.py +144 -0
- attocode_intel/symbol_inspection.py +141 -0
- attocode_intel/symbol_links.py +167 -0
- attocode_intel/telemetry.py +42 -0
- attocode_intel/test_ranking.py +73 -0
- attocode_intel/testing/__init__.py +43 -0
- attocode_intel/testing/fixtures.py +122 -0
- attocode_intel/testing/helpers.py +75 -0
- attocode_intel/testing/mocks.py +99 -0
- attocode_intel/tools/__init__.py +2 -0
- attocode_intel/tools/adr_tools.py +628 -0
- attocode_intel/tools/analysis_tools.py +382 -0
- attocode_intel/tools/composite_tools.py +695 -0
- attocode_intel/tools/cross_mode_tools.py +173 -0
- attocode_intel/tools/dead_code_tools.py +582 -0
- attocode_intel/tools/distill_tools.py +353 -0
- attocode_intel/tools/frecency_tools.py +220 -0
- attocode_intel/tools/fuzzy_tools.py +255 -0
- attocode_intel/tools/history_tools.py +486 -0
- attocode_intel/tools/learning_tools.py +222 -0
- attocode_intel/tools/lsp_tools.py +218 -0
- attocode_intel/tools/maintenance_tools.py +1662 -0
- attocode_intel/tools/navigation_tools.py +220 -0
- attocode_intel/tools/overlay_tools.py +540 -0
- attocode_intel/tools/pin_store.py +432 -0
- attocode_intel/tools/pin_tools.py +266 -0
- attocode_intel/tools/query_constraints_tools.py +262 -0
- attocode_intel/tools/query_history_tools.py +158 -0
- attocode_intel/tools/readiness_tools.py +44 -0
- attocode_intel/tools/rule_tools.py +992 -0
- attocode_intel/tools/search_tools.py +770 -0
- attocode_intel/tools/snapshot_tools.py +624 -0
- attocode_intel/workers/__init__.py +1 -0
- attocode_intel/workers/job_utils.py +111 -0
- attocode_intel/workers/jobs.py +573 -0
- attocode_intel/workers/run.py +30 -0
- attocode_intel/workers/settings.py +61 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# PHP security rules (Tier 1 regex).
|
|
2
|
+
|
|
3
|
+
- id: php-md5-deprecated
|
|
4
|
+
name: md5() used for security purposes
|
|
5
|
+
pattern: '\bmd5\s*\('
|
|
6
|
+
message: "md5() is broken for security — use password_hash() or hash('sha256', ...)"
|
|
7
|
+
severity: medium
|
|
8
|
+
category: security
|
|
9
|
+
languages: [php]
|
|
10
|
+
cwe: CWE-327
|
|
11
|
+
confidence: 0.6
|
|
12
|
+
recommendation: "Use password_hash($pw, PASSWORD_BCRYPT) for passwords, hash('sha256', ...) for general hashing."
|
|
13
|
+
|
|
14
|
+
- id: php-mysql-real-escape-string-only
|
|
15
|
+
name: mysql_real_escape_string as sole defense
|
|
16
|
+
pattern: '\bmysql_real_escape_string\s*\('
|
|
17
|
+
message: "mysql_* extension is removed in PHP 7+ — use PDO with parameterized queries"
|
|
18
|
+
severity: high
|
|
19
|
+
category: security
|
|
20
|
+
languages: [php]
|
|
21
|
+
cwe: CWE-89
|
|
22
|
+
confidence: 0.85
|
|
23
|
+
recommendation: "Migrate to PDO::prepare with bindParam, or mysqli prepared statements."
|
|
24
|
+
|
|
25
|
+
- id: php-superglobal-direct-output
|
|
26
|
+
name: $_GET / $_POST echoed directly
|
|
27
|
+
pattern: 'echo\s+\$_(?:GET|POST|REQUEST|COOKIE)'
|
|
28
|
+
message: "Echoing user input directly — XSS risk; escape with htmlspecialchars()"
|
|
29
|
+
severity: high
|
|
30
|
+
category: security
|
|
31
|
+
languages: [php]
|
|
32
|
+
cwe: CWE-79
|
|
33
|
+
confidence: 0.8
|
|
34
|
+
recommendation: "Wrap in htmlspecialchars($value, ENT_QUOTES, 'UTF-8') before echoing."
|
|
35
|
+
|
|
36
|
+
- id: php-include-variable
|
|
37
|
+
name: include with a variable path
|
|
38
|
+
pattern: '\b(?:include|require)(?:_once)?\s*\(\s*\$'
|
|
39
|
+
message: "include/require with variable path — risk of LFI/RFI if attacker controls the path"
|
|
40
|
+
severity: high
|
|
41
|
+
category: security
|
|
42
|
+
languages: [php]
|
|
43
|
+
cwe: CWE-98
|
|
44
|
+
confidence: 0.6
|
|
45
|
+
recommendation: "Whitelist allowed paths, or build the path from an allowlist of identifiers."
|
|
46
|
+
|
|
47
|
+
- id: php-error-reporting-display
|
|
48
|
+
name: display_errors enabled
|
|
49
|
+
pattern: "display_errors[^=]*=\\s*['\"]?(?:1|on|true)"
|
|
50
|
+
message: "display_errors leaks stack traces and paths to users in production"
|
|
51
|
+
severity: medium
|
|
52
|
+
category: security
|
|
53
|
+
languages: [php]
|
|
54
|
+
cwe: CWE-209
|
|
55
|
+
confidence: 0.7
|
|
56
|
+
recommendation: "Set display_errors = Off in production; log errors to a file instead."
|
|
57
|
+
|
|
58
|
+
- id: php-suppress-error
|
|
59
|
+
name: Error suppression operator
|
|
60
|
+
pattern: '@\w'
|
|
61
|
+
message: "@ suppresses errors silently — fix the underlying issue or handle it explicitly"
|
|
62
|
+
severity: low
|
|
63
|
+
category: suspicious
|
|
64
|
+
languages: [php]
|
|
65
|
+
confidence: 0.5
|
|
66
|
+
recommendation: "Use try/catch or check the precondition; @ hides bugs."
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# PHP structural patterns (ast-grep, Tier 2).
|
|
2
|
+
|
|
3
|
+
- id: php-var-dump-debug
|
|
4
|
+
name: var_dump debug leftover
|
|
5
|
+
structural_pattern: 'var_dump($X)'
|
|
6
|
+
message: "var_dump($X) — debug leftover, remove before commit"
|
|
7
|
+
severity: low
|
|
8
|
+
category: style
|
|
9
|
+
languages: [php]
|
|
10
|
+
confidence: 0.85
|
|
11
|
+
tags: [debug]
|
|
12
|
+
explanation: >
|
|
13
|
+
``var_dump`` writes raw debug output to the current output stream,
|
|
14
|
+
typically into the page response in web contexts. Often committed
|
|
15
|
+
accidentally during local debugging.
|
|
16
|
+
recommendation: "Remove the var_dump or route through your logger."
|
|
17
|
+
|
|
18
|
+
- id: php-print-r-debug
|
|
19
|
+
name: print_r debug leftover
|
|
20
|
+
structural_pattern: 'print_r($X)'
|
|
21
|
+
message: "print_r($X) — debug leftover, remove before commit"
|
|
22
|
+
severity: low
|
|
23
|
+
category: style
|
|
24
|
+
languages: [php]
|
|
25
|
+
confidence: 0.7
|
|
26
|
+
tags: [debug]
|
|
27
|
+
recommendation: "Remove the print_r or route through your logger."
|
|
28
|
+
|
|
29
|
+
- id: php-die-with-message
|
|
30
|
+
name: die() / exit() with debug message
|
|
31
|
+
structural_pattern: 'die($X)'
|
|
32
|
+
message: "die($X) — terminates request, often a debug statement that escaped"
|
|
33
|
+
severity: medium
|
|
34
|
+
category: suspicious
|
|
35
|
+
languages: [php]
|
|
36
|
+
confidence: 0.5
|
|
37
|
+
explanation: >
|
|
38
|
+
``die`` and ``exit`` halt the current request with the given output.
|
|
39
|
+
Useful in error handlers and CLI scripts; often a leftover debug
|
|
40
|
+
statement when found mid-handler.
|
|
41
|
+
recommendation: "Throw an exception so the framework can render an error page."
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Python performance antipatterns
|
|
2
|
+
|
|
3
|
+
- id: py-string-concat-loop
|
|
4
|
+
name: String concatenation in loop
|
|
5
|
+
pattern: '\w+\s*\+=\s*[''"]'
|
|
6
|
+
message: "String concatenation in loop creates N intermediate strings"
|
|
7
|
+
severity: low
|
|
8
|
+
category: performance
|
|
9
|
+
languages: [python]
|
|
10
|
+
confidence: 0.5
|
|
11
|
+
explanation: >
|
|
12
|
+
Python strings are immutable. Concatenation with += creates a new string
|
|
13
|
+
object each iteration, copying all previous content. For N iterations,
|
|
14
|
+
this is O(N^2) total characters copied.
|
|
15
|
+
recommendation: "Collect into a list and use ''.join(parts) at the end"
|
|
16
|
+
examples:
|
|
17
|
+
- bad: "result = ''\nfor item in items:\n result += str(item)"
|
|
18
|
+
good: "result = ''.join(str(item) for item in items)"
|
|
19
|
+
explanation: "join() pre-calculates total size and copies once"
|
|
20
|
+
|
|
21
|
+
- id: py-mutable-default-arg
|
|
22
|
+
name: Mutable default argument
|
|
23
|
+
pattern: 'def\s+\w+\s*\([^)]*(?:=\s*\[\]|=\s*\{\}|=\s*set\(\))'
|
|
24
|
+
message: "Mutable default argument — shared across all calls"
|
|
25
|
+
severity: medium
|
|
26
|
+
category: correctness
|
|
27
|
+
languages: [python]
|
|
28
|
+
confidence: 0.85
|
|
29
|
+
explanation: >
|
|
30
|
+
Default mutable arguments (list, dict, set) are evaluated once at function
|
|
31
|
+
definition time, not at each call. All calls that use the default share the
|
|
32
|
+
same object, leading to surprising mutation bugs.
|
|
33
|
+
recommendation: "Use None as default and create inside function: if arg is None: arg = []"
|
|
34
|
+
examples:
|
|
35
|
+
- bad: "def add(item, items=[]):\n items.append(item)\n return items"
|
|
36
|
+
good: "def add(item, items=None):\n if items is None:\n items = []\n items.append(item)\n return items"
|
|
37
|
+
|
|
38
|
+
- id: py-dict-keys-iteration
|
|
39
|
+
name: Iterating dict.keys() unnecessarily
|
|
40
|
+
pattern: 'for\s+\w+\s+in\s+\w+\.keys\(\)\s*:'
|
|
41
|
+
message: "Iterating .keys() is redundant — iterate the dict directly"
|
|
42
|
+
severity: info
|
|
43
|
+
category: style
|
|
44
|
+
languages: [python]
|
|
45
|
+
confidence: 0.9
|
|
46
|
+
recommendation: "Use 'for key in my_dict:' instead of 'for key in my_dict.keys():'"
|
|
47
|
+
examples:
|
|
48
|
+
- bad: "for key in config.keys():"
|
|
49
|
+
good: "for key in config:"
|
|
50
|
+
|
|
51
|
+
- id: py-isinstance-chain
|
|
52
|
+
name: Long isinstance chain
|
|
53
|
+
pattern: 'isinstance\s*\([^)]+\)\s*(?:and|or)\s*isinstance'
|
|
54
|
+
message: "Chained isinstance calls — consider match/case or dict dispatch"
|
|
55
|
+
severity: low
|
|
56
|
+
category: complexity
|
|
57
|
+
languages: [python]
|
|
58
|
+
confidence: 0.6
|
|
59
|
+
explanation: >
|
|
60
|
+
Long isinstance chains are hard to read and maintain. Python 3.10+
|
|
61
|
+
match/case provides cleaner structural pattern matching, or use a
|
|
62
|
+
dispatch dict for handler routing.
|
|
63
|
+
recommendation: "Use match/case (3.10+) or a type->handler dict"
|
|
64
|
+
|
|
65
|
+
- id: py-global-import-in-function
|
|
66
|
+
name: Import inside function
|
|
67
|
+
pattern: '^\s{4,}import\s+\w+'
|
|
68
|
+
message: "Import inside function — runs on every call (acceptable for optional deps)"
|
|
69
|
+
severity: info
|
|
70
|
+
category: performance
|
|
71
|
+
languages: [python]
|
|
72
|
+
confidence: 0.4
|
|
73
|
+
recommendation: "Move to top of file unless it's intentionally lazy for optional dependencies"
|
|
74
|
+
|
|
75
|
+
- id: py-bare-except
|
|
76
|
+
name: Bare except clause
|
|
77
|
+
pattern: 'except\s*:'
|
|
78
|
+
message: "Bare except catches SystemExit, KeyboardInterrupt — too broad"
|
|
79
|
+
severity: medium
|
|
80
|
+
category: correctness
|
|
81
|
+
languages: [python]
|
|
82
|
+
confidence: 0.9
|
|
83
|
+
explanation: >
|
|
84
|
+
A bare 'except:' clause catches everything including SystemExit (sys.exit)
|
|
85
|
+
and KeyboardInterrupt (Ctrl+C), making it impossible to stop the program
|
|
86
|
+
normally.
|
|
87
|
+
recommendation: "Use 'except Exception:' to exclude system-level exceptions"
|
|
88
|
+
examples:
|
|
89
|
+
- bad: "try:\n risky()\nexcept:\n pass"
|
|
90
|
+
good: "try:\n risky()\nexcept Exception as e:\n logger.error(e)"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Python structural patterns (ast-grep, Tier 2).
|
|
2
|
+
#
|
|
3
|
+
# These complement the regex-based rules in ``performance.yaml`` —
|
|
4
|
+
# patterns that are awkward or imprecise as regex but trivial as AST.
|
|
5
|
+
|
|
6
|
+
- id: py-debug-print-leftover
|
|
7
|
+
name: Debug print left in source
|
|
8
|
+
structural_pattern: 'print($X)'
|
|
9
|
+
message: "Debug print($X) left in source — remove before commit or switch to logger"
|
|
10
|
+
severity: low
|
|
11
|
+
category: style
|
|
12
|
+
languages: [python]
|
|
13
|
+
confidence: 0.35
|
|
14
|
+
tags: [debug]
|
|
15
|
+
explanation: >
|
|
16
|
+
A bare ``print()`` is fine in scripts and CLI tools but usually
|
|
17
|
+
indicates a debug statement when found inside libraries or service
|
|
18
|
+
code. Easy to leave behind during quick iteration.
|
|
19
|
+
recommendation: "Remove the print or replace with logging.debug/info"
|
|
20
|
+
examples:
|
|
21
|
+
- bad: "def handle(req):\n print(req)\n return process(req)"
|
|
22
|
+
good: "logger.debug('handling %s', req)"
|
|
23
|
+
explanation: "Use the standard logging module so verbosity can be controlled at deploy time."
|
|
24
|
+
|
|
25
|
+
- id: py-assert-in-non-test
|
|
26
|
+
name: Plain assert outside tests
|
|
27
|
+
structural_pattern: 'assert $X'
|
|
28
|
+
message: "assert $X — stripped when Python runs with -O; use explicit checks in production"
|
|
29
|
+
severity: medium
|
|
30
|
+
category: correctness
|
|
31
|
+
languages: [python]
|
|
32
|
+
confidence: 0.5
|
|
33
|
+
explanation: >
|
|
34
|
+
``assert`` is removed when the interpreter runs with ``-O``. Tests
|
|
35
|
+
and dev-time invariants are fine; production code paths that rely
|
|
36
|
+
on the check (input validation, postconditions) silently lose their
|
|
37
|
+
guard.
|
|
38
|
+
recommendation: "Raise an explicit exception (ValueError, AssertionError) instead of assert."
|
|
39
|
+
|
|
40
|
+
- id: py-blocking-sleep
|
|
41
|
+
name: Blocking time.sleep call
|
|
42
|
+
structural_pattern: 'time.sleep($X)'
|
|
43
|
+
message: "time.sleep($X) blocks the thread — wrong inside async code or hot loops"
|
|
44
|
+
severity: low
|
|
45
|
+
category: performance
|
|
46
|
+
languages: [python]
|
|
47
|
+
confidence: 0.5
|
|
48
|
+
explanation: >
|
|
49
|
+
``time.sleep`` blocks the thread. Inside ``async def`` functions
|
|
50
|
+
use ``await asyncio.sleep`` instead so the event loop can do work.
|
|
51
|
+
recommendation: "Use asyncio.sleep in async code; reserve time.sleep for sync scripts and tests."
|
|
52
|
+
examples:
|
|
53
|
+
- bad: "async def poll():\n time.sleep(1)"
|
|
54
|
+
good: "async def poll():\n await asyncio.sleep(1)"
|
|
55
|
+
explanation: "Frees the event loop while waiting."
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Ruby security and correctness rules (Tier 1 regex).
|
|
2
|
+
|
|
3
|
+
- id: ruby-yaml-load-untrusted
|
|
4
|
+
name: YAML.load on untrusted input
|
|
5
|
+
pattern: '\bYAML\.load\b'
|
|
6
|
+
message: "YAML.load can deserialize arbitrary objects — use YAML.safe_load instead"
|
|
7
|
+
severity: high
|
|
8
|
+
category: security
|
|
9
|
+
languages: [ruby]
|
|
10
|
+
cwe: CWE-502
|
|
11
|
+
confidence: 0.85
|
|
12
|
+
explanation: >
|
|
13
|
+
``YAML.load`` instantiates whatever Ruby classes appear in the
|
|
14
|
+
document, allowing attackers to construct objects with side effects
|
|
15
|
+
or to gain code execution via gadget chains.
|
|
16
|
+
recommendation: "Use YAML.safe_load(data) — restricts to a small set of safe types."
|
|
17
|
+
|
|
18
|
+
- id: ruby-marshal-load-untrusted
|
|
19
|
+
name: Marshal.load on untrusted input
|
|
20
|
+
pattern: '\bMarshal\.load\b'
|
|
21
|
+
message: "Marshal.load deserializes arbitrary Ruby objects — never call on untrusted input"
|
|
22
|
+
severity: critical
|
|
23
|
+
category: security
|
|
24
|
+
languages: [ruby]
|
|
25
|
+
cwe: CWE-502
|
|
26
|
+
confidence: 0.9
|
|
27
|
+
recommendation: "Use a structured format (JSON, MessagePack) for untrusted data."
|
|
28
|
+
|
|
29
|
+
- id: ruby-send-with-user-input
|
|
30
|
+
name: .send/.public_send with non-literal method name
|
|
31
|
+
pattern: '\.(?:public_)?send\s*\(\s*[^"'']'
|
|
32
|
+
message: "send with dynamic method name — risk of invoking arbitrary methods"
|
|
33
|
+
severity: medium
|
|
34
|
+
category: security
|
|
35
|
+
languages: [ruby]
|
|
36
|
+
cwe: CWE-470
|
|
37
|
+
confidence: 0.5
|
|
38
|
+
recommendation: "Whitelist allowed method names, or refactor to explicit dispatch."
|
|
39
|
+
|
|
40
|
+
- id: ruby-where-string-interpolation
|
|
41
|
+
name: ActiveRecord .where with string interpolation
|
|
42
|
+
pattern: '\.where\s*\(\s*["''][^"'']*#\{'
|
|
43
|
+
message: ".where(\"...#{var}...\") — SQL injection risk; use placeholders"
|
|
44
|
+
severity: high
|
|
45
|
+
category: security
|
|
46
|
+
languages: [ruby]
|
|
47
|
+
cwe: CWE-89
|
|
48
|
+
confidence: 0.85
|
|
49
|
+
recommendation: "Use .where(\"col = ?\", value) or .where(col: value) to parameterize."
|
|
50
|
+
examples:
|
|
51
|
+
- bad: 'User.where("name = #{params[:name]}")'
|
|
52
|
+
good: 'User.where("name = ?", params[:name])'
|
|
53
|
+
explanation: "Placeholder syntax escapes the value through ActiveRecord."
|
|
54
|
+
|
|
55
|
+
- id: ruby-rescue-bare
|
|
56
|
+
name: Bare rescue catches everything
|
|
57
|
+
pattern: '^\s*rescue\s*(?:=>|\n|$)'
|
|
58
|
+
message: "Bare rescue catches StandardError and below — usually too broad"
|
|
59
|
+
severity: medium
|
|
60
|
+
category: correctness
|
|
61
|
+
languages: [ruby]
|
|
62
|
+
confidence: 0.55
|
|
63
|
+
recommendation: "Catch specific exception classes (rescue Net::HTTPError => e)."
|
|
64
|
+
|
|
65
|
+
- id: ruby-update-without-bang
|
|
66
|
+
name: ActiveRecord .update return value ignored
|
|
67
|
+
pattern: '\.(?:update|save)(?:\([^)]*\))?\s*$'
|
|
68
|
+
message: ".update / .save without ! returns false on failure — check the result or use the bang variant"
|
|
69
|
+
severity: low
|
|
70
|
+
category: correctness
|
|
71
|
+
languages: [ruby]
|
|
72
|
+
confidence: 0.4
|
|
73
|
+
recommendation: "Use .update! / .save! to raise on failure, or check the return value."
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Ruby structural patterns (ast-grep, Tier 2).
|
|
2
|
+
|
|
3
|
+
- id: ruby-puts-debug
|
|
4
|
+
name: puts debug leftover
|
|
5
|
+
structural_pattern: 'puts $X'
|
|
6
|
+
message: "puts $X — debug leftover, use Rails.logger.debug or remove"
|
|
7
|
+
severity: low
|
|
8
|
+
category: style
|
|
9
|
+
languages: [ruby]
|
|
10
|
+
confidence: 0.35
|
|
11
|
+
tags: [debug]
|
|
12
|
+
explanation: >
|
|
13
|
+
Bare ``puts`` writes to stdout with no level filtering. In Rails
|
|
14
|
+
apps prefer ``Rails.logger.debug`` so output respects the configured
|
|
15
|
+
log level and is captured in production logs.
|
|
16
|
+
recommendation: "Use Rails.logger.debug \"...\" or remove if it was a debug aid."
|
|
17
|
+
|
|
18
|
+
- id: ruby-pp-debug
|
|
19
|
+
name: pp / p debug leftover
|
|
20
|
+
structural_pattern: 'pp $X'
|
|
21
|
+
message: "pp $X — pretty-print debug leftover, remove before commit"
|
|
22
|
+
severity: low
|
|
23
|
+
category: style
|
|
24
|
+
languages: [ruby]
|
|
25
|
+
confidence: 0.7
|
|
26
|
+
tags: [debug]
|
|
27
|
+
recommendation: "Remove the pp call or route through Rails.logger.debug."
|
|
28
|
+
|
|
29
|
+
- id: ruby-binding-pry
|
|
30
|
+
name: binding.pry / debugger left in code
|
|
31
|
+
structural_pattern: 'binding.pry'
|
|
32
|
+
message: "binding.pry — interactive debugger left in code; will hang in production"
|
|
33
|
+
severity: high
|
|
34
|
+
category: correctness
|
|
35
|
+
languages: [ruby]
|
|
36
|
+
confidence: 0.95
|
|
37
|
+
tags: [debug]
|
|
38
|
+
explanation: >
|
|
39
|
+
``binding.pry`` opens an interactive REPL. In production this hangs
|
|
40
|
+
the request waiting for stdin. Should never be committed.
|
|
41
|
+
recommendation: "Remove the binding.pry call before committing."
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Rust correctness and performance patterns
|
|
2
|
+
|
|
3
|
+
- id: rs-unwrap-usage
|
|
4
|
+
name: Unwrap without context
|
|
5
|
+
pattern: '\.unwrap\(\)'
|
|
6
|
+
message: "unwrap() panics on None/Err — use expect() or proper error handling"
|
|
7
|
+
severity: medium
|
|
8
|
+
category: correctness
|
|
9
|
+
languages: [rust]
|
|
10
|
+
confidence: 0.7
|
|
11
|
+
explanation: >
|
|
12
|
+
unwrap() provides no context on panic. In production code, use
|
|
13
|
+
expect("reason") for intentional panics or ? for propagation.
|
|
14
|
+
recommendation: "Use .expect('context') or the ? operator"
|
|
15
|
+
examples:
|
|
16
|
+
- bad: "let value = result.unwrap();"
|
|
17
|
+
good: 'let value = result.expect("config must be valid");'
|
|
18
|
+
|
|
19
|
+
- id: rs-clone-in-loop
|
|
20
|
+
name: Clone in hot loop
|
|
21
|
+
pattern: '\.clone\(\)'
|
|
22
|
+
message: "clone() in potential hot path — deep copy may be expensive"
|
|
23
|
+
severity: low
|
|
24
|
+
category: performance
|
|
25
|
+
languages: [rust]
|
|
26
|
+
confidence: 0.4
|
|
27
|
+
recommendation: "Use references or Cow<T> to avoid unnecessary cloning"
|
|
28
|
+
|
|
29
|
+
- id: rs-todo-macro
|
|
30
|
+
name: todo!() macro left in code
|
|
31
|
+
pattern: 'todo!\s*\('
|
|
32
|
+
message: "todo!() panics at runtime — unfinished implementation"
|
|
33
|
+
severity: high
|
|
34
|
+
category: correctness
|
|
35
|
+
languages: [rust]
|
|
36
|
+
confidence: 0.95
|
|
37
|
+
recommendation: "Implement the missing functionality or use unimplemented!() with a tracking issue"
|
|
38
|
+
|
|
39
|
+
- id: rs-unsafe-block
|
|
40
|
+
name: Unsafe block usage
|
|
41
|
+
pattern: 'unsafe\s*\{'
|
|
42
|
+
message: "unsafe block — verify memory safety invariants"
|
|
43
|
+
severity: medium
|
|
44
|
+
category: security
|
|
45
|
+
languages: [rust]
|
|
46
|
+
confidence: 0.8
|
|
47
|
+
cwe: CWE-119
|
|
48
|
+
explanation: >
|
|
49
|
+
Unsafe blocks disable Rust's borrow checker guarantees. Every unsafe
|
|
50
|
+
block should have a SAFETY comment explaining why it's correct.
|
|
51
|
+
recommendation: "Add a // SAFETY: comment and consider safe alternatives"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Rust structural patterns (ast-grep, Tier 2).
|
|
2
|
+
#
|
|
3
|
+
# IDs picked to avoid collision with the regex rules in
|
|
4
|
+
# ``correctness.yaml`` (rs-unwrap-usage, rs-todo-macro). These are
|
|
5
|
+
# precision-better restatements via the AST.
|
|
6
|
+
|
|
7
|
+
- id: rs-expect-call
|
|
8
|
+
name: .expect() with hardcoded message
|
|
9
|
+
structural_pattern: '$X.expect($MSG)'
|
|
10
|
+
message: ".expect($MSG) on $X panics on None/Err — make sure $MSG is informative"
|
|
11
|
+
severity: low
|
|
12
|
+
category: correctness
|
|
13
|
+
languages: [rust]
|
|
14
|
+
confidence: 0.4
|
|
15
|
+
explanation: >
|
|
16
|
+
``.expect("…")`` is preferable to ``.unwrap()`` because the message
|
|
17
|
+
surfaces the violated invariant. This rule flags every use so you
|
|
18
|
+
can audit whether the message actually helps debugging — terse
|
|
19
|
+
placeholders ("oops", "fail") are worse than nothing.
|
|
20
|
+
recommendation: "Make the expect message describe the precondition that should hold."
|
|
21
|
+
|
|
22
|
+
- id: rs-debug-println
|
|
23
|
+
name: Debug println! left in source
|
|
24
|
+
structural_pattern: 'println!($X)'
|
|
25
|
+
message: "println!($X) left in source — switch to log/tracing or remove"
|
|
26
|
+
severity: low
|
|
27
|
+
category: style
|
|
28
|
+
languages: [rust]
|
|
29
|
+
confidence: 0.35
|
|
30
|
+
tags: [debug]
|
|
31
|
+
explanation: >
|
|
32
|
+
``println!`` writes straight to stdout and is unfilterable. Use
|
|
33
|
+
``log::info!`` or ``tracing::info!`` so output respects log levels
|
|
34
|
+
and structured logging.
|
|
35
|
+
recommendation: "Use tracing::info! / log::info! macros (or remove if it was a debug aid)."
|
|
36
|
+
|
|
37
|
+
- id: rs-dbg-macro
|
|
38
|
+
name: dbg!() macro left in source
|
|
39
|
+
structural_pattern: 'dbg!($X)'
|
|
40
|
+
message: "dbg!($X) — debug macro that prints to stderr, remove before commit"
|
|
41
|
+
severity: low
|
|
42
|
+
category: style
|
|
43
|
+
languages: [rust]
|
|
44
|
+
confidence: 0.85
|
|
45
|
+
tags: [debug]
|
|
46
|
+
explanation: >
|
|
47
|
+
``dbg!`` is a debug aid that prints the file/line and value to stderr.
|
|
48
|
+
Convenient during local iteration; should not survive into mainline.
|
|
49
|
+
recommendation: "Remove the dbg! macro before committing."
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# TypeScript/JavaScript performance and correctness patterns
|
|
2
|
+
|
|
3
|
+
- id: ts-await-in-loop
|
|
4
|
+
name: Sequential await in loop
|
|
5
|
+
pattern: '^\s+(?:const|let|var)\s+\w+\s*=\s*await\s'
|
|
6
|
+
message: "Possible sequential await in loop — requests may execute one at a time"
|
|
7
|
+
severity: medium
|
|
8
|
+
category: performance
|
|
9
|
+
languages: [typescript, javascript]
|
|
10
|
+
confidence: 0.55
|
|
11
|
+
explanation: >
|
|
12
|
+
Using await inside a for loop makes each iteration wait for the previous
|
|
13
|
+
one to complete. If the operations are independent, they can run in
|
|
14
|
+
parallel with Promise.all(), potentially reducing total time by N×.
|
|
15
|
+
recommendation: "Collect promises and use Promise.all() for independent operations"
|
|
16
|
+
examples:
|
|
17
|
+
- bad: "for (const id of ids) {\n const data = await fetch(id);\n}"
|
|
18
|
+
good: "const results = await Promise.all(ids.map(id => fetch(id)));"
|
|
19
|
+
explanation: "Promise.all runs all fetches concurrently"
|
|
20
|
+
|
|
21
|
+
- id: ts-no-optional-chain
|
|
22
|
+
name: Nested null checks instead of optional chaining
|
|
23
|
+
pattern: '(\w+)\s*&&\s*\1\.\w+\s*&&\s*\1\.\w+\.\w+'
|
|
24
|
+
message: "Nested && null checks — use optional chaining (?.)"
|
|
25
|
+
severity: info
|
|
26
|
+
category: style
|
|
27
|
+
languages: [typescript, javascript]
|
|
28
|
+
confidence: 0.7
|
|
29
|
+
recommendation: "Use optional chaining: obj?.prop?.nested"
|
|
30
|
+
examples:
|
|
31
|
+
- bad: "if (user && user.address && user.address.city)"
|
|
32
|
+
good: "if (user?.address?.city)"
|
|
33
|
+
|
|
34
|
+
- id: ts-array-push-spread
|
|
35
|
+
name: Array.push with spread in loop
|
|
36
|
+
pattern: '\.push\(\.\.\.'
|
|
37
|
+
message: "Array.push(...spread) can hit call stack limit for large arrays"
|
|
38
|
+
severity: medium
|
|
39
|
+
category: correctness
|
|
40
|
+
languages: [typescript, javascript]
|
|
41
|
+
confidence: 0.7
|
|
42
|
+
explanation: >
|
|
43
|
+
Array.push(...largeArray) passes each element as a function argument.
|
|
44
|
+
JavaScript engines have a maximum argument count (~65k-130k), so this
|
|
45
|
+
throws RangeError for large arrays.
|
|
46
|
+
recommendation: "Use Array.prototype.push.apply() or concat()"
|
|
47
|
+
examples:
|
|
48
|
+
- bad: "result.push(...bigArray)"
|
|
49
|
+
good: "for (const item of bigArray) result.push(item)"
|
|
50
|
+
|
|
51
|
+
- id: ts-console-log
|
|
52
|
+
name: console.log in production code
|
|
53
|
+
pattern: 'console\.log\s*\('
|
|
54
|
+
message: "console.log left in code — use proper logging or remove"
|
|
55
|
+
severity: info
|
|
56
|
+
category: style
|
|
57
|
+
languages: [typescript, javascript]
|
|
58
|
+
confidence: 0.35
|
|
59
|
+
tags: [debug]
|
|
60
|
+
recommendation: "Use a structured logger or remove debug statements"
|
|
61
|
+
|
|
62
|
+
- id: ts-any-type
|
|
63
|
+
name: TypeScript any type usage
|
|
64
|
+
pattern: ':\s*any\b'
|
|
65
|
+
message: "Explicit 'any' type — loses type safety"
|
|
66
|
+
severity: low
|
|
67
|
+
category: style
|
|
68
|
+
languages: [typescript]
|
|
69
|
+
confidence: 0.6
|
|
70
|
+
recommendation: "Use specific types, unknown, or generics instead of any"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# TypeScript structural patterns (ast-grep, Tier 2).
|
|
2
|
+
|
|
3
|
+
- id: ts-console-log-leftover
|
|
4
|
+
name: console.log left in source
|
|
5
|
+
structural_pattern: 'console.log($X)'
|
|
6
|
+
message: "console.log($X) left in source — remove or route through a logger"
|
|
7
|
+
severity: low
|
|
8
|
+
category: style
|
|
9
|
+
languages: [typescript, javascript]
|
|
10
|
+
confidence: 0.35
|
|
11
|
+
tags: [debug]
|
|
12
|
+
explanation: >
|
|
13
|
+
Bare ``console.log`` survives into production builds, leaks
|
|
14
|
+
information into the browser console, and bypasses any logging
|
|
15
|
+
pipeline. Use a structured logger or remove the line.
|
|
16
|
+
recommendation: "Use the project's logger; for browser code prefer console.debug behind a flag."
|
|
17
|
+
examples:
|
|
18
|
+
- bad: "function handle(req) { console.log(req); return process(req); }"
|
|
19
|
+
good: "logger.debug({ req }, 'handle');"
|
|
20
|
+
explanation: "Structured loggers support levels and shipping."
|
|
21
|
+
|
|
22
|
+
- id: ts-non-null-assertion
|
|
23
|
+
name: Non-null assertion operator
|
|
24
|
+
structural_pattern: '$X!'
|
|
25
|
+
message: "Non-null assertion ($X!) bypasses the type checker — prove the invariant or guard explicitly"
|
|
26
|
+
severity: low
|
|
27
|
+
category: suspicious
|
|
28
|
+
languages: [typescript]
|
|
29
|
+
confidence: 0.4
|
|
30
|
+
explanation: >
|
|
31
|
+
The ``!`` operator silences the compiler without checking. When the
|
|
32
|
+
value is null at runtime you get an unhelpful TypeError. Either
|
|
33
|
+
refactor so the type narrows naturally, or add an explicit guard.
|
|
34
|
+
recommendation: "Use a runtime check (if (!x) throw …) or refactor the type."
|
|
35
|
+
|
|
36
|
+
- id: ts-set-timeout-zero
|
|
37
|
+
name: setTimeout($X, 0) workaround
|
|
38
|
+
structural_pattern: 'setTimeout($X, 0)'
|
|
39
|
+
message: "setTimeout($X, 0) is a microtask hack — queueMicrotask is clearer intent"
|
|
40
|
+
severity: info
|
|
41
|
+
category: style
|
|
42
|
+
languages: [typescript, javascript]
|
|
43
|
+
confidence: 0.6
|
|
44
|
+
explanation: >
|
|
45
|
+
``setTimeout(fn, 0)`` defers ``fn`` until after the current macro
|
|
46
|
+
task. ``queueMicrotask(fn)`` schedules sooner (after the current
|
|
47
|
+
sync code) and signals intent without the magic ``0``.
|
|
48
|
+
recommendation: "Use queueMicrotask(fn) when you want to defer until after sync work."
|