pi-lens 3.8.21 → 3.8.23

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.
Files changed (92) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +2 -0
  3. package/clients/dispatch/dispatcher.ts +75 -91
  4. package/clients/dispatch/fact-provider-types.ts +22 -0
  5. package/clients/dispatch/fact-rule-runner.ts +22 -0
  6. package/clients/dispatch/fact-runner.ts +28 -0
  7. package/clients/dispatch/fact-scheduler.ts +78 -0
  8. package/clients/dispatch/fact-store.ts +67 -0
  9. package/clients/dispatch/facts/comment-facts.ts +59 -0
  10. package/clients/dispatch/facts/file-content.ts +20 -0
  11. package/clients/dispatch/facts/function-facts.ts +177 -0
  12. package/clients/dispatch/facts/try-catch-facts.ts +80 -0
  13. package/clients/dispatch/integration.ts +130 -24
  14. package/clients/dispatch/priorities.ts +22 -0
  15. package/clients/dispatch/rules/async-noise.ts +43 -0
  16. package/clients/dispatch/rules/error-obscuring.ts +40 -0
  17. package/clients/dispatch/rules/error-swallowing.ts +35 -0
  18. package/clients/dispatch/rules/pass-through-wrappers.ts +52 -0
  19. package/clients/dispatch/rules/placeholder-comments.ts +47 -0
  20. package/clients/dispatch/runners/architect.ts +2 -1
  21. package/clients/dispatch/runners/ast-grep-napi.ts +2 -1
  22. package/clients/dispatch/runners/biome-check.ts +40 -8
  23. package/clients/dispatch/runners/biome.ts +2 -1
  24. package/clients/dispatch/runners/eslint.ts +34 -6
  25. package/clients/dispatch/runners/go-vet.ts +2 -1
  26. package/clients/dispatch/runners/golangci-lint.ts +2 -1
  27. package/clients/dispatch/runners/index.ts +29 -27
  28. package/clients/dispatch/runners/lsp.ts +60 -4
  29. package/clients/dispatch/runners/oxlint.ts +2 -1
  30. package/clients/dispatch/runners/pyright.ts +2 -1
  31. package/clients/dispatch/runners/python-slop.ts +2 -1
  32. package/clients/dispatch/runners/rubocop.ts +2 -1
  33. package/clients/dispatch/runners/ruff.ts +2 -1
  34. package/clients/dispatch/runners/rust-clippy.ts +2 -1
  35. package/clients/dispatch/runners/shellcheck.ts +2 -1
  36. package/clients/dispatch/runners/similarity.ts +2 -1
  37. package/clients/dispatch/runners/spellcheck.ts +2 -1
  38. package/clients/dispatch/runners/sqlfluff.ts +2 -1
  39. package/clients/dispatch/runners/tree-sitter.ts +469 -1
  40. package/clients/dispatch/runners/ts-lsp.ts +2 -1
  41. package/clients/dispatch/runners/type-safety.ts +2 -1
  42. package/clients/dispatch/runners/yamllint.ts +2 -1
  43. package/clients/dispatch/tool-profile.ts +40 -0
  44. package/clients/dispatch/types.ts +3 -13
  45. package/clients/lsp/client.ts +366 -12
  46. package/clients/lsp/index.ts +374 -76
  47. package/clients/lsp/launch.ts +42 -2
  48. package/clients/lsp/server.ts +186 -12
  49. package/clients/pipeline.ts +2 -2
  50. package/clients/runtime-context.ts +2 -2
  51. package/clients/runtime-session.ts +43 -5
  52. package/clients/session-summary.ts +21 -0
  53. package/clients/tree-sitter-client.ts +162 -0
  54. package/clients/tree-sitter-logger.ts +47 -0
  55. package/clients/tree-sitter-query-loader.ts +13 -2
  56. package/index.ts +67 -17
  57. package/package.json +3 -1
  58. package/rules/rule-catalog.json +64 -0
  59. package/rules/tree-sitter-queries/go/go-bare-error.yml +19 -7
  60. package/rules/tree-sitter-queries/go/go-command-injection.yml +55 -0
  61. package/rules/tree-sitter-queries/go/go-direct-panic.yml +45 -0
  62. package/rules/tree-sitter-queries/go/go-empty-if-err.yml +47 -0
  63. package/rules/tree-sitter-queries/go/go-goroutine-loop-capture.yml +49 -0
  64. package/rules/tree-sitter-queries/go/go-ignored-call-result.yml +51 -0
  65. package/rules/tree-sitter-queries/go/go-insecure-random.yml +51 -0
  66. package/rules/tree-sitter-queries/go/go-log-fatal.yml +49 -0
  67. package/rules/tree-sitter-queries/go/go-path-traversal.yml +51 -0
  68. package/rules/tree-sitter-queries/go/go-shared-map-write-goroutine.yml +54 -0
  69. package/rules/tree-sitter-queries/go/go-sql-injection.yml +55 -0
  70. package/rules/tree-sitter-queries/go/go-weak-hash.yml +51 -0
  71. package/rules/tree-sitter-queries/python/python-command-injection.yml +63 -0
  72. package/rules/tree-sitter-queries/python/python-insecure-deserialization.yml +48 -0
  73. package/rules/tree-sitter-queries/python/python-insecure-random.yml +51 -0
  74. package/rules/tree-sitter-queries/python/python-path-traversal.yml +55 -0
  75. package/rules/tree-sitter-queries/python/python-sql-injection.yml +47 -0
  76. package/rules/tree-sitter-queries/python/python-ssrf.yml +50 -0
  77. package/rules/tree-sitter-queries/python/python-thread-global-write.yml +58 -0
  78. package/rules/tree-sitter-queries/python/python-weak-hash.yml +51 -0
  79. package/rules/tree-sitter-queries/ruby/ruby-command-injection.yml +56 -0
  80. package/rules/tree-sitter-queries/ruby/ruby-insecure-deserialization.yml +47 -0
  81. package/rules/tree-sitter-queries/ruby/ruby-insecure-random.yml +54 -0
  82. package/rules/tree-sitter-queries/ruby/ruby-weak-hash.yml +50 -0
  83. package/rules/tree-sitter-queries/rust/rust-lock-held-across-await.yml +59 -0
  84. package/rules/tree-sitter-queries/typescript/ts-command-injection.yml +60 -0
  85. package/rules/tree-sitter-queries/typescript/ts-detached-async-call.yml +56 -0
  86. package/rules/tree-sitter-queries/typescript/ts-insecure-random.yml +54 -0
  87. package/rules/tree-sitter-queries/typescript/ts-ssrf.yml +53 -0
  88. package/rules/tree-sitter-queries/typescript/ts-weak-hash.yml +54 -0
  89. package/scripts/validate-rule-catalog.mjs +227 -0
  90. package/skills/lsp-navigation/SKILL.md +15 -3
  91. package/tools/lsp-navigation.js +466 -79
  92. package/tools/lsp-navigation.ts +587 -85
@@ -0,0 +1,56 @@
1
+ # Ruby Security
2
+ # Detects shell execution sinks frequently involved in command injection.
3
+ id: ruby-command-injection
4
+ name: Command Injection Sink
5
+ severity: warning
6
+ category: security
7
+ defect_class: injection
8
+ inline_tier: warning
9
+ language: ruby
10
+
11
+ message: "Potential command injection sink — avoid shell execution with untrusted input"
12
+
13
+ description: |
14
+ Ruby shell execution APIs (`system`, `exec`, `spawn`, backticks) can execute
15
+ user-controlled command strings.
16
+
17
+ ✅ FIX: avoid shell interpolation and use safer APIs with strict allowlists.
18
+
19
+ query: |
20
+ (call
21
+ method: (identifier) @FN
22
+ arguments: (argument_list) @ARGS)
23
+ (#match? @FN "^(system|exec|spawn|popen|capture3|capture2|capture2e)$")
24
+
25
+ (command
26
+ method: (identifier) @FN
27
+ argument: (_) @ARGS)
28
+ (#match? @FN "^(system|exec|spawn|popen)$")
29
+
30
+ (call_expression
31
+ receiver: (constant) @NS
32
+ method: (identifier) @FN
33
+ arguments: (argument_list) @ARGS)
34
+ (#match? @FN "^(system|exec|spawn|popen|capture3|capture2|capture2e)$")
35
+
36
+ metavars:
37
+ - FN
38
+ - ARGS
39
+
40
+ post_filter: ruby_command_injection_sink
41
+
42
+ has_fix: false
43
+
44
+ tags:
45
+ - ruby
46
+ - security
47
+ - command-injection
48
+ - cwe-78
49
+ - owasp-a03
50
+
51
+ examples:
52
+ bad: |
53
+ system("sh -c #{params[:cmd]}")
54
+
55
+ good: |
56
+ Open3.capture3("git", "status")
@@ -0,0 +1,47 @@
1
+ # Ruby Security
2
+ # Detects unsafe deserialization APIs.
3
+ id: ruby-insecure-deserialization
4
+ name: Insecure Deserialization
5
+ severity: warning
6
+ category: security
7
+ defect_class: injection
8
+ inline_tier: warning
9
+ language: ruby
10
+
11
+ message: "Potential insecure deserialization sink — avoid unsafe loaders"
12
+
13
+ description: |
14
+ Deserializing untrusted data with Marshal/YAML loaders can enable code execution.
15
+
16
+ ✅ FIX: use safe serialization formats and strict schema validation.
17
+
18
+ query: |
19
+ (call_expression
20
+ receiver: (constant) @MOD
21
+ method: (identifier) @FN
22
+ arguments: (argument_list (_) @DATA))
23
+ (#match? @MOD "^(Marshal|YAML|Psych)$")
24
+ (#match? @FN "^(load|unsafe_load)$")
25
+
26
+ metavars:
27
+ - MOD
28
+ - FN
29
+ - DATA
30
+
31
+ post_filter: ruby_insecure_deserialization_sink
32
+
33
+ has_fix: false
34
+
35
+ tags:
36
+ - ruby
37
+ - security
38
+ - deserialization
39
+ - cwe-502
40
+ - owasp-a08
41
+
42
+ examples:
43
+ bad: |
44
+ Marshal.load(payload)
45
+
46
+ good: |
47
+ JSON.parse(payload)
@@ -0,0 +1,54 @@
1
+ # Ruby Security
2
+ # Detects non-cryptographic randomness usage.
3
+ id: ruby-insecure-random
4
+ name: Insecure Randomness
5
+ severity: warning
6
+ category: security
7
+ defect_class: injection
8
+ inline_tier: warning
9
+ language: ruby
10
+
11
+ message: "Insecure randomness source detected — use SecureRandom for security-sensitive values"
12
+
13
+ description: |
14
+ Kernel.rand/Random.new are not suitable for security-sensitive tokens.
15
+
16
+ ✅ FIX: use SecureRandom.hex/base64/uuid.
17
+
18
+ query: |
19
+ [
20
+ (call
21
+ method: (identifier) @FN
22
+ arguments: (argument_list) @ARGS)
23
+ (call_expression
24
+ receiver: (constant) @MOD
25
+ method: (identifier) @FN
26
+ arguments: (argument_list) @ARGS)
27
+ ]
28
+ (#match? @FN "^(rand|srand)$")
29
+
30
+ metavars:
31
+ - MOD
32
+ - FN
33
+ - ARGS
34
+
35
+ cwe:
36
+ - CWE-330
37
+ owasp:
38
+ - A02
39
+ confidence: medium
40
+
41
+ has_fix: false
42
+
43
+ tags:
44
+ - ruby
45
+ - security
46
+ - randomness
47
+ - weak-prng
48
+
49
+ examples:
50
+ bad: |
51
+ token = rand(10_000_000)
52
+
53
+ good: |
54
+ token = SecureRandom.hex(16)
@@ -0,0 +1,50 @@
1
+ # Ruby Security
2
+ # Detects weak digest algorithm usage.
3
+ id: ruby-weak-hash
4
+ name: Weak Hash Primitive
5
+ severity: warning
6
+ category: security
7
+ defect_class: injection
8
+ inline_tier: warning
9
+ language: ruby
10
+
11
+ message: "Weak hash primitive detected (MD5/SHA1) — use SHA-256+ for security-sensitive contexts"
12
+
13
+ description: |
14
+ Digest::MD5 and Digest::SHA1 are not suitable for secure hashing.
15
+
16
+ ✅ FIX: use Digest::SHA256 or stronger algorithms.
17
+
18
+ query: |
19
+ (call_expression
20
+ receiver: (constant) @MOD
21
+ method: (identifier) @FN
22
+ arguments: (argument_list) @ARGS)
23
+ (#match? @MOD "^(Digest::MD5|Digest::SHA1)$")
24
+ (#match? @FN "^(hexdigest|digest|base64digest)$")
25
+
26
+ metavars:
27
+ - MOD
28
+ - FN
29
+ - ARGS
30
+
31
+ cwe:
32
+ - CWE-327
33
+ owasp:
34
+ - A02
35
+ confidence: high
36
+
37
+ has_fix: false
38
+
39
+ tags:
40
+ - ruby
41
+ - security
42
+ - crypto
43
+ - weak-hash
44
+
45
+ examples:
46
+ bad: |
47
+ Digest::MD5.hexdigest(data)
48
+
49
+ good: |
50
+ Digest::SHA256.hexdigest(data)
@@ -0,0 +1,59 @@
1
+ # Rust Concurrency
2
+ # Detects lock guards obtained via lock().await and additional await in same block.
3
+ id: rust-lock-held-across-await
4
+ name: Lock Held Across Await
5
+ severity: warning
6
+ category: concurrency
7
+ defect_class: async-misuse
8
+ inline_tier: warning
9
+ language: rust
10
+
11
+ message: "Lock guard may be held across await — release lock before awaiting other work"
12
+
13
+ description: |
14
+ Awaiting while holding a mutex guard can cause contention and deadlocks.
15
+
16
+ ✅ FIX: limit lock scope, clone needed data, then await outside lock lifetime.
17
+
18
+ query: |
19
+ (block
20
+ (let_declaration
21
+ pattern: (identifier) @GUARD
22
+ value: (await_expression
23
+ expression: (call_expression
24
+ function: (field_expression
25
+ field: (field_identifier) @LOCKFN))))
26
+ (_)*
27
+ (await_expression) @LATER_AWAIT)
28
+ (#eq? @LOCKFN "lock")
29
+
30
+ metavars:
31
+ - GUARD
32
+ - LOCKFN
33
+ - LATER_AWAIT
34
+
35
+ cwe:
36
+ - CWE-833
37
+ owasp:
38
+ - A09
39
+ confidence: low
40
+
41
+ has_fix: false
42
+
43
+ tags:
44
+ - rust
45
+ - concurrency
46
+ - mutex
47
+ - async
48
+
49
+ examples:
50
+ bad: |
51
+ let guard = state.lock().await;
52
+ do_network().await;
53
+
54
+ good: |
55
+ {
56
+ let guard = state.lock().await;
57
+ update(&guard);
58
+ }
59
+ do_network().await;
@@ -0,0 +1,60 @@
1
+ # JS/TS Security
2
+ # Detects command execution sinks via child_process APIs.
3
+ id: ts-command-injection
4
+ name: Command Injection Sink
5
+ severity: warning
6
+ category: security
7
+ defect_class: injection
8
+ inline_tier: warning
9
+ language: typescript
10
+
11
+ message: "Potential command injection sink — avoid child_process command execution with untrusted input"
12
+
13
+ description: |
14
+ child_process command APIs (`exec`, `execSync`) execute shell commands and are
15
+ vulnerable when command strings include untrusted input.
16
+
17
+ ✅ FIX: prefer `spawn`/`execFile` with explicit argument arrays and strict allowlists.
18
+
19
+ query: |
20
+ [
21
+ (call_expression
22
+ function: (member_expression
23
+ object: (identifier) @MOD
24
+ property: (property_identifier) @FN)
25
+ arguments: (arguments) @ARGS)
26
+ (call_expression
27
+ function: (member_expression
28
+ object: (member_expression
29
+ object: (identifier) @MOD
30
+ property: (property_identifier) @NS)
31
+ property: (property_identifier) @FN)
32
+ arguments: (arguments) @ARGS)
33
+ ]
34
+ (#eq? @MOD "child_process")
35
+ (#match? @FN "^(exec|execSync)$")
36
+
37
+ metavars:
38
+ - MOD
39
+ - NS
40
+ - FN
41
+ - ARGS
42
+
43
+ post_filter: ts_command_injection_sink
44
+
45
+ has_fix: false
46
+
47
+ tags:
48
+ - javascript
49
+ - typescript
50
+ - security
51
+ - command-injection
52
+ - cwe-78
53
+ - owasp-a03
54
+
55
+ examples:
56
+ bad: |
57
+ child_process.exec(userInput)
58
+
59
+ good: |
60
+ spawn("git", ["status"])
@@ -0,0 +1,56 @@
1
+ # JS/TS Concurrency
2
+ # Detects detached async/suspicious promise calls used as bare statements.
3
+ id: ts-detached-async-call
4
+ name: Detached Async Call
5
+ severity: warning
6
+ category: concurrency
7
+ defect_class: async-misuse
8
+ inline_tier: warning
9
+ language: typescript
10
+
11
+ message: "Detached async call — ensure this Promise is awaited or explicitly handled"
12
+
13
+ description: |
14
+ Bare async calls can drop errors and cause race conditions when results are ignored.
15
+
16
+ ✅ FIX: await the call, return the promise, or explicitly handle it with .catch/.then.
17
+
18
+ query: |
19
+ (expression_statement
20
+ (call_expression
21
+ function: [
22
+ (identifier) @FN
23
+ (member_expression
24
+ property: (property_identifier) @FN)
25
+ ]
26
+ arguments: (arguments) @ARGS))
27
+ (#match? @FN "(Async$|fetch$|request$)")
28
+
29
+ metavars:
30
+ - FN
31
+ - ARGS
32
+
33
+ post_filter: ts_detached_async_call
34
+
35
+ cwe:
36
+ - CWE-703
37
+ owasp:
38
+ - A09
39
+ confidence: medium
40
+
41
+ has_fix: false
42
+
43
+ tags:
44
+ - javascript
45
+ - typescript
46
+ - concurrency
47
+ - async
48
+
49
+ examples:
50
+ bad: |
51
+ fetch(url)
52
+ saveAsync(record)
53
+
54
+ good: |
55
+ await fetch(url)
56
+ await saveAsync(record)
@@ -0,0 +1,54 @@
1
+ # JS/TS Security
2
+ # Detects non-cryptographic randomness usage.
3
+ id: ts-insecure-random
4
+ name: Insecure Randomness
5
+ severity: warning
6
+ category: security
7
+ defect_class: injection
8
+ inline_tier: warning
9
+ language: typescript
10
+
11
+ message: "Insecure randomness source detected — use crypto.getRandomValues or secure RNG APIs"
12
+
13
+ description: |
14
+ Math.random is not suitable for security-sensitive tokens and identifiers.
15
+
16
+ ✅ FIX: use crypto.getRandomValues / crypto.randomUUID / secure server-side RNG.
17
+
18
+ query: |
19
+ (call_expression
20
+ function: (member_expression
21
+ object: (identifier) @OBJ
22
+ property: (property_identifier) @FN)
23
+ arguments: (arguments) @ARGS)
24
+ (#eq? @OBJ "Math")
25
+ (#eq? @FN "random")
26
+
27
+ metavars:
28
+ - OBJ
29
+ - FN
30
+ - ARGS
31
+
32
+ post_filter: ts_insecure_random_source
33
+
34
+ cwe:
35
+ - CWE-330
36
+ owasp:
37
+ - A02
38
+ confidence: medium
39
+
40
+ has_fix: false
41
+
42
+ tags:
43
+ - javascript
44
+ - typescript
45
+ - security
46
+ - randomness
47
+ - weak-prng
48
+
49
+ examples:
50
+ bad: |
51
+ const token = Math.random().toString(36)
52
+
53
+ good: |
54
+ const token = crypto.randomUUID()
@@ -0,0 +1,53 @@
1
+ # JS/TS Security
2
+ # Detects outbound HTTP sinks invoked with dynamic URL expressions.
3
+ id: ts-ssrf
4
+ name: SSRF Risk
5
+ severity: warning
6
+ category: security
7
+ defect_class: injection
8
+ inline_tier: warning
9
+ language: typescript
10
+
11
+ message: "Potential SSRF sink — validate and allowlist outbound URLs"
12
+
13
+ description: |
14
+ Outbound requests with untrusted URL input can lead to server-side request forgery.
15
+
16
+ ✅ FIX: validate URL host/scheme and allowlist external targets.
17
+
18
+ query: |
19
+ [
20
+ (call_expression
21
+ function: (identifier) @FN
22
+ arguments: (arguments [(identifier) (member_expression) (call_expression)] @URL))
23
+ (call_expression
24
+ function: (member_expression
25
+ object: (identifier) @OBJ
26
+ property: (property_identifier) @FN)
27
+ arguments: (arguments [(identifier) (member_expression) (call_expression)] @URL))
28
+ ]
29
+ (#match? @FN "^(fetch|get|post|put|patch|delete|request)$")
30
+
31
+ metavars:
32
+ - OBJ
33
+ - FN
34
+ - URL
35
+
36
+ post_filter: ts_ssrf_sink
37
+
38
+ has_fix: false
39
+
40
+ tags:
41
+ - javascript
42
+ - typescript
43
+ - security
44
+ - ssrf
45
+ - cwe-918
46
+ - owasp-a10
47
+
48
+ examples:
49
+ bad: |
50
+ await fetch(userUrl)
51
+
52
+ good: |
53
+ if (ALLOWED_HOSTS.has(url.host)) await fetch(url.toString())
@@ -0,0 +1,54 @@
1
+ # JS/TS Security
2
+ # Detects weak hash algorithm selection in crypto hashing APIs.
3
+ id: ts-weak-hash
4
+ name: Weak Hash Primitive
5
+ severity: warning
6
+ category: security
7
+ defect_class: injection
8
+ inline_tier: warning
9
+ language: typescript
10
+
11
+ message: "Weak hash primitive selected (md5/sha1) — use sha256+ for security-sensitive contexts"
12
+
13
+ description: |
14
+ Using MD5/SHA1 in cryptographic hashing contexts is insecure.
15
+
16
+ ✅ FIX: use SHA-256 or stronger algorithms.
17
+
18
+ query: |
19
+ (call_expression
20
+ function: (member_expression
21
+ property: (property_identifier) @FN)
22
+ arguments: (arguments
23
+ (string (string_fragment) @ALG)
24
+ (_)*))
25
+ (#eq? @FN "createHash")
26
+ (#match? @ALG "^(md5|sha1)$")
27
+
28
+ metavars:
29
+ - FN
30
+ - ALG
31
+
32
+ post_filter: ts_weak_hash_algorithm
33
+
34
+ cwe:
35
+ - CWE-327
36
+ owasp:
37
+ - A02
38
+ confidence: high
39
+
40
+ has_fix: false
41
+
42
+ tags:
43
+ - javascript
44
+ - typescript
45
+ - security
46
+ - crypto
47
+ - weak-hash
48
+
49
+ examples:
50
+ bad: |
51
+ const hash = crypto.createHash("md5").update(data).digest("hex")
52
+
53
+ good: |
54
+ const hash = crypto.createHash("sha256").update(data).digest("hex")