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,724 @@
|
|
|
1
|
+
"""Security scanning pattern definitions.
|
|
2
|
+
|
|
3
|
+
High-confidence patterns for secret detection and code anti-pattern
|
|
4
|
+
recognition, each tagged with a CWE ID and severity level.
|
|
5
|
+
|
|
6
|
+
NOTE: The regex patterns in this file are DETECTORS — they match
|
|
7
|
+
dangerous constructs in scanned code to flag them for review.
|
|
8
|
+
The patterns themselves do not execute any dangerous operations.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import re
|
|
14
|
+
from dataclasses import dataclass, field
|
|
15
|
+
from enum import StrEnum
|
|
16
|
+
|
|
17
|
+
from attocode_intel._internal.types.severity import Severity
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Category(StrEnum):
|
|
21
|
+
SECRET = "secret"
|
|
22
|
+
ANTI_PATTERN = "anti_pattern"
|
|
23
|
+
DEPENDENCY = "dependency"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
@dataclass(slots=True)
|
|
27
|
+
class SecurityPattern:
|
|
28
|
+
"""A single security scanning pattern."""
|
|
29
|
+
|
|
30
|
+
name: str
|
|
31
|
+
pattern: re.Pattern[str]
|
|
32
|
+
severity: Severity
|
|
33
|
+
category: Category
|
|
34
|
+
cwe_id: str
|
|
35
|
+
message: str
|
|
36
|
+
recommendation: str
|
|
37
|
+
languages: list[str] = field(default_factory=list) # empty = all languages
|
|
38
|
+
scan_comments: bool = False # if True, scan comment lines too (for stego payloads)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
# ---------------------------------------------------------------------------
|
|
42
|
+
# Secret detection patterns
|
|
43
|
+
# ---------------------------------------------------------------------------
|
|
44
|
+
|
|
45
|
+
_SECRET_DEFS: list[tuple[str, str, str, str, str, str]] = [
|
|
46
|
+
# (name, regex, severity, cwe, message, recommendation)
|
|
47
|
+
("generic_api_key",
|
|
48
|
+
r"""(?:api[_-]?key|apikey)\s*[:=]\s*['"]([a-zA-Z0-9_\-]{20,})['"]""",
|
|
49
|
+
"high", "CWE-798",
|
|
50
|
+
"Hardcoded API key detected",
|
|
51
|
+
"Use environment variables or a secrets manager"),
|
|
52
|
+
("openai_key",
|
|
53
|
+
r"""sk-(?:proj-)?[a-zA-Z0-9_-]{20,}""",
|
|
54
|
+
"critical", "CWE-798",
|
|
55
|
+
"OpenAI API key (sk-...) detected",
|
|
56
|
+
"Move to OPENAI_API_KEY environment variable"),
|
|
57
|
+
("anthropic_key",
|
|
58
|
+
r"""sk-ant-[a-zA-Z0-9\-]{20,}""",
|
|
59
|
+
"critical", "CWE-798",
|
|
60
|
+
"Anthropic API key (sk-ant-...) detected",
|
|
61
|
+
"Move to ANTHROPIC_API_KEY environment variable"),
|
|
62
|
+
("github_token",
|
|
63
|
+
r"""ghp_[a-zA-Z0-9]{36}""",
|
|
64
|
+
"critical", "CWE-798",
|
|
65
|
+
"GitHub personal access token detected",
|
|
66
|
+
"Use GITHUB_TOKEN environment variable"),
|
|
67
|
+
("github_oauth",
|
|
68
|
+
r"""gho_[a-zA-Z0-9]{36}""",
|
|
69
|
+
"high", "CWE-798",
|
|
70
|
+
"GitHub OAuth token detected",
|
|
71
|
+
"Use environment variable or OAuth flow"),
|
|
72
|
+
("aws_access_key",
|
|
73
|
+
r"""AKIA[0-9A-Z]{16}""",
|
|
74
|
+
"critical", "CWE-798",
|
|
75
|
+
"AWS access key ID detected",
|
|
76
|
+
"Use IAM roles or AWS_ACCESS_KEY_ID env var"),
|
|
77
|
+
("aws_secret_key",
|
|
78
|
+
r"""(?:aws_secret_access_key|secret_key)\s*[:=]\s*['"]([a-zA-Z0-9/+=]{40})['"]""",
|
|
79
|
+
"critical", "CWE-798",
|
|
80
|
+
"AWS secret access key detected",
|
|
81
|
+
"Use IAM roles or AWS_SECRET_ACCESS_KEY env var"),
|
|
82
|
+
("private_key",
|
|
83
|
+
r"""-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----""",
|
|
84
|
+
"critical", "CWE-321",
|
|
85
|
+
"Private key embedded in source code",
|
|
86
|
+
"Store keys in a secure vault, never commit to source control"),
|
|
87
|
+
("bearer_token",
|
|
88
|
+
r"""(?:bearer|token|auth)\s*[:=]\s*['"]([a-zA-Z0-9_\-.]{20,})['"]""",
|
|
89
|
+
"medium", "CWE-798",
|
|
90
|
+
"Possible hardcoded bearer/auth token",
|
|
91
|
+
"Use environment variables for authentication tokens"),
|
|
92
|
+
("password_assignment",
|
|
93
|
+
r"""(?:password|passwd|pwd|secret)\s*[:=]\s*['"](?!(?:None|null|''|""|<|{|\*|test|example|placeholder|changeme)\b)[^'"]{8,}['"]""",
|
|
94
|
+
"high", "CWE-798",
|
|
95
|
+
"Possible hardcoded password or secret",
|
|
96
|
+
"Use environment variables or a secrets manager"),
|
|
97
|
+
("jwt_token",
|
|
98
|
+
r"""eyJ[a-zA-Z0-9_-]{10,}\.eyJ[a-zA-Z0-9_-]{10,}\.[a-zA-Z0-9_-]{10,}""",
|
|
99
|
+
"high", "CWE-798",
|
|
100
|
+
"JWT token detected in source code",
|
|
101
|
+
"Never hardcode JWT tokens; generate at runtime"),
|
|
102
|
+
("slack_webhook",
|
|
103
|
+
r"""https://hooks\.slack\.com/services/T[a-zA-Z0-9_]+/B[a-zA-Z0-9_]+/[a-zA-Z0-9_]+""",
|
|
104
|
+
"high", "CWE-798",
|
|
105
|
+
"Slack webhook URL detected",
|
|
106
|
+
"Store webhook URL in environment variable"),
|
|
107
|
+
("connection_string",
|
|
108
|
+
r"""(?:mysql|postgres|postgresql|mongodb|redis)://[^'"\s]{10,}""",
|
|
109
|
+
"high", "CWE-798",
|
|
110
|
+
"Database connection string with possible credentials",
|
|
111
|
+
"Use DATABASE_URL environment variable"),
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
SECRET_PATTERNS: list[SecurityPattern] = [
|
|
115
|
+
SecurityPattern(
|
|
116
|
+
name=name,
|
|
117
|
+
pattern=re.compile(regex, re.IGNORECASE if name not in (
|
|
118
|
+
"openai_key", "anthropic_key", "github_token", "github_oauth",
|
|
119
|
+
"aws_access_key", "private_key", "jwt_token", "slack_webhook",
|
|
120
|
+
) else 0),
|
|
121
|
+
severity=Severity(sev),
|
|
122
|
+
category=Category.SECRET,
|
|
123
|
+
cwe_id=cwe,
|
|
124
|
+
message=msg,
|
|
125
|
+
recommendation=rec,
|
|
126
|
+
)
|
|
127
|
+
for name, regex, sev, cwe, msg, rec in _SECRET_DEFS
|
|
128
|
+
]
|
|
129
|
+
|
|
130
|
+
# ---------------------------------------------------------------------------
|
|
131
|
+
# Code anti-pattern detection (DETECTORS only — these find risky code)
|
|
132
|
+
# ---------------------------------------------------------------------------
|
|
133
|
+
|
|
134
|
+
# These regex patterns DETECT dangerous constructs in scanned source files.
|
|
135
|
+
# They do NOT themselves call or use any dangerous functions.
|
|
136
|
+
_ANTI_PATTERN_DEFS: list[tuple[str, str, str, str, str, str, list[str], bool]] = [
|
|
137
|
+
# (name, regex, severity, cwe, message, recommendation, languages, scan_comments)
|
|
138
|
+
# Python detectors
|
|
139
|
+
("python_dynamic_eval",
|
|
140
|
+
r"""\beval\s*\(""",
|
|
141
|
+
"high", "CWE-95",
|
|
142
|
+
"Dynamic code evaluation detected — code injection risk",
|
|
143
|
+
"Use ast.literal_eval() for data, or avoid dynamic evaluation",
|
|
144
|
+
["python"], False),
|
|
145
|
+
("python_dynamic_exec",
|
|
146
|
+
r"""\bexec\s*\(""",
|
|
147
|
+
"high", "CWE-95",
|
|
148
|
+
"Dynamic code execution detected — code injection risk",
|
|
149
|
+
"Avoid dynamic code execution; use structured alternatives",
|
|
150
|
+
["python"], False),
|
|
151
|
+
("python_shell_true",
|
|
152
|
+
r"""subprocess\.\w+\([^)]*shell\s*=\s*True""",
|
|
153
|
+
"high", "CWE-78",
|
|
154
|
+
"subprocess with shell=True — command injection risk",
|
|
155
|
+
"Use subprocess with shell=False and pass args as list",
|
|
156
|
+
["python"], False),
|
|
157
|
+
("python_shell_true_standalone",
|
|
158
|
+
r"""shell\s*=\s*True""",
|
|
159
|
+
"medium", "CWE-78",
|
|
160
|
+
"shell=True detected — possible command injection risk (check if used with subprocess)",
|
|
161
|
+
"Use subprocess with shell=False and pass args as list",
|
|
162
|
+
["python"], False),
|
|
163
|
+
("python_pickle_loads",
|
|
164
|
+
r"""pickle\.loads?\s*\(""",
|
|
165
|
+
"high", "CWE-502",
|
|
166
|
+
"pickle.load/loads — deserialization of untrusted data risk",
|
|
167
|
+
"Use json or other safe serialization formats",
|
|
168
|
+
["python"], False),
|
|
169
|
+
("python_yaml_unsafe",
|
|
170
|
+
r"""yaml\.load\s*\([^,)]+\)""",
|
|
171
|
+
"medium", "CWE-502",
|
|
172
|
+
"yaml.load() without SafeLoader — arbitrary code execution risk",
|
|
173
|
+
"Use yaml.safe_load() or yaml.load(data, Loader=SafeLoader)",
|
|
174
|
+
["python"], False),
|
|
175
|
+
("python_sql_fstring",
|
|
176
|
+
r"""(?:cursor\.execute|\.execute)\s*\(\s*f['"]""",
|
|
177
|
+
"high", "CWE-89",
|
|
178
|
+
"f-string in SQL query — SQL injection risk",
|
|
179
|
+
"Use parameterized queries with ? or %s placeholders",
|
|
180
|
+
["python"], False),
|
|
181
|
+
("python_verify_false",
|
|
182
|
+
r"""verify\s*=\s*False""",
|
|
183
|
+
"medium", "CWE-295",
|
|
184
|
+
"SSL verification disabled (verify=False)",
|
|
185
|
+
"Enable SSL verification; use a CA bundle if needed",
|
|
186
|
+
["python"], False),
|
|
187
|
+
("python_weak_hash",
|
|
188
|
+
r"""hashlib\.(?:md5|sha1)\s*\(""",
|
|
189
|
+
"low", "CWE-328",
|
|
190
|
+
"Weak hash algorithm (MD5/SHA1) — not suitable for security",
|
|
191
|
+
"Use hashlib.sha256() or hashlib.sha3_256() for security",
|
|
192
|
+
["python"], False),
|
|
193
|
+
("python_tempfile_insecure",
|
|
194
|
+
r"""tempfile\.mktemp\s*\(""",
|
|
195
|
+
"medium", "CWE-377",
|
|
196
|
+
"tempfile.mktemp() — race condition vulnerability",
|
|
197
|
+
"Use tempfile.mkstemp() or tempfile.NamedTemporaryFile()",
|
|
198
|
+
["python"], False),
|
|
199
|
+
# JavaScript/TypeScript detectors
|
|
200
|
+
("js_dynamic_eval",
|
|
201
|
+
r"""\beval\s*\(""",
|
|
202
|
+
"high", "CWE-95",
|
|
203
|
+
"Dynamic code evaluation detected — code injection risk",
|
|
204
|
+
"Avoid dynamic evaluation; use JSON.parse() for data",
|
|
205
|
+
["javascript", "typescript"], False),
|
|
206
|
+
("js_innerhtml",
|
|
207
|
+
r"""\.innerHTML\s*=""",
|
|
208
|
+
"medium", "CWE-79",
|
|
209
|
+
"Direct innerHTML assignment — XSS risk",
|
|
210
|
+
"Use textContent or a DOM sanitizer library",
|
|
211
|
+
["javascript", "typescript"], False),
|
|
212
|
+
("js_dangerously_set",
|
|
213
|
+
r"""dangerouslySetInnerHTML""",
|
|
214
|
+
"medium", "CWE-79",
|
|
215
|
+
"dangerouslySetInnerHTML — XSS risk in React",
|
|
216
|
+
"Sanitize content with DOMPurify before rendering",
|
|
217
|
+
["javascript", "typescript"], False),
|
|
218
|
+
("js_document_write",
|
|
219
|
+
r"""document\.write\s*\(""",
|
|
220
|
+
"medium", "CWE-79",
|
|
221
|
+
"document.write() — XSS risk and bad practice",
|
|
222
|
+
"Use DOM manipulation methods instead",
|
|
223
|
+
["javascript", "typescript"], False),
|
|
224
|
+
# GlassWorm-class supply-chain detectors
|
|
225
|
+
("invisible_unicode_run",
|
|
226
|
+
r"""[\u200B-\u200F\u2060-\u206F\uFE00-\uFE0F]{3,}|(?:[\U000E0000-\U000E007F]|[\U000E0100-\U000E01EF]){3,}""",
|
|
227
|
+
"high", "CWE-506",
|
|
228
|
+
"Run of invisible/non-rendering Unicode characters — possible steganographic payload (supply-chain attack)",
|
|
229
|
+
"Audit with 'hexdump -C' or 'cat -v'; legitimate source should not contain runs of zero-width/variation-selector/tag characters",
|
|
230
|
+
[], True),
|
|
231
|
+
("js_eval_on_decoded",
|
|
232
|
+
r"""\b(?:eval|Function)\s*\(\s*(?:new\s+Function\s*\(\s*)?[^)]*?\b(?:atob|decodeURIComponent|unescape)\s*\(""",
|
|
233
|
+
"critical", "CWE-94",
|
|
234
|
+
"eval/Function() called on decoded data (atob/decodeURIComponent/unescape) — supply-chain obfuscation pattern",
|
|
235
|
+
"Never eval decoded strings; use JSON.parse() for data, or refactor to explicit logic",
|
|
236
|
+
["javascript", "typescript"], False),
|
|
237
|
+
("js_eval_on_buffer",
|
|
238
|
+
r"""\b(?:eval|Function)\s*\(\s*(?:new\s+Function\s*\(\s*)?[^)]*?Buffer\.from\s*\([^)]*?(?:['"]base64['"]|['"]hex['"])""",
|
|
239
|
+
"critical", "CWE-94",
|
|
240
|
+
"eval/Function() called on Buffer.from(..., 'base64'|'hex') decoded data — supply-chain obfuscation pattern",
|
|
241
|
+
"Never eval decoded Buffers; refactor to explicit logic",
|
|
242
|
+
["javascript", "typescript"], False),
|
|
243
|
+
("js_eval_on_fromcharcode",
|
|
244
|
+
r"""\b(?:eval|Function)\s*\(\s*(?:new\s+Function\s*\(\s*)?[^)]*?String\.fromCharCode\s*\(""",
|
|
245
|
+
"critical", "CWE-94",
|
|
246
|
+
"eval/Function() called on String.fromCharCode(...) — classic obfuscation pattern",
|
|
247
|
+
"Never eval char-code sequences; this is almost always malicious",
|
|
248
|
+
["javascript", "typescript"], False),
|
|
249
|
+
("python_eval_on_b64decode",
|
|
250
|
+
r"""\b(?:eval|exec)\s*\(\s*[^)]*?\b(?:b64decode|base64\.b64decode|urlsafe_b64decode)\s*\(""",
|
|
251
|
+
"critical", "CWE-94",
|
|
252
|
+
"eval/exec called on base64.b64decode(...) — supply-chain obfuscation pattern",
|
|
253
|
+
"Never eval decoded data; refactor to explicit logic",
|
|
254
|
+
["python"], False),
|
|
255
|
+
("python_exec_on_codecs_decode",
|
|
256
|
+
r"""\b(?:eval|exec)\s*\(\s*[^)]*?(?:\bcodecs\.decode\s*\(|\bbytes\.fromhex\s*\(|\bzlib\.decompress\s*\()""",
|
|
257
|
+
"critical", "CWE-94",
|
|
258
|
+
"eval/exec called on codecs.decode/bytes.fromhex/zlib.decompress — obfuscation pattern",
|
|
259
|
+
"Never eval decoded/decompressed data; refactor to explicit logic",
|
|
260
|
+
["python"], False),
|
|
261
|
+
("python_exec_on_marshal_loads",
|
|
262
|
+
r"""\b(?:eval|exec)\s*\(\s*[^)]*?\bmarshal\.loads\s*\(""",
|
|
263
|
+
"critical", "CWE-94",
|
|
264
|
+
"eval/exec called on marshal.loads(...) — code injection via deserialization",
|
|
265
|
+
"Never execute marshal-deserialized data from untrusted sources",
|
|
266
|
+
["python"], False),
|
|
267
|
+
# Shai-Hulud / dynamic-require obfuscation: require() with string concatenation
|
|
268
|
+
# or template interpolation — used to evade literal 'child_process' string detection.
|
|
269
|
+
("js_dynamic_require_concat",
|
|
270
|
+
r"""require\s*\(\s*(?:["'][^"']*["']\s*\+|`[^`]*\$\{)""",
|
|
271
|
+
"critical", "CWE-94",
|
|
272
|
+
"require() called with concatenated string or template interpolation — supply-chain obfuscation (Shai-Hulud style)",
|
|
273
|
+
"Use static string literals for require(); dynamic module loading is almost always an obfuscation indicator",
|
|
274
|
+
["javascript", "typescript"], False),
|
|
275
|
+
# MDN explicitly warns that string-argument setTimeout/setInterval behaves like eval().
|
|
276
|
+
# Legitimate callers pass functions; string arguments are near-universally obfuscation.
|
|
277
|
+
("js_settimer_string_arg",
|
|
278
|
+
r"""\b(?:setTimeout|setInterval)\s*\(\s*["'`]""",
|
|
279
|
+
"high", "CWE-95",
|
|
280
|
+
"setTimeout/setInterval called with a string argument — behaves like eval()",
|
|
281
|
+
"Pass a function reference instead of a string; string args are implicit dynamic code execution",
|
|
282
|
+
["javascript", "typescript"], False),
|
|
283
|
+
# -----------------------------------------------------------------------
|
|
284
|
+
# Additional OWASP Top 10 detectors (Python)
|
|
285
|
+
# -----------------------------------------------------------------------
|
|
286
|
+
("python_sql_format_string",
|
|
287
|
+
r"""\b(?:cursor\.execute|\.execute)\s*\(\s*['"].*?%[sd]""",
|
|
288
|
+
"high", "CWE-89",
|
|
289
|
+
"SQL query uses %-formatting — SQL injection risk",
|
|
290
|
+
"Use parameterized queries with ? or %s placeholders instead of string formatting",
|
|
291
|
+
["python"], False),
|
|
292
|
+
("python_sql_concat",
|
|
293
|
+
r"""\b(?:cursor\.execute|\.execute)\s*\(\s*['"].*?\+""",
|
|
294
|
+
"high", "CWE-89",
|
|
295
|
+
"SQL query built with string concatenation — SQL injection risk",
|
|
296
|
+
"Use parameterized queries with ? or %s placeholders instead of concatenation",
|
|
297
|
+
["python"], False),
|
|
298
|
+
("python_marshal_loads",
|
|
299
|
+
r"""\bmarshal\.loads?\s*\(""",
|
|
300
|
+
"high", "CWE-502",
|
|
301
|
+
"marshal.load/loads — unsafe deserialization of arbitrary code objects",
|
|
302
|
+
"Use json or other safe serialization formats; marshal is not safe for untrusted data",
|
|
303
|
+
["python"], False),
|
|
304
|
+
("python_debug_true",
|
|
305
|
+
r"""\bDEBUG\s*=\s*True\b""",
|
|
306
|
+
"medium", "CWE-489",
|
|
307
|
+
"DEBUG mode enabled — may expose sensitive information in production",
|
|
308
|
+
"Ensure DEBUG=False in production settings; use environment variables for configuration",
|
|
309
|
+
["python"], False),
|
|
310
|
+
("python_assert_security",
|
|
311
|
+
r"""\bassert\b(?!.*(?:test|spec))""",
|
|
312
|
+
"low", "CWE-617",
|
|
313
|
+
"assert used outside tests — stripped in optimized mode (-O flag)",
|
|
314
|
+
"Use explicit if/raise for security checks; assert is stripped with python -O",
|
|
315
|
+
["python"], False),
|
|
316
|
+
("hardcoded_ip_address",
|
|
317
|
+
r"""(?:['"])\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(?:['"])""",
|
|
318
|
+
"medium", "CWE-1188",
|
|
319
|
+
"Hardcoded IP address detected — may hinder deployment flexibility",
|
|
320
|
+
"Use configuration files or environment variables for IP addresses",
|
|
321
|
+
[], False),
|
|
322
|
+
("python_os_system",
|
|
323
|
+
r"""\bos\.system\s*\(""",
|
|
324
|
+
"high", "CWE-78",
|
|
325
|
+
"os.system() — command injection risk via shell execution",
|
|
326
|
+
"Use subprocess.run() with shell=False and pass args as a list",
|
|
327
|
+
["python"], False),
|
|
328
|
+
("python_popen",
|
|
329
|
+
r"""\bos\.popen\s*\(""",
|
|
330
|
+
"high", "CWE-78",
|
|
331
|
+
"os.popen() — command injection risk via shell execution",
|
|
332
|
+
"Use subprocess.run() with shell=False and pass args as a list",
|
|
333
|
+
["python"], False),
|
|
334
|
+
("python_ssrf_request",
|
|
335
|
+
r"""\brequests\.(?:get|post|put|delete|patch|head)\s*\(\s*(?:f['"]|[^'"]*?\+|.*?\.format\()""",
|
|
336
|
+
"high", "CWE-918",
|
|
337
|
+
"HTTP request with dynamically constructed URL — potential SSRF",
|
|
338
|
+
"Validate and whitelist URLs before making requests; avoid user-controlled URL construction",
|
|
339
|
+
["python"], False),
|
|
340
|
+
("python_path_traversal",
|
|
341
|
+
r"""\bopen\s*\(\s*(?:os\.path\.join\s*\()?.*?(?:request|params|query|input|args)\b""",
|
|
342
|
+
"high", "CWE-22",
|
|
343
|
+
"File open with user-controlled path — path traversal risk",
|
|
344
|
+
"Validate and sanitize file paths; use os.path.realpath() and check against allowed directories",
|
|
345
|
+
["python"], False),
|
|
346
|
+
("python_weak_random",
|
|
347
|
+
r"""\brandom\.(?:random|randint|choice|randrange)\s*\(""",
|
|
348
|
+
"low", "CWE-330",
|
|
349
|
+
"Weak PRNG (random module) — not suitable for security-sensitive operations",
|
|
350
|
+
"Use secrets module or os.urandom() for cryptographic randomness",
|
|
351
|
+
["python"], False),
|
|
352
|
+
("python_cors_wildcard",
|
|
353
|
+
r"""(?:CORS|cors).*?\*""",
|
|
354
|
+
"medium", "CWE-942",
|
|
355
|
+
"CORS wildcard (*) allows any origin — may expose API to cross-origin attacks",
|
|
356
|
+
"Restrict CORS to specific trusted origins instead of using wildcard",
|
|
357
|
+
[], False),
|
|
358
|
+
# -----------------------------------------------------------------------
|
|
359
|
+
# Additional OWASP Top 10 detectors (JavaScript / TypeScript)
|
|
360
|
+
# -----------------------------------------------------------------------
|
|
361
|
+
("js_no_escape_html",
|
|
362
|
+
r"""\.html\s*\(\s*(?!['"]<)""",
|
|
363
|
+
"medium", "CWE-79",
|
|
364
|
+
"jQuery .html() with dynamic content — XSS risk",
|
|
365
|
+
"Sanitize content before inserting; use .text() for untrusted data or DOMPurify for HTML",
|
|
366
|
+
["javascript", "typescript"], False),
|
|
367
|
+
("js_url_redirect",
|
|
368
|
+
r"""(?:window\.location|location\.href|location\.assign|location\.replace)\s*=\s*(?!['"])""",
|
|
369
|
+
"high", "CWE-601",
|
|
370
|
+
"Open redirect via dynamic URL assignment — phishing risk",
|
|
371
|
+
"Validate redirect URLs against a whitelist of allowed destinations",
|
|
372
|
+
["javascript", "typescript"], False),
|
|
373
|
+
("js_postmessage_wildcard",
|
|
374
|
+
r"""\.postMessage\s*\([^)]*?,\s*['"]\*""",
|
|
375
|
+
"medium", "CWE-346",
|
|
376
|
+
"postMessage with wildcard origin (*) — message sent to any window",
|
|
377
|
+
"Specify the exact target origin instead of '*' in postMessage",
|
|
378
|
+
["javascript", "typescript"], False),
|
|
379
|
+
("js_unsafe_regex",
|
|
380
|
+
r"""new\s+RegExp\s*\(\s*(?!['"])""",
|
|
381
|
+
"medium", "CWE-1333",
|
|
382
|
+
"RegExp constructed from variable — potential ReDoS if user-controlled",
|
|
383
|
+
"Validate and sanitize input before constructing RegExp; consider using a regex-safe library",
|
|
384
|
+
["javascript", "typescript"], False),
|
|
385
|
+
("js_prototype_pollution",
|
|
386
|
+
r"""(?:__proto__|constructor\s*\.\s*prototype)\s*(?:\[|=)""",
|
|
387
|
+
"high", "CWE-1321",
|
|
388
|
+
"Prototype pollution — modifying Object.prototype can affect all objects",
|
|
389
|
+
"Use Object.create(null), Map, or validate property names to prevent prototype pollution",
|
|
390
|
+
["javascript", "typescript"], False),
|
|
391
|
+
("js_child_process_exec",
|
|
392
|
+
r"""\bexec\s*\(\s*(?!['"])""",
|
|
393
|
+
"high", "CWE-78",
|
|
394
|
+
"child_process.exec() with dynamic input — command injection risk",
|
|
395
|
+
"Use execFile() or spawn() with arguments as an array; avoid shell interpolation",
|
|
396
|
+
["javascript", "typescript"], False),
|
|
397
|
+
("js_nosql_injection",
|
|
398
|
+
r"""\$(?:gt|gte|lt|lte|ne|in|nin|or|and|not|regex|where|exists)\b""",
|
|
399
|
+
"medium", "CWE-943",
|
|
400
|
+
"NoSQL query operator detected — potential NoSQL injection if user-controlled",
|
|
401
|
+
"Validate and sanitize query inputs; use explicit field comparisons instead of raw operators",
|
|
402
|
+
["javascript", "typescript"], False),
|
|
403
|
+
# -----------------------------------------------------------------------
|
|
404
|
+
# Additional OWASP Top 10 detectors (Go)
|
|
405
|
+
# -----------------------------------------------------------------------
|
|
406
|
+
("go_sql_sprintf",
|
|
407
|
+
r"""(?:fmt\.Sprintf|fmt\.Fprintf)\s*\([^)]*?(?:SELECT|INSERT|UPDATE|DELETE|WHERE|FROM)""",
|
|
408
|
+
"high", "CWE-89",
|
|
409
|
+
"SQL query built with fmt.Sprintf — SQL injection risk",
|
|
410
|
+
"Use parameterized queries with database/sql placeholder syntax ($1, ?, etc.)",
|
|
411
|
+
["go"], False),
|
|
412
|
+
("go_unhandled_error",
|
|
413
|
+
r"""(?:_\s*(?:,\s*)?=\s*|(?:,\s*)?_\s*=)\s*\w+\.\w+\(""",
|
|
414
|
+
"low", "CWE-391",
|
|
415
|
+
"Error return value ignored (assigned to _) — may mask failures",
|
|
416
|
+
"Handle the error explicitly; at minimum log it for debugging",
|
|
417
|
+
["go"], False),
|
|
418
|
+
("go_tls_insecure",
|
|
419
|
+
r"""InsecureSkipVerify\s*:\s*true""",
|
|
420
|
+
"high", "CWE-295",
|
|
421
|
+
"TLS certificate verification disabled (InsecureSkipVerify: true)",
|
|
422
|
+
"Enable TLS verification; use a custom CA certificate pool if needed",
|
|
423
|
+
["go"], False),
|
|
424
|
+
# -----------------------------------------------------------------------
|
|
425
|
+
# Additional OWASP Top 10 detectors (Java / Kotlin)
|
|
426
|
+
# -----------------------------------------------------------------------
|
|
427
|
+
("java_sql_concat",
|
|
428
|
+
r"""(?:Statement|PreparedStatement)\s*.*?(?:executeQuery|executeUpdate|execute)\s*\(\s*(?!['"])""",
|
|
429
|
+
"high", "CWE-89",
|
|
430
|
+
"SQL execution with dynamic input — SQL injection risk",
|
|
431
|
+
"Use PreparedStatement with parameterized queries (? placeholders)",
|
|
432
|
+
["java", "kotlin"], False),
|
|
433
|
+
("java_xxe",
|
|
434
|
+
r"""(?:XMLInputFactory|DocumentBuilderFactory|SAXParserFactory)\.newInstance\(\)""",
|
|
435
|
+
"medium", "CWE-611",
|
|
436
|
+
"XML parser created without disabling external entities — XXE risk",
|
|
437
|
+
"Disable external entities: setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) and disable DTDs",
|
|
438
|
+
["java", "kotlin"], False),
|
|
439
|
+
("java_deserialization",
|
|
440
|
+
r"""\bObjectInputStream\s*\(""",
|
|
441
|
+
"high", "CWE-502",
|
|
442
|
+
"ObjectInputStream — unsafe deserialization of untrusted data",
|
|
443
|
+
"Use JSON/protobuf for serialization; if ObjectInputStream is required, use an allowlist filter",
|
|
444
|
+
["java", "kotlin"], False),
|
|
445
|
+
("java_weak_crypto",
|
|
446
|
+
r"""Cipher\.getInstance\s*\(\s*['"](?:DES|RC4|Blowfish|RC2)""",
|
|
447
|
+
"high", "CWE-327",
|
|
448
|
+
"Weak cipher algorithm (DES/RC4/Blowfish/RC2) — easily broken",
|
|
449
|
+
"Use AES-256-GCM or ChaCha20-Poly1305 for symmetric encryption",
|
|
450
|
+
["java", "kotlin"], False),
|
|
451
|
+
# -----------------------------------------------------------------------
|
|
452
|
+
# Additional OWASP Top 10 detectors (Ruby)
|
|
453
|
+
# -----------------------------------------------------------------------
|
|
454
|
+
("ruby_system_call",
|
|
455
|
+
r"""\b(?:system|exec|spawn|IO\.popen)\s*\(?\s*(?!['"])""",
|
|
456
|
+
"high", "CWE-78",
|
|
457
|
+
"Shell command execution with dynamic input — command injection risk",
|
|
458
|
+
"Use parameterized system calls; pass command and arguments as separate array elements",
|
|
459
|
+
["ruby"], False),
|
|
460
|
+
("ruby_send_dynamic",
|
|
461
|
+
r"""\.send\s*\(\s*(?:params|request|input)""",
|
|
462
|
+
"high", "CWE-94",
|
|
463
|
+
"Dynamic method dispatch (.send) with user-controlled input — code injection risk",
|
|
464
|
+
"Validate method names against an explicit allowlist before calling .send",
|
|
465
|
+
["ruby"], False),
|
|
466
|
+
# -----------------------------------------------------------------------
|
|
467
|
+
# Multi-language detectors
|
|
468
|
+
# -----------------------------------------------------------------------
|
|
469
|
+
("hardcoded_localhost",
|
|
470
|
+
r"""['"](?:localhost|127\.0\.0\.1|0\.0\.0\.0):\d{2,5}['"]""",
|
|
471
|
+
"low", "CWE-1188",
|
|
472
|
+
"Hardcoded localhost address with port — may not work in containerized/deployed environments",
|
|
473
|
+
"Use configuration files or environment variables for host/port settings",
|
|
474
|
+
[], False),
|
|
475
|
+
("todo_fixme_security",
|
|
476
|
+
r"""(?:#|//|/\*)\s*(?:TODO|FIXME|HACK|XXX)\s*.*?(?:security|auth|password|token|secret|credential|encrypt)""",
|
|
477
|
+
"info", "CWE-546",
|
|
478
|
+
"Security-related TODO/FIXME comment — unresolved security concern in code",
|
|
479
|
+
"Address the security concern described in the comment before deploying to production",
|
|
480
|
+
[], True),
|
|
481
|
+
# -----------------------------------------------------------------------
|
|
482
|
+
# Django framework detectors
|
|
483
|
+
# -----------------------------------------------------------------------
|
|
484
|
+
("django_mark_safe",
|
|
485
|
+
r"""\bmark_safe\s*\(""",
|
|
486
|
+
"high", "CWE-79",
|
|
487
|
+
"mark_safe() with potentially untrusted content — XSS risk",
|
|
488
|
+
"Avoid mark_safe() on user-supplied data; use Django template autoescaping or bleach.clean()",
|
|
489
|
+
["python"], False),
|
|
490
|
+
("django_raw_sql",
|
|
491
|
+
r"""\b(?:raw|extra)\s*\(\s*(?:f['"]|['"].*?%[sd])""",
|
|
492
|
+
"high", "CWE-89",
|
|
493
|
+
"SQL injection via Django raw()/extra() with string formatting",
|
|
494
|
+
"Use parameterized queries: Model.objects.raw('SELECT ... WHERE id = %s', [user_id])",
|
|
495
|
+
["python"], False),
|
|
496
|
+
("django_csrf_exempt",
|
|
497
|
+
r"""@csrf_exempt""",
|
|
498
|
+
"medium", "CWE-352",
|
|
499
|
+
"CSRF protection disabled via @csrf_exempt decorator",
|
|
500
|
+
"Remove @csrf_exempt unless the endpoint genuinely requires it (e.g., webhook); use csrf_protect for selective protection",
|
|
501
|
+
["python"], False),
|
|
502
|
+
("django_debug_toolbar",
|
|
503
|
+
r"""debug_toolbar""",
|
|
504
|
+
"low", "CWE-489",
|
|
505
|
+
"Django Debug Toolbar reference detected — must not be enabled in production",
|
|
506
|
+
"Ensure debug_toolbar is only in INSTALLED_APPS when DEBUG=True; remove from production settings",
|
|
507
|
+
["python"], False),
|
|
508
|
+
("django_secret_key_hardcoded",
|
|
509
|
+
r"""SECRET_KEY\s*=\s*['"][^'"]{10,}['"]""",
|
|
510
|
+
"high", "CWE-798",
|
|
511
|
+
"Hardcoded Django SECRET_KEY — compromises session security and CSRF protection",
|
|
512
|
+
"Load SECRET_KEY from environment variable: SECRET_KEY = os.environ['DJANGO_SECRET_KEY']",
|
|
513
|
+
["python"], False),
|
|
514
|
+
("django_allowed_hosts_wildcard",
|
|
515
|
+
r"""ALLOWED_HOSTS\s*=\s*\[['"\*]""",
|
|
516
|
+
"medium", "CWE-942",
|
|
517
|
+
"ALLOWED_HOSTS contains wildcard '*' — allows HTTP Host header attacks",
|
|
518
|
+
"Set ALLOWED_HOSTS to specific domain names: ALLOWED_HOSTS = ['example.com']",
|
|
519
|
+
["python"], False),
|
|
520
|
+
("django_safe_string",
|
|
521
|
+
r"""\bSafeString\s*\(|SafeText\s*\(|SafeData\s*\(""",
|
|
522
|
+
"medium", "CWE-79",
|
|
523
|
+
"Wrapping content in SafeString/SafeText/SafeData bypasses template autoescaping — XSS risk",
|
|
524
|
+
"Let Django's template autoescaping handle output; only use Safe* wrappers after sanitizing with bleach",
|
|
525
|
+
["python"], False),
|
|
526
|
+
("django_session_cookie_insecure",
|
|
527
|
+
r"""SESSION_COOKIE_SECURE\s*=\s*False""",
|
|
528
|
+
"medium", "CWE-614",
|
|
529
|
+
"Django session cookie transmitted without Secure flag — vulnerable to interception over HTTP",
|
|
530
|
+
"Set SESSION_COOKIE_SECURE = True in production to require HTTPS for session cookies",
|
|
531
|
+
["python"], False),
|
|
532
|
+
# -----------------------------------------------------------------------
|
|
533
|
+
# Flask framework detectors
|
|
534
|
+
# -----------------------------------------------------------------------
|
|
535
|
+
("flask_debug_mode",
|
|
536
|
+
r"""app\.run\s*\([^)]*debug\s*=\s*True""",
|
|
537
|
+
"high", "CWE-489",
|
|
538
|
+
"Flask app running with debug=True — exposes interactive debugger and reloader in production",
|
|
539
|
+
"Set debug=False in production; use FLASK_DEBUG environment variable for development",
|
|
540
|
+
["python"], False),
|
|
541
|
+
("flask_send_file_user_input",
|
|
542
|
+
r"""send_file\s*\(\s*(?:request|f['"]|.*?\+)""",
|
|
543
|
+
"high", "CWE-22",
|
|
544
|
+
"Flask send_file() with user-controlled path — path traversal risk",
|
|
545
|
+
"Use send_from_directory() with a fixed base directory; validate and sanitize filenames",
|
|
546
|
+
["python"], False),
|
|
547
|
+
("flask_jsonify_user_data",
|
|
548
|
+
r"""make_response\s*\(\s*(?:request|f['"])""",
|
|
549
|
+
"medium", "CWE-79",
|
|
550
|
+
"Flask make_response() with unescaped user data — potential XSS or injection",
|
|
551
|
+
"Use flask.jsonify() for JSON responses; escape HTML content with markupsafe.escape()",
|
|
552
|
+
["python"], False),
|
|
553
|
+
("flask_secret_key_hardcoded",
|
|
554
|
+
r"""app\.secret_key\s*=\s*['"][^'"]{5,}['"]""",
|
|
555
|
+
"high", "CWE-798",
|
|
556
|
+
"Hardcoded Flask secret_key — compromises session signing and CSRF tokens",
|
|
557
|
+
"Load secret_key from environment variable: app.secret_key = os.environ['FLASK_SECRET_KEY']",
|
|
558
|
+
["python"], False),
|
|
559
|
+
("flask_no_csrf",
|
|
560
|
+
r"""WTF_CSRF_ENABLED\s*=\s*False""",
|
|
561
|
+
"medium", "CWE-352",
|
|
562
|
+
"CSRF protection disabled in Flask-WTF — forms vulnerable to cross-site request forgery",
|
|
563
|
+
"Enable CSRF protection: set WTF_CSRF_ENABLED = True or remove the override",
|
|
564
|
+
["python"], False),
|
|
565
|
+
# -----------------------------------------------------------------------
|
|
566
|
+
# Express / Node.js framework detectors
|
|
567
|
+
# -----------------------------------------------------------------------
|
|
568
|
+
("express_cors_wildcard",
|
|
569
|
+
r"""cors\s*\(\s*\)""",
|
|
570
|
+
"medium", "CWE-942",
|
|
571
|
+
"Express CORS middleware with default config — allows all origins",
|
|
572
|
+
"Configure cors() with specific origin: cors({ origin: 'https://example.com' })",
|
|
573
|
+
["javascript", "typescript"], False),
|
|
574
|
+
("express_helmet_disabled",
|
|
575
|
+
r"""app\.disable\s*\(\s*['"]x-powered-by['"]""",
|
|
576
|
+
"low", "CWE-200",
|
|
577
|
+
"Manual X-Powered-By removal instead of using helmet — may miss other security headers",
|
|
578
|
+
"Use helmet middleware for comprehensive security headers: app.use(helmet())",
|
|
579
|
+
["javascript", "typescript"], False),
|
|
580
|
+
("express_body_parser_limit",
|
|
581
|
+
r"""bodyParser\.json\s*\(\s*\)""",
|
|
582
|
+
"low", "CWE-400",
|
|
583
|
+
"bodyParser.json() without size limit — vulnerable to large payload DoS",
|
|
584
|
+
"Set a body size limit: bodyParser.json({ limit: '100kb' })",
|
|
585
|
+
["javascript", "typescript"], False),
|
|
586
|
+
("express_sql_template",
|
|
587
|
+
r"""(?:query|execute)\s*\(\s*`[^`]*\$\{""",
|
|
588
|
+
"high", "CWE-89",
|
|
589
|
+
"SQL query built with template literal interpolation — SQL injection risk",
|
|
590
|
+
"Use parameterized queries: db.query('SELECT * FROM users WHERE id = $1', [userId])",
|
|
591
|
+
["javascript", "typescript"], False),
|
|
592
|
+
("express_jwt_no_verify",
|
|
593
|
+
r"""jwt\.decode\s*\([^)]*?,\s*\{[^}]*complete\s*:\s*true""",
|
|
594
|
+
"high", "CWE-347",
|
|
595
|
+
"JWT decoded without signature verification — token integrity not checked",
|
|
596
|
+
"Use jwt.verify() instead of jwt.decode() to validate token signatures",
|
|
597
|
+
["javascript", "typescript"], False),
|
|
598
|
+
("express_rate_limit_missing",
|
|
599
|
+
r"""app\.(?:post|put|delete)\s*\(\s*['"]\/(?:api|auth|login)""",
|
|
600
|
+
"low", "CWE-799",
|
|
601
|
+
"Sensitive API endpoint without apparent rate limiting — brute force risk",
|
|
602
|
+
"Apply rate limiting middleware: app.use('/api', rateLimit({ windowMs: 15*60*1000, max: 100 }))",
|
|
603
|
+
["javascript", "typescript"], False),
|
|
604
|
+
("express_session_insecure",
|
|
605
|
+
r"""(?:cookie|session).*?secure\s*:\s*false""",
|
|
606
|
+
"medium", "CWE-614",
|
|
607
|
+
"Session/cookie configured with secure: false — transmitted over HTTP",
|
|
608
|
+
"Set secure: true in production to require HTTPS for cookies",
|
|
609
|
+
["javascript", "typescript"], False),
|
|
610
|
+
# -----------------------------------------------------------------------
|
|
611
|
+
# Spring / Java framework detectors
|
|
612
|
+
# -----------------------------------------------------------------------
|
|
613
|
+
("spring_sql_concatenation",
|
|
614
|
+
r"""@Query\s*\(\s*['"].*?\+""",
|
|
615
|
+
"high", "CWE-89",
|
|
616
|
+
"SQL injection in Spring @Query annotation via string concatenation",
|
|
617
|
+
"Use named parameters in @Query: @Query('SELECT u FROM User u WHERE u.name = :name')",
|
|
618
|
+
["java", "kotlin"], False),
|
|
619
|
+
("spring_csrf_disabled",
|
|
620
|
+
r"""\.csrf\s*\(\s*\)\s*\.disable\s*\(\)""",
|
|
621
|
+
"medium", "CWE-352",
|
|
622
|
+
"Spring Security CSRF protection disabled — forms vulnerable to cross-site request forgery",
|
|
623
|
+
"Keep CSRF enabled for browser-facing endpoints; disable only for stateless APIs with token auth",
|
|
624
|
+
["java", "kotlin"], False),
|
|
625
|
+
("spring_cors_permit_all",
|
|
626
|
+
r"""\.allowedOrigins\s*\(\s*['"]\*['"]""",
|
|
627
|
+
"medium", "CWE-942",
|
|
628
|
+
"Spring CORS configured with wildcard origin '*' — allows any domain to make requests",
|
|
629
|
+
"Restrict allowedOrigins to specific trusted domains",
|
|
630
|
+
["java", "kotlin"], False),
|
|
631
|
+
("spring_actuator_exposed",
|
|
632
|
+
r"""management\.endpoints\.web\.exposure\.include\s*=\s*\*""",
|
|
633
|
+
"high", "CWE-200",
|
|
634
|
+
"All Spring Boot actuator endpoints exposed — leaks environment, health, and config data",
|
|
635
|
+
"Expose only needed endpoints: management.endpoints.web.exposure.include=health,info",
|
|
636
|
+
["java", "kotlin"], False),
|
|
637
|
+
("spring_hardcoded_password",
|
|
638
|
+
r"""spring\.datasource\.password\s*=\s*[^\$]""",
|
|
639
|
+
"high", "CWE-798",
|
|
640
|
+
"Hardcoded database password in Spring configuration — credential exposure risk",
|
|
641
|
+
"Use environment variable substitution: spring.datasource.password=${DB_PASSWORD}",
|
|
642
|
+
["java", "kotlin"], False),
|
|
643
|
+
("spring_security_permit_all",
|
|
644
|
+
r"""\.permitAll\s*\(\s*\)""",
|
|
645
|
+
"low", "CWE-862",
|
|
646
|
+
"Spring Security .permitAll() — verify endpoint intentionally allows unauthenticated access",
|
|
647
|
+
"Review whether the endpoint should require authentication; use .authenticated() for protected resources",
|
|
648
|
+
["java", "kotlin"], False),
|
|
649
|
+
# -----------------------------------------------------------------------
|
|
650
|
+
# Rails framework detectors
|
|
651
|
+
# -----------------------------------------------------------------------
|
|
652
|
+
("rails_html_safe",
|
|
653
|
+
r"""\.html_safe\b""",
|
|
654
|
+
"high", "CWE-79",
|
|
655
|
+
"Rails .html_safe on potentially untrusted content — XSS risk",
|
|
656
|
+
"Use sanitize() helper or ERB autoescaping; only call .html_safe on content you fully control",
|
|
657
|
+
["ruby"], False),
|
|
658
|
+
("rails_raw_sql",
|
|
659
|
+
r"""(?:find_by_sql|connection\.execute)\s*\(\s*(?!['"])""",
|
|
660
|
+
"high", "CWE-89",
|
|
661
|
+
"Rails raw SQL with dynamic input — SQL injection risk",
|
|
662
|
+
"Use parameterized queries: User.find_by_sql(['SELECT * FROM users WHERE id = ?', id])",
|
|
663
|
+
["ruby"], False),
|
|
664
|
+
("rails_mass_assignment",
|
|
665
|
+
r"""params\.permit!\b""",
|
|
666
|
+
"high", "CWE-915",
|
|
667
|
+
"Rails params.permit! allows mass assignment of all parameters — privilege escalation risk",
|
|
668
|
+
"Use explicit strong parameters: params.require(:user).permit(:name, :email)",
|
|
669
|
+
["ruby"], False),
|
|
670
|
+
("rails_force_ssl_false",
|
|
671
|
+
r"""force_ssl\s*=\s*false|config\.force_ssl\s*=\s*false""",
|
|
672
|
+
"medium", "CWE-319",
|
|
673
|
+
"Rails force_ssl disabled — application may serve requests over unencrypted HTTP",
|
|
674
|
+
"Set config.force_ssl = true in production to redirect all HTTP to HTTPS",
|
|
675
|
+
["ruby"], False),
|
|
676
|
+
("rails_skip_forgery",
|
|
677
|
+
r"""skip_before_action\s*:verify_authenticity_token""",
|
|
678
|
+
"medium", "CWE-352",
|
|
679
|
+
"Rails CSRF protection skipped via skip_before_action — forgery risk",
|
|
680
|
+
"Keep CSRF verification enabled; skip only for API-only controllers with token authentication",
|
|
681
|
+
["ruby"], False),
|
|
682
|
+
# -----------------------------------------------------------------------
|
|
683
|
+
# General framework-agnostic detectors
|
|
684
|
+
# -----------------------------------------------------------------------
|
|
685
|
+
("graphql_introspection",
|
|
686
|
+
r"""introspection\s*[:=]\s*true""",
|
|
687
|
+
"low", "CWE-200",
|
|
688
|
+
"GraphQL introspection enabled — exposes full API schema to attackers in production",
|
|
689
|
+
"Disable introspection in production: set introspection to false",
|
|
690
|
+
[], False),
|
|
691
|
+
("hardcoded_port",
|
|
692
|
+
r"""(?:PORT|port)\s*[:=]\s*\d{4,5}\b""",
|
|
693
|
+
"low", "CWE-1188",
|
|
694
|
+
"Hardcoded port number — reduces deployment flexibility",
|
|
695
|
+
"Use environment variable: PORT = int(os.environ.get('PORT', 8080))",
|
|
696
|
+
[], False),
|
|
697
|
+
("admin_route_unprotected",
|
|
698
|
+
r"""(?:route|path|get|post)\s*\(\s*['"]\/admin""",
|
|
699
|
+
"low", "CWE-862",
|
|
700
|
+
"Admin route detected — ensure authentication and authorization middleware is applied",
|
|
701
|
+
"Protect admin routes with authentication middleware and role-based access control",
|
|
702
|
+
[], False),
|
|
703
|
+
("cookie_httponly_false",
|
|
704
|
+
r"""httpOnly\s*[:=]\s*false|httponly\s*[:=]\s*False""",
|
|
705
|
+
"medium", "CWE-1004",
|
|
706
|
+
"Cookie without HttpOnly flag — accessible to JavaScript, increasing XSS impact",
|
|
707
|
+
"Set httpOnly: true (or httponly=True) to prevent client-side script access to the cookie",
|
|
708
|
+
[], False),
|
|
709
|
+
]
|
|
710
|
+
|
|
711
|
+
ANTI_PATTERNS: list[SecurityPattern] = [
|
|
712
|
+
SecurityPattern(
|
|
713
|
+
name=name,
|
|
714
|
+
pattern=re.compile(regex),
|
|
715
|
+
severity=Severity(sev),
|
|
716
|
+
category=Category.ANTI_PATTERN,
|
|
717
|
+
cwe_id=cwe,
|
|
718
|
+
message=msg,
|
|
719
|
+
recommendation=rec,
|
|
720
|
+
languages=langs,
|
|
721
|
+
scan_comments=scan_comments,
|
|
722
|
+
)
|
|
723
|
+
for name, regex, sev, cwe, msg, rec, langs, scan_comments in _ANTI_PATTERN_DEFS
|
|
724
|
+
]
|