pi-lens 3.8.73 → 4.0.0
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.
- package/CHANGELOG.md +2614 -12
- package/README.md +50 -21
- package/dist/clients/actionable-warnings.js +73 -18
- package/dist/clients/agent-behavior-client.js +21 -4
- package/dist/clients/ast-grep-client.js +68 -16
- package/dist/clients/ast-grep-types.js +0 -1
- package/dist/clients/ast-grep-yaml-synth.js +37 -10
- package/dist/clients/atomic-write-staging.js +63 -0
- package/dist/clients/atomic-write.js +116 -16
- package/dist/clients/bash-file-access.js +193 -23
- package/dist/clients/biome-client.js +29 -25
- package/dist/clients/bootstrap.js +11 -2
- package/dist/clients/bounded-cache.js +34 -0
- package/dist/clients/bounded-pid-file-lock.js +192 -0
- package/dist/clients/bus-events-logger.js +5 -1
- package/dist/clients/bus-publish.js +10 -3
- package/dist/clients/cache/rule-cache.js +89 -6
- package/dist/clients/cache-manager.js +97 -9
- package/dist/clients/cache-observability.js +498 -0
- package/dist/clients/call-graph.js +460 -108
- package/dist/clients/cascade-logger.js +5 -1
- package/dist/clients/child-unref.js +85 -0
- package/dist/clients/codebase-model.js +52 -23
- package/dist/clients/collateral-test-role.js +40 -0
- package/dist/clients/complexity-client.js +6 -8
- package/dist/clients/console-guard-install.js +14 -0
- package/dist/clients/cooperative-budget.js +42 -0
- package/dist/clients/dead-code-client.js +2 -1
- package/dist/clients/debug-handles.js +206 -0
- package/dist/clients/debug-heap.js +167 -0
- package/dist/clients/degradation-ledger.js +153 -0
- package/dist/clients/dependency-checker.js +466 -63
- package/dist/clients/diagnostic-dispositions.js +83 -13
- package/dist/clients/diagnostics-publish.js +10 -3
- package/dist/clients/dispatch/auxiliary-lsp.js +34 -0
- package/dist/clients/dispatch/dispatcher.js +71 -13
- package/dist/clients/dispatch/fact-store.js +11 -0
- package/dist/clients/dispatch/facts/function-facts.js +37 -7
- package/dist/clients/dispatch/facts/import-facts.js +108 -119
- package/dist/clients/dispatch/facts/tree-sitter-facts.js +12 -12
- package/dist/clients/dispatch/facts/try-catch-facts.js +13 -0
- package/dist/clients/dispatch/indent-detect.js +35 -0
- package/dist/clients/dispatch/inline-suppressions.js +17 -8
- package/dist/clients/dispatch/integration.js +1094 -611
- package/dist/clients/dispatch/lazy.js +14 -0
- package/dist/clients/dispatch/plan.js +11 -1
- package/dist/clients/dispatch/rule-id-normalize.js +50 -0
- package/dist/clients/dispatch/rule-policy.js +135 -0
- package/dist/clients/dispatch/rules/async-noise.js +1 -0
- package/dist/clients/dispatch/rules/unsafe-boundary.js +7 -0
- package/dist/clients/dispatch/runners/ast-grep-napi.js +47 -6
- package/dist/clients/dispatch/runners/biome-check.js +5 -9
- package/dist/clients/dispatch/runners/detekt.js +3 -2
- package/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/dist/clients/dispatch/runners/helm-lint.js +154 -0
- package/dist/clients/dispatch/runners/htmlhint.js +3 -2
- package/dist/clients/dispatch/runners/index.js +5 -1
- package/dist/clients/dispatch/runners/lsp.js +14 -6
- package/dist/clients/dispatch/runners/markdownlint.js +4 -9
- package/dist/clients/dispatch/runners/psscriptanalyzer.js +10 -1
- package/dist/clients/dispatch/runners/pyright.js +9 -5
- package/dist/clients/dispatch/runners/ruff.js +4 -8
- package/dist/clients/dispatch/runners/shellcheck.js +2 -3
- package/dist/clients/dispatch/runners/shfmt.js +2 -3
- package/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/dist/clients/dispatch/runners/taplo.js +2 -1
- package/dist/clients/dispatch/runners/terragrunt.js +163 -0
- package/dist/clients/dispatch/runners/tflint.js +37 -5
- package/dist/clients/dispatch/runners/tree-sitter.js +155 -166
- package/dist/clients/dispatch/runners/trivy-config.js +13 -7
- package/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
- package/dist/clients/dispatch/runners/utils/runner-helpers.js +284 -34
- package/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
- package/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
- package/dist/clients/disposition-publish.js +10 -3
- package/dist/clients/durable-store.js +97 -0
- package/dist/clients/event-loop-monitor.js +94 -3
- package/dist/clients/extension-log.js +139 -0
- package/dist/clients/extension-mode.js +73 -0
- package/dist/clients/feature-hints.js +53 -7
- package/dist/clients/file-kinds.js +143 -31
- package/dist/clients/file-role.js +18 -3
- package/dist/clients/file-utils.js +56 -34
- package/dist/clients/fix-worklog.js +14 -2
- package/dist/clients/format-events-publish.js +16 -3
- package/dist/clients/format-service.js +24 -8
- package/dist/clients/formatters-lazy.js +8 -0
- package/dist/clients/formatters.js +358 -61
- package/dist/clients/generated-artifacts.js +169 -15
- package/dist/clients/git-guard.js +681 -11
- package/dist/clients/git-tracked-ignore.js +4 -0
- package/dist/clients/go-client.js +2 -1
- package/dist/clients/govulncheck-client.js +8 -0
- package/dist/clients/grammar-source.js +12 -4
- package/dist/clients/gzip-stage-write.js +102 -0
- package/dist/clients/host-ports.js +31 -0
- package/dist/clients/installer/index.js +733 -213
- package/dist/clients/instance-reaper.js +142 -172
- package/dist/clients/jscpd-client.js +31 -54
- package/dist/clients/knip-client.js +78 -36
- package/dist/clients/language-policy.js +14 -2
- package/dist/clients/language-profile.js +72 -77
- package/dist/clients/latency-logger.js +28 -16
- package/dist/clients/lens-config.js +140 -166
- package/dist/clients/lens-engine.js +124 -21
- package/dist/clients/lens-events.js +27 -4
- package/dist/clients/lens-flag-registry.js +293 -0
- package/dist/clients/lens-map.js +96 -26
- package/dist/clients/live-bus-emitter.js +30 -0
- package/dist/clients/log-cleanup.js +8 -18
- package/dist/clients/lsp/cascade-tier.js +23 -3
- package/dist/clients/lsp/client.js +566 -57
- package/dist/clients/lsp/config.js +74 -10
- package/dist/clients/lsp/diagnostic-binding.js +86 -0
- package/dist/clients/lsp/edits.js +1012 -121
- package/dist/clients/lsp/index.js +1840 -803
- package/dist/clients/lsp/language.js +4 -1
- package/dist/clients/lsp/launch.js +40 -32
- package/dist/clients/lsp/path-utils.js +1 -1
- package/dist/clients/lsp/ruby-drive-dirs.js +83 -0
- package/dist/clients/lsp/server.js +279 -60
- package/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
- package/dist/clients/lsp-document-symbols.js +112 -0
- package/dist/clients/lsp-lazy.js +8 -0
- package/dist/clients/lsp-mutation.js +248 -0
- package/dist/clients/mcp/analyze.js +128 -36
- package/dist/clients/mcp/ipc.js +157 -24
- package/dist/clients/mcp/review.js +36 -3
- package/dist/clients/mcp/session.js +216 -8
- package/dist/clients/memory-sampler.js +115 -0
- package/dist/clients/metrics-client.js +2 -1
- package/dist/clients/metrics-history.js +2 -1
- package/dist/clients/module-report-lsp.js +5 -0
- package/dist/clients/module-report.js +267 -82
- package/dist/clients/ndjson-logger.js +334 -103
- package/dist/clients/opengrep-client.js +1 -1
- package/dist/clients/partial-edit-apply.js +120 -5
- package/dist/clients/path-keyed-map.js +76 -0
- package/dist/clients/path-utils.js +141 -5
- package/dist/clients/performance-report.js +327 -0
- package/dist/clients/pipeline.js +54 -13
- package/dist/clients/print-mode.js +21 -0
- package/dist/clients/project-changes.js +117 -4
- package/dist/clients/project-diagnostics/cache.js +3 -2
- package/dist/clients/project-diagnostics/extractors.js +26 -115
- package/dist/clients/project-diagnostics/fresh-fetch.js +149 -19
- package/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +117 -0
- package/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +37 -5
- package/dist/clients/project-diagnostics/scanner.js +268 -128
- package/dist/clients/project-lens-config.js +138 -34
- package/dist/clients/project-report.js +64 -25
- package/dist/clients/project-scale.js +8 -10
- package/dist/clients/project-snapshot-persist-worker.js +6 -0
- package/dist/clients/project-snapshot.js +767 -8
- package/dist/clients/project-trust.js +181 -0
- package/dist/clients/quiet-window.js +27 -5
- package/dist/clients/read-bridge.js +147 -0
- package/dist/clients/read-expansion.js +22 -12
- package/dist/clients/read-guard-logger.js +159 -1
- package/dist/clients/read-guard-tool-lines.js +150 -29
- package/dist/clients/read-guard.js +262 -3
- package/dist/clients/redact/secrets.js +449 -0
- package/dist/clients/resource-sampler.js +144 -39
- package/dist/clients/reverse-deps.js +48 -0
- package/dist/clients/review-graph/builder.js +2570 -326
- package/dist/clients/review-graph/git-identity.js +2 -1
- package/dist/clients/review-graph/import-resolvers.js +21 -10
- package/dist/clients/review-graph/persist-worker.js +10 -0
- package/dist/clients/review-graph/query.js +5 -0
- package/dist/clients/review-graph/shared-extraction-ir.js +90 -0
- package/dist/clients/review-graph/symbol-id.js +46 -0
- package/dist/clients/review-graph/tsconfig-paths.js +57 -6
- package/dist/clients/review-graph/workspace-modules.js +51 -3
- package/dist/clients/review-graph-logger.js +53 -0
- package/dist/clients/ruff-client.js +27 -44
- package/dist/clients/runtime-agent-end.js +111 -75
- package/dist/clients/runtime-context.js +36 -12
- package/dist/clients/runtime-coordinator.js +76 -8
- package/dist/clients/runtime-session.js +799 -137
- package/dist/clients/runtime-tool-call.js +117 -62
- package/dist/clients/runtime-tool-result.js +218 -23
- package/dist/clients/runtime-turn.js +284 -40
- package/dist/clients/rust-client.js +2 -1
- package/dist/clients/safe-spawn.js +873 -71
- package/dist/clients/security-scan-client.js +2 -1
- package/dist/clients/session-start-observability.js +15 -0
- package/dist/clients/session-state-store.js +5 -3
- package/dist/clients/sessionstart-logger.js +18 -0
- package/dist/clients/sg-runner.js +284 -159
- package/dist/clients/slow-fs.js +2 -1
- package/dist/clients/smells-rollup.js +224 -0
- package/dist/clients/source-filter.js +231 -43
- package/dist/clients/source-walker.js +66 -10
- package/dist/clients/startup-scan.js +15 -16
- package/dist/clients/startup-timing.js +9 -0
- package/dist/clients/test-runner-client.js +38 -8
- package/dist/clients/todo-scanner.js +30 -3
- package/dist/clients/tool-event.js +35 -0
- package/dist/clients/tool-policy.js +388 -39
- package/dist/clients/tool-render.js +155 -0
- package/dist/clients/tree-sitter-cache.js +153 -140
- package/dist/clients/tree-sitter-client.js +1722 -80
- package/dist/clients/tree-sitter-logger.js +64 -1
- package/dist/clients/tree-sitter-query-loader.js +117 -12
- package/dist/clients/tree-sitter-shared.js +48 -19
- package/dist/clients/tree-sitter-symbol-extractor.js +115 -11
- package/dist/clients/user-notify.js +51 -0
- package/dist/clients/vanished-instance-marker.js +57 -0
- package/dist/clients/warm-attach.js +33 -13
- package/dist/clients/widget-state.js +342 -49
- package/dist/clients/word-index-logger.js +44 -0
- package/dist/clients/word-index.js +612 -68
- package/dist/clients/workspace-topology.js +100 -7
- package/dist/index.js +65923 -47161
- package/dist/mcp/analyze-cli.js +185 -29
- package/dist/mcp/cli.js +110 -0
- package/dist/mcp/server.js +272 -50
- package/dist/tools/ast-grep-search.js +93 -27
- package/dist/tools/lens-diagnostics.js +247 -41
- package/dist/tools/lsp-diagnostics.js +153 -40
- package/dist/tools/lsp-navigation.js +51 -31
- package/dist/tools/module-report.js +9 -0
- package/dist/tools/symbol-search.js +21 -2
- package/docs/agent-guide.md +247 -0
- package/docs/agent-tools.md +21 -10
- package/docs/analysisall.md +192 -0
- package/docs/api-ports-inventory.md +165 -0
- package/docs/ast-grep_rules_catalog.md +5 -2
- package/docs/astplayground.md +3 -4
- package/docs/audit1.md +5 -5
- package/docs/durable-store-audit-1202.md +32 -0
- package/docs/environment-variables.md +197 -11
- package/docs/fable.md +27 -0
- package/docs/features.md +35 -5
- package/docs/globalconfig.md +101 -5
- package/docs/language-coverage.md +6 -5
- package/docs/lsp-capability-matrix.md +2 -2
- package/docs/mcp.md +54 -20
- package/docs/servercapabilities.md +7 -4
- package/docs/settings.md +192 -0
- package/docs/tools.md +18 -1
- package/docs/tree-sitter_rules_catalog.md +11 -31
- package/docs/usage.md +31 -0
- package/package.json +139 -138
- package/rules/ast-grep-rules/rule-tests/hardcoded-url-js-test.yml +1 -0
- package/rules/ast-grep-rules/rule-tests/hardcoded-url-test.yml +2 -0
- package/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
- package/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
- package/rules/ast-grep-rules/rule-tests/no-case-declarations-js-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/no-case-declarations-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/no-javascript-url-js-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/no-javascript-url-test.yml +10 -0
- package/rules/ast-grep-rules/rule-tests/no-nested-links-test.yml +11 -1
- package/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
- package/rules/ast-grep-rules/rule-tests/no-win32-isabsolute-for-qualification-test.yml +16 -0
- package/rules/ast-grep-rules/rule-tests/strict-equality-js-test.yml +3 -0
- package/rules/ast-grep-rules/rule-tests/strict-equality-test.yml +3 -0
- package/rules/ast-grep-rules/rule-tests/strict-inequality-js-test.yml +3 -0
- package/rules/ast-grep-rules/rule-tests/strict-inequality-test.yml +4 -0
- package/rules/ast-grep-rules/rules/hardcoded-url-js.yml +22 -4
- package/rules/ast-grep-rules/rules/hardcoded-url.yml +22 -4
- package/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
- package/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
- package/rules/ast-grep-rules/rules/no-case-declarations-js.yml +4 -3
- package/rules/ast-grep-rules/rules/no-case-declarations.yml +4 -3
- package/rules/ast-grep-rules/rules/no-console-except-error-js.yml +10 -0
- package/rules/ast-grep-rules/rules/no-console-except-error.yml +10 -0
- package/rules/ast-grep-rules/rules/no-javascript-url-js.yml +42 -6
- package/rules/ast-grep-rules/rules/no-javascript-url.yml +42 -6
- package/rules/ast-grep-rules/rules/no-nested-links.yml +7 -0
- package/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
- package/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
- package/rules/ast-grep-rules/rules/strict-equality-js.yml +14 -1
- package/rules/ast-grep-rules/rules/strict-equality.yml +14 -1
- package/rules/ast-grep-rules/rules/strict-inequality-js.yml +14 -1
- package/rules/ast-grep-rules/rules/strict-inequality.yml +14 -1
- package/rules/tree-sitter-queries/cpp/no-memset-sensitive-data.yml +9 -3
- package/rules/tree-sitter-queries/cpp/no-scoped-lock-without-args.yml +6 -6
- package/rules/tree-sitter-queries/css/calc-spacing.yml +8 -6
- package/rules/tree-sitter-queries/go/go-mutex-copy.yml +21 -18
- package/rules/tree-sitter-queries/go/go-shared-map-write-goroutine.yml +3 -3
- package/rules/tree-sitter-queries/java/infinite-loop-java.yml +3 -3
- package/rules/tree-sitter-queries/java/junit-call-super.yml +6 -4
- package/rules/tree-sitter-queries/java/no-double-checked-locking.yml +10 -8
- package/rules/tree-sitter-queries/java/no-field-shadowing.yml +1 -1
- package/rules/tree-sitter-queries/java/prepared-statement-valid-indices.yml +2 -3
- package/rules/tree-sitter-queries/java/resources-closed.yml +2 -2
- package/rules/tree-sitter-queries/java/springboot-default-package.yml +6 -3
- package/rules/tree-sitter-queries/java/switch-fall-through.yml +6 -4
- package/rules/tree-sitter-queries/java/switch-non-case-labels.yml +4 -3
- package/rules/tree-sitter-queries/java/tests-include-assertions.yml +6 -5
- package/rules/tree-sitter-queries/javascript/switch-case-termination-js.yml +5 -8
- package/rules/tree-sitter-queries/javascript/switch-non-case-labels.yml +3 -2
- package/rules/tree-sitter-queries/kotlin/prepared-statement-indices.yml +9 -5
- package/rules/tree-sitter-queries/php/this-in-static-context.yml +5 -5
- package/rules/tree-sitter-queries/python/exit-signature-check.yml +2 -9
- package/rules/tree-sitter-queries/python/in-operator-unsupported.yml +3 -4
- package/rules/tree-sitter-queries/python/no-super-torchscript.yml +4 -8
- package/rules/tree-sitter-queries/python/notimplemented-boolean-context.yml +1 -5
- package/rules/tree-sitter-queries/python/python-empty-except.yml +1 -1
- package/rules/tree-sitter-queries/python/return-in-init.yml +0 -2
- package/rules/tree-sitter-queries/python/yield-return-outside-function.yml +0 -3
- package/rules/tree-sitter-queries/ruby/ruby-command-injection.yml +1 -12
- package/rules/tree-sitter-queries/ruby/ruby-eval.yml +1 -1
- package/rules/tree-sitter-queries/ruby/ruby-insecure-deserialization.yml +4 -4
- package/rules/tree-sitter-queries/ruby/ruby-insecure-random.yml +4 -11
- package/rules/tree-sitter-queries/ruby/ruby-open-struct.yml +1 -1
- package/rules/tree-sitter-queries/ruby/ruby-string-eval.yml +2 -3
- package/rules/tree-sitter-queries/ruby/ruby-weak-hash.yml +4 -4
- package/rules/tree-sitter-queries/rust/rust-lock-held-across-await.yml +4 -3
- package/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
- package/rules/tree-sitter-queries/typescript/console-statement.yml +11 -0
- package/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +4 -9
- package/rules/tree-sitter-queries/typescript/empty-switch-case.yml +13 -9
- package/rules/tree-sitter-queries/typescript/infinite-loop.yml +2 -2
- package/rules/tree-sitter-queries/typescript/mixed-async-styles.yml +10 -1
- package/rules/tree-sitter-queries/typescript/switch-case-termination.yml +5 -8
- package/rules/tree-sitter-queries/typescript/ts-insecure-random.yml +7 -10
- package/rules/tree-sitter-queries/typescript/unsafe-regex.yml +4 -2
- package/rules/typos/_typos.toml +17 -0
- package/scripts/analyze-pi-lens-logs.mjs +55 -2
- package/skills/pi-lens-write-tree-sitter-rule/SKILL.md +5 -0
- package/dist/clients/ast-grep-parser.js +0 -86
- package/dist/clients/config-enabled-shape.js +0 -39
- package/dist/clients/lsp/interactive-install.js +0 -367
- package/dist/clients/lsp/lsp-index.js +0 -10
- package/dist/clients/lsp/server-strategies.js +0 -5
- package/dist/clients/project-metadata.js +0 -690
- package/dist/clients/source-groups.js +0 -96
- package/dist/clients/types.js +0 -11
- package/docs/env_variables.md +0 -10
- package/rules/tree-sitter-queries/abap-disabled/delete-where.yml +0 -46
- package/rules/tree-sitter-queries/cpp/no-confused-move-forward.yml +0 -59
- package/rules/tree-sitter-queries/cpp/noexcept-functions.yml +0 -58
- package/rules/tree-sitter-queries/java/mockito-initialized.yml +0 -66
- package/rules/tree-sitter-queries/java/no-wait-notify-on-thread.yml +0 -58
- package/rules/tree-sitter-queries/java/short-circuit-logic.yml +0 -57
- package/rules/tree-sitter-queries/java/spring-session-attributes-setcomplete.yml +0 -75
- package/rules/tree-sitter-queries/plsql-disabled/delete-update-where.yml +0 -56
- package/rules/tree-sitter-queries/plsql-disabled/end-loop-semicolon.yml +0 -51
- package/rules/tree-sitter-queries/plsql-disabled/fetch-bulk-collect-limit.yml +0 -47
- package/rules/tree-sitter-queries/plsql-disabled/forallsave-exceptions.yml +0 -51
- package/rules/tree-sitter-queries/plsql-disabled/nchar-nvarchar2-bytes.yml +0 -54
- package/rules/tree-sitter-queries/plsql-disabled/not-null-initialization.yml +0 -59
- package/rules/tree-sitter-queries/plsql-disabled/raise-application-error-codes.yml +0 -50
- package/rules/tree-sitter-queries/typescript-disabled/ts-path-traversal.yml +0 -71
|
@@ -16,22 +16,19 @@ description: |
|
|
|
16
16
|
✅ FIX: use crypto.getRandomValues / crypto.randomUUID / secure server-side RNG.
|
|
17
17
|
|
|
18
18
|
query: |
|
|
19
|
-
(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
property: (property_identifier) @FN)
|
|
25
|
-
arguments: (arguments) @ARGS)
|
|
19
|
+
(call_expression
|
|
20
|
+
function: (member_expression
|
|
21
|
+
object: (identifier) @OBJ
|
|
22
|
+
property: (property_identifier) @FN)
|
|
23
|
+
arguments: (arguments) @ARGS
|
|
26
24
|
(#eq? @OBJ "Math")
|
|
27
|
-
(#eq? @FN "random")
|
|
28
|
-
(#match? @VAR "(?i)(token|secret|password|key|nonce|salt|csrf|auth|session|credential|hash|otp|pin)"))
|
|
25
|
+
(#eq? @FN "random")) @CALL
|
|
29
26
|
|
|
30
27
|
metavars:
|
|
31
28
|
- OBJ
|
|
32
29
|
- FN
|
|
33
30
|
- ARGS
|
|
34
|
-
-
|
|
31
|
+
- CALL
|
|
35
32
|
|
|
36
33
|
post_filter: ts_insecure_random_source
|
|
37
34
|
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
# Detects dynamic regex construction that can lead to ReDoS
|
|
3
3
|
id: unsafe-regex
|
|
4
4
|
name: Dynamic Regex Construction
|
|
5
|
-
severity:
|
|
5
|
+
severity: warning
|
|
6
6
|
category: security
|
|
7
7
|
defect_class: injection
|
|
8
|
-
inline_tier:
|
|
8
|
+
inline_tier: warning
|
|
9
9
|
language: typescript
|
|
10
10
|
|
|
11
11
|
message: "Dynamic regex from user input — can cause ReDoS (Regular Expression Denial of Service)"
|
|
@@ -44,6 +44,8 @@ metavars:
|
|
|
44
44
|
- INTERPOLATION
|
|
45
45
|
- PATTERN
|
|
46
46
|
|
|
47
|
+
post_filter: unsafe_regex_dynamic_identifier
|
|
48
|
+
|
|
47
49
|
has_fix: false
|
|
48
50
|
|
|
49
51
|
tags:
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# pi-lens bundled default typos allowlist (#967).
|
|
2
|
+
#
|
|
3
|
+
# This file is injected as `initializationOptions.config` for the `typos-lsp`
|
|
4
|
+
# auxiliary server ONLY when a project has no local typos config of its own
|
|
5
|
+
# (`typos.toml` / `_typos.toml` / `.typos.toml` — see clients/typos-config.ts).
|
|
6
|
+
# Any project-owned config always wins outright: pi-lens injects nothing in
|
|
7
|
+
# that case, so this file never merges with (and can never outrank) a team's
|
|
8
|
+
# own allowlist.
|
|
9
|
+
#
|
|
10
|
+
# Keep this list to evidenced false positives only — exact-identifier matches
|
|
11
|
+
# via `extend-identifiers`, never the looser `extend-words` (which also
|
|
12
|
+
# rewrites substrings inside unrelated words). Do not bulk-import a
|
|
13
|
+
# dictionary here; every entry must have a provenance comment.
|
|
14
|
+
|
|
15
|
+
[default.extend-identifiers]
|
|
16
|
+
dito = "dito" # #967 — real model/vendor namespace (provider-failover normalization prefix), not a misspelling of "ditto"
|
|
17
|
+
unparseable = "unparseable" # #967 — valid English spelling ("un-parseable"), not a typo of "unparsable"
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* ~/.pi-lens/cascade*.log JSONL impact-cascade logs
|
|
9
9
|
* ~/.pi-lens/read-guard*.log JSONL read-guard friction logs
|
|
10
10
|
* ~/.pi-lens/tree-sitter*.log JSONL structural runner logs
|
|
11
|
+
* ~/.pi-lens/extension*.log JSONL extension diagnostics and console-guard telemetry
|
|
11
12
|
* ~/.pi-lens/actionable-warnings*.log JSONL advisory pipeline (inject/suppress)
|
|
12
13
|
* ~/.pi-lens/ast-grep-tools*.log JSONL MCP ast-grep search/replace telemetry
|
|
13
14
|
* ~/.pi-lens/logs/*.jsonl JSONL diagnostic findings
|
|
@@ -18,10 +19,12 @@ import os from "node:os";
|
|
|
18
19
|
import path from "node:path";
|
|
19
20
|
import readline from "node:readline";
|
|
20
21
|
import { fileURLToPath } from "node:url";
|
|
22
|
+
import { minimatch } from "minimatch";
|
|
21
23
|
|
|
22
24
|
const DEFAULT_ROOT = path.join(os.homedir(), ".pi-lens");
|
|
23
25
|
const DEFAULT_SINCE = "2d";
|
|
24
26
|
const DEFAULT_LIMIT = 12;
|
|
27
|
+
const DEFAULT_EXCLUDE_GLOBS = ["**/AppData/Local/Temp/claude/**", "**/heap-corpus*/**", "**/.plegma/work/**"];
|
|
25
28
|
|
|
26
29
|
const args = parseArgs(process.argv.slice(2));
|
|
27
30
|
const root = path.resolve(expandHome(args.root ?? DEFAULT_ROOT));
|
|
@@ -30,6 +33,10 @@ const limit =
|
|
|
30
33
|
Number.parseInt(args.limit ?? `${DEFAULT_LIMIT}`, 10) || DEFAULT_LIMIT;
|
|
31
34
|
const outputJson = Boolean(args.json);
|
|
32
35
|
const includeArchived = Boolean(args.archived);
|
|
36
|
+
const excludeGlobs = [
|
|
37
|
+
...DEFAULT_EXCLUDE_GLOBS,
|
|
38
|
+
...(Array.isArray(args.exclude) ? args.exclude : args.exclude ? [args.exclude] : []),
|
|
39
|
+
];
|
|
33
40
|
|
|
34
41
|
const thresholds = {
|
|
35
42
|
startupSlowMs: Number.parseInt(args.startupSlowMs ?? "500", 10),
|
|
@@ -83,7 +90,14 @@ function parseArgs(argv) {
|
|
|
83
90
|
const key = arg.slice(2);
|
|
84
91
|
const next = argv[i + 1];
|
|
85
92
|
if (!next || next.startsWith("--")) out[key] = "true";
|
|
86
|
-
else
|
|
93
|
+
else if (key === "exclude") {
|
|
94
|
+
const value = argv[++i];
|
|
95
|
+
out.exclude = out.exclude
|
|
96
|
+
? Array.isArray(out.exclude)
|
|
97
|
+
? [...out.exclude, value]
|
|
98
|
+
: [out.exclude, value]
|
|
99
|
+
: value;
|
|
100
|
+
} else out[key] = argv[++i];
|
|
87
101
|
}
|
|
88
102
|
}
|
|
89
103
|
return out;
|
|
@@ -158,6 +172,7 @@ function createState(files) {
|
|
|
158
172
|
window: { since: since?.toISOString() ?? "all", root },
|
|
159
173
|
files,
|
|
160
174
|
parseErrors: counter(),
|
|
175
|
+
excludedRows: 0,
|
|
161
176
|
seen: counter(),
|
|
162
177
|
projects: counter(),
|
|
163
178
|
smellTotals: counter(),
|
|
@@ -557,6 +572,10 @@ async function analyzeSessionStart(files, state) {
|
|
|
557
572
|
const ts = dateOf(match[1]);
|
|
558
573
|
if (!inWindow(ts)) return;
|
|
559
574
|
const message = match[2];
|
|
575
|
+
if (isExcludedText(message)) {
|
|
576
|
+
state.excludedRows++;
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
560
579
|
state.seen.inc("sessionstart");
|
|
561
580
|
|
|
562
581
|
const cwd = /session_start cwd:\s*(.*)$/.exec(message)?.[1];
|
|
@@ -722,13 +741,45 @@ async function forEachJsonLine(file, bucket, state, visitor) {
|
|
|
722
741
|
await forEachLine(file, async (line) => {
|
|
723
742
|
if (!line.trim()) return;
|
|
724
743
|
try {
|
|
725
|
-
|
|
744
|
+
const entry = JSON.parse(line);
|
|
745
|
+
if (isExcludedEntry(entry)) {
|
|
746
|
+
state.excludedRows++;
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
visitor(entry);
|
|
726
750
|
} catch {
|
|
727
751
|
state.parseErrors.inc(`${bucket}:${path.basename(file)}`);
|
|
728
752
|
}
|
|
729
753
|
});
|
|
730
754
|
}
|
|
731
755
|
|
|
756
|
+
function isExcludedEntry(entry) {
|
|
757
|
+
return pathValues(entry).some((value) =>
|
|
758
|
+
excludeGlobs.some((glob) =>
|
|
759
|
+
minimatch(value, glob, { nocase: true, dot: true }),
|
|
760
|
+
),
|
|
761
|
+
);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
function pathValues(value, key = "") {
|
|
765
|
+
if (typeof value === "string") {
|
|
766
|
+
return /(file|path|cwd|root|project)/i.test(key) ? [normalizePath(value)] : [];
|
|
767
|
+
}
|
|
768
|
+
if (!value || typeof value !== "object") return [];
|
|
769
|
+
return Object.entries(value).flatMap(([childKey, child]) =>
|
|
770
|
+
pathValues(child, childKey),
|
|
771
|
+
);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function isExcludedText(text) {
|
|
775
|
+
const cwd = /session_start cwd:\s*(.*)$/.exec(text)?.[1];
|
|
776
|
+
return cwd
|
|
777
|
+
? excludeGlobs.some((glob) =>
|
|
778
|
+
minimatch(normalizePath(cwd), glob, { nocase: true, dot: true }),
|
|
779
|
+
)
|
|
780
|
+
: false;
|
|
781
|
+
}
|
|
782
|
+
|
|
732
783
|
async function forEachLine(file, visitor) {
|
|
733
784
|
if (!fs.existsSync(file)) return;
|
|
734
785
|
const rl = readline.createInterface({
|
|
@@ -1129,6 +1180,7 @@ function buildReport(state) {
|
|
|
1129
1180
|
Object.entries(state.files).map(([key, list]) => [key, list.length]),
|
|
1130
1181
|
),
|
|
1131
1182
|
rowsSeen: state.seen.toJSON(),
|
|
1183
|
+
rowsExcluded: state.excludedRows,
|
|
1132
1184
|
parseErrors: state.parseErrors.toJSON(),
|
|
1133
1185
|
projects: state.projects.top(limit),
|
|
1134
1186
|
smells,
|
|
@@ -1232,6 +1284,7 @@ function printReport(report) {
|
|
|
1232
1284
|
.map(([k, v]) => `${k}=${v}`)
|
|
1233
1285
|
.join(", ")}`,
|
|
1234
1286
|
);
|
|
1287
|
+
console.log(`${report.rowsExcluded} rows excluded (synthetic corpora)`);
|
|
1235
1288
|
if (Object.keys(report.parseErrors).length)
|
|
1236
1289
|
console.log(`parse errors: ${JSON.stringify(report.parseErrors)}`);
|
|
1237
1290
|
|
|
@@ -111,6 +111,11 @@ predicates:
|
|
|
111
111
|
client.runQueryOnFile(queryDef, filePath, "typescript")
|
|
112
112
|
(TreeSitterClient compiles via the same WASM the runner uses.)
|
|
113
113
|
|
|
114
|
+
✅ For rule-bug fixes, also add a real-runner regression test through
|
|
115
|
+
treeSitterRunner.run() via makeRealRunnerCtx (tests/support/real-runner-ctx.ts) —
|
|
116
|
+
runQueryOnFile bypasses dispatch (skip_test_files, tiers, delta, rule cache).
|
|
117
|
+
Template: tests/clients/dispatch/runners/tree-sitter-skip-test-files.test.ts.
|
|
118
|
+
|
|
114
119
|
✅ JS files also run typescript/ rules (shared grammar) — one rule in
|
|
115
120
|
rules/tree-sitter-queries/typescript/ covers BOTH .ts and .js. No -js copy needed.
|
|
116
121
|
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import * as path from "node:path";
|
|
2
|
-
export class AstGrepParser {
|
|
3
|
-
getRuleDescription;
|
|
4
|
-
mapSeverity;
|
|
5
|
-
constructor(getRuleDescription, mapSeverity) {
|
|
6
|
-
this.getRuleDescription = getRuleDescription;
|
|
7
|
-
this.mapSeverity = mapSeverity;
|
|
8
|
-
}
|
|
9
|
-
parseOutput(output, filterFile) {
|
|
10
|
-
const resolvedFilterFile = path.resolve(filterFile);
|
|
11
|
-
try {
|
|
12
|
-
const items = JSON.parse(output);
|
|
13
|
-
if (Array.isArray(items)) {
|
|
14
|
-
return items
|
|
15
|
-
.map((item) => this.parseDiagnostic(item, resolvedFilterFile))
|
|
16
|
-
.filter((d) => d !== null);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
catch (err) {
|
|
20
|
-
void err;
|
|
21
|
-
}
|
|
22
|
-
return output
|
|
23
|
-
.split(/\r?\n/)
|
|
24
|
-
.filter((l) => l.trim())
|
|
25
|
-
.map((line) => {
|
|
26
|
-
try {
|
|
27
|
-
return this.parseDiagnostic(JSON.parse(line), resolvedFilterFile);
|
|
28
|
-
}
|
|
29
|
-
catch (err) {
|
|
30
|
-
void err;
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
})
|
|
34
|
-
.filter((d) => d !== null);
|
|
35
|
-
}
|
|
36
|
-
parseDiagnostic(item, filterFile) {
|
|
37
|
-
if (item.labels?.length) {
|
|
38
|
-
return this.parseNewFormat(item, filterFile);
|
|
39
|
-
}
|
|
40
|
-
if (item.spans?.length) {
|
|
41
|
-
return this.parseLegacyFormat(item, filterFile);
|
|
42
|
-
}
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
parseNewFormat(item, filterFile) {
|
|
46
|
-
const label = item.labels.find((l) => l.style === "primary") || item.labels[0];
|
|
47
|
-
const filePath = path.resolve(label.file || filterFile);
|
|
48
|
-
if (filePath !== filterFile)
|
|
49
|
-
return null;
|
|
50
|
-
const start = label.range?.start || { line: 0, column: 0 };
|
|
51
|
-
const end = label.range?.end || start;
|
|
52
|
-
return {
|
|
53
|
-
line: start.line + 1,
|
|
54
|
-
column: start.column,
|
|
55
|
-
endLine: end.line + 1,
|
|
56
|
-
endColumn: end.column,
|
|
57
|
-
severity: this.mapSeverity(item.severity),
|
|
58
|
-
message: item.message || "Unknown issue",
|
|
59
|
-
rule: item.ruleId || "unknown",
|
|
60
|
-
ruleDescription: this.getRuleDescription(item.ruleId || "unknown"),
|
|
61
|
-
file: filePath,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
parseLegacyFormat(item, filterFile) {
|
|
65
|
-
const span = item.spans?.[0];
|
|
66
|
-
if (!span)
|
|
67
|
-
return null;
|
|
68
|
-
const filePath = path.resolve(span.file || filterFile);
|
|
69
|
-
if (filePath !== filterFile)
|
|
70
|
-
return null;
|
|
71
|
-
const start = span.range?.start || { line: 0, column: 0 };
|
|
72
|
-
const end = span.range?.end || start;
|
|
73
|
-
const ruleId = item.name || item.ruleId || "unknown";
|
|
74
|
-
return {
|
|
75
|
-
line: start.line + 1,
|
|
76
|
-
column: start.column,
|
|
77
|
-
endLine: end.line + 1,
|
|
78
|
-
endColumn: end.column,
|
|
79
|
-
severity: this.mapSeverity(item.severity || item.Severity || "warning"),
|
|
80
|
-
message: item.Message?.text || item.message || "Unknown issue",
|
|
81
|
-
rule: ruleId,
|
|
82
|
-
ruleDescription: this.getRuleDescription(ruleId),
|
|
83
|
-
file: filePath,
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared parser for the `{ enabled?: boolean }` shape used by BOTH the global
|
|
3
|
-
* config (`clients/lens-config.ts`, `~/.pi-lens/config.json`) and the project
|
|
4
|
-
* config (`clients/project-lens-config.ts`, `.pi-lens.json`) for their
|
|
5
|
-
* mutation-control keys (`format`, `autofix`, `actionableWarnings.autoFix`).
|
|
6
|
-
*
|
|
7
|
-
* Extracted (#792) so both loaders parse and warn on the identical shape
|
|
8
|
-
* identically instead of two independent hand-rolled implementations that had
|
|
9
|
-
* diverged in strictness — project warned on invalid `enabled` values via its
|
|
10
|
-
* own `warnInvalidConfigOnce`, global silently dropped them. This module has
|
|
11
|
-
* no dependency on either config module (avoids an import cycle) — callers
|
|
12
|
-
* supply their own `warnInvalid` callback so each config keeps its own
|
|
13
|
-
* warn-once plumbing (keyed by its own config path).
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* Parse a raw `{ enabled?: boolean }` value.
|
|
17
|
-
*
|
|
18
|
-
* - `undefined` input → `undefined` (key absent from the config).
|
|
19
|
-
* - Non-object (or array) input → `warnInvalid` is called, returns `undefined`.
|
|
20
|
-
* - Object with no `enabled` key → `{}` (present but nothing to say).
|
|
21
|
-
* - `enabled` present but not a boolean → `warnInvalid` is called, returns `{}`.
|
|
22
|
-
* - `enabled` a boolean → `{ enabled }`.
|
|
23
|
-
*/
|
|
24
|
-
export function parseEnabledShape(value, fieldPath, warnInvalid) {
|
|
25
|
-
if (value === undefined)
|
|
26
|
-
return undefined;
|
|
27
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
28
|
-
warnInvalid(`${fieldPath} must be an object`);
|
|
29
|
-
return undefined;
|
|
30
|
-
}
|
|
31
|
-
const raw = value;
|
|
32
|
-
if (!("enabled" in raw))
|
|
33
|
-
return {};
|
|
34
|
-
if (typeof raw.enabled !== "boolean") {
|
|
35
|
-
warnInvalid(`${fieldPath}.enabled must be a boolean`);
|
|
36
|
-
return {};
|
|
37
|
-
}
|
|
38
|
-
return { enabled: raw.enabled };
|
|
39
|
-
}
|