@critiq/rules 0.0.1

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 (121) hide show
  1. package/README.md +169 -0
  2. package/catalog.yaml +599 -0
  3. package/package.json +21 -0
  4. package/rules/shared/security.insecure-http-transport.rule.yaml +42 -0
  5. package/rules/shared/security.no-command-execution-with-request-input.rule.yaml +42 -0
  6. package/rules/shared/security.no-hardcoded-credentials.rule.yaml +42 -0
  7. package/rules/shared/security.no-request-path-file-read.rule.yaml +42 -0
  8. package/rules/shared/security.no-sensitive-data-in-logs-and-telemetry.rule.yaml +44 -0
  9. package/rules/shared/security.no-sql-interpolation.rule.yaml +42 -0
  10. package/rules/shared/security.tls-verification-disabled.rule.yaml +42 -0
  11. package/rules/shared/security.unsafe-deserialization.rule.yaml +41 -0
  12. package/rules/shared/security.weak-hash-algorithm.rule.yaml +41 -0
  13. package/rules/typescript/ts.config.no-process-env-outside-config.rule.yaml +37 -0
  14. package/rules/typescript/ts.correctness.blocking-call-in-async-flow.rule.yaml +35 -0
  15. package/rules/typescript/ts.correctness.constant-condition.rule.yaml +35 -0
  16. package/rules/typescript/ts.correctness.implicit-undefined-return.rule.yaml +34 -0
  17. package/rules/typescript/ts.correctness.incorrect-boolean-logic.rule.yaml +35 -0
  18. package/rules/typescript/ts.correctness.missing-await-on-async-call.rule.yaml +35 -0
  19. package/rules/typescript/ts.correctness.missing-default-dispatch.rule.yaml +35 -0
  20. package/rules/typescript/ts.correctness.missing-timeout-on-external-call.rule.yaml +35 -0
  21. package/rules/typescript/ts.correctness.nested-property-access-without-check.rule.yaml +35 -0
  22. package/rules/typescript/ts.correctness.off-by-one-loop-boundary.rule.yaml +35 -0
  23. package/rules/typescript/ts.correctness.optional-value-without-fallback.rule.yaml +35 -0
  24. package/rules/typescript/ts.correctness.possible-null-dereference.rule.yaml +35 -0
  25. package/rules/typescript/ts.correctness.shared-state-race.rule.yaml +35 -0
  26. package/rules/typescript/ts.correctness.unchecked-map-key-access.rule.yaml +35 -0
  27. package/rules/typescript/ts.correctness.unhandled-async-error.rule.yaml +35 -0
  28. package/rules/typescript/ts.correctness.unreachable-statement.rule.yaml +40 -0
  29. package/rules/typescript/ts.logging.no-console-error.rule.yaml +34 -0
  30. package/rules/typescript/ts.logging.no-console-log.rule.yaml +34 -0
  31. package/rules/typescript/ts.next.no-server-client-boundary-leaks.rule.yaml +36 -0
  32. package/rules/typescript/ts.performance.inefficient-data-structure-usage.rule.yaml +35 -0
  33. package/rules/typescript/ts.performance.large-payload-without-streaming.rule.yaml +35 -0
  34. package/rules/typescript/ts.performance.missing-batch-operations.rule.yaml +35 -0
  35. package/rules/typescript/ts.performance.nested-loops-hot-path.rule.yaml +35 -0
  36. package/rules/typescript/ts.performance.repeated-expensive-computation.rule.yaml +35 -0
  37. package/rules/typescript/ts.performance.repeated-io-in-loop.rule.yaml +35 -0
  38. package/rules/typescript/ts.performance.retained-large-object.rule.yaml +35 -0
  39. package/rules/typescript/ts.performance.sequential-async-calls.rule.yaml +35 -0
  40. package/rules/typescript/ts.performance.unbounded-growth-memory-leak.rule.yaml +35 -0
  41. package/rules/typescript/ts.performance.unnecessary-rerenders-from-state-misuse.rule.yaml +35 -0
  42. package/rules/typescript/ts.quality.deep-nesting.rule.yaml +35 -0
  43. package/rules/typescript/ts.quality.duplicate-code-block.rule.yaml +35 -0
  44. package/rules/typescript/ts.quality.function-too-large-or-complex.rule.yaml +35 -0
  45. package/rules/typescript/ts.quality.hardcoded-configuration-values.rule.yaml +35 -0
  46. package/rules/typescript/ts.quality.logic-change-without-test-updates.rule.yaml +36 -0
  47. package/rules/typescript/ts.quality.magic-numbers-or-strings.rule.yaml +35 -0
  48. package/rules/typescript/ts.quality.missing-error-context.rule.yaml +35 -0
  49. package/rules/typescript/ts.quality.missing-tests-for-critical-logic.rule.yaml +35 -0
  50. package/rules/typescript/ts.quality.swallowed-error.rule.yaml +35 -0
  51. package/rules/typescript/ts.quality.tight-module-coupling.rule.yaml +35 -0
  52. package/rules/typescript/ts.random.no-math-random-in-core.rule.yaml +37 -0
  53. package/rules/typescript/ts.react.no-cascaded-effect-fetches.rule.yaml +37 -0
  54. package/rules/typescript/ts.runtime.no-debugger-statement.rule.yaml +29 -0
  55. package/rules/typescript/ts.security.bind-to-all-interfaces.rule.yaml +36 -0
  56. package/rules/typescript/ts.security.browser-token-storage.rule.yaml +37 -0
  57. package/rules/typescript/ts.security.dangerous-insert-html.rule.yaml +36 -0
  58. package/rules/typescript/ts.security.dangerously-set-inner-html.rule.yaml +38 -0
  59. package/rules/typescript/ts.security.datadog-browser-track-user-interactions.rule.yaml +37 -0
  60. package/rules/typescript/ts.security.debug-mode-enabled.rule.yaml +38 -0
  61. package/rules/typescript/ts.security.dynamodb-query-injection.rule.yaml +36 -0
  62. package/rules/typescript/ts.security.exposed-directory-listing.rule.yaml +37 -0
  63. package/rules/typescript/ts.security.express-cookie-missing-http-only.rule.yaml +36 -0
  64. package/rules/typescript/ts.security.express-default-cookie-config.rule.yaml +39 -0
  65. package/rules/typescript/ts.security.express-default-session-config.rule.yaml +37 -0
  66. package/rules/typescript/ts.security.express-insecure-cookie.rule.yaml +36 -0
  67. package/rules/typescript/ts.security.express-missing-helmet.rule.yaml +37 -0
  68. package/rules/typescript/ts.security.express-nosql-injection.rule.yaml +36 -0
  69. package/rules/typescript/ts.security.express-permissive-cookie-config.rule.yaml +38 -0
  70. package/rules/typescript/ts.security.express-reduce-fingerprint.rule.yaml +37 -0
  71. package/rules/typescript/ts.security.express-static-assets-after-session.rule.yaml +37 -0
  72. package/rules/typescript/ts.security.external-file-upload.rule.yaml +36 -0
  73. package/rules/typescript/ts.security.file-generation.rule.yaml +36 -0
  74. package/rules/typescript/ts.security.format-string-using-user-input.rule.yaml +36 -0
  75. package/rules/typescript/ts.security.frontend-only-authorization.rule.yaml +35 -0
  76. package/rules/typescript/ts.security.handlebars-no-escape.rule.yaml +38 -0
  77. package/rules/typescript/ts.security.hardcoded-auth-secret.rule.yaml +37 -0
  78. package/rules/typescript/ts.security.import-using-user-input.rule.yaml +36 -0
  79. package/rules/typescript/ts.security.information-leakage.rule.yaml +38 -0
  80. package/rules/typescript/ts.security.insecure-allow-origin.rule.yaml +36 -0
  81. package/rules/typescript/ts.security.insecure-auth-cookie-flags.rule.yaml +37 -0
  82. package/rules/typescript/ts.security.insecure-password-hash-configuration.rule.yaml +37 -0
  83. package/rules/typescript/ts.security.insecure-websocket-transport.rule.yaml +37 -0
  84. package/rules/typescript/ts.security.insufficiently-random-values.rule.yaml +36 -0
  85. package/rules/typescript/ts.security.jwt-not-revoked.rule.yaml +37 -0
  86. package/rules/typescript/ts.security.jwt-sensitive-claims.rule.yaml +37 -0
  87. package/rules/typescript/ts.security.manual-html-sanitization.rule.yaml +37 -0
  88. package/rules/typescript/ts.security.missing-authorization-before-sensitive-action.rule.yaml +35 -0
  89. package/rules/typescript/ts.security.missing-integrity-check.rule.yaml +36 -0
  90. package/rules/typescript/ts.security.missing-message-origin-check.rule.yaml +36 -0
  91. package/rules/typescript/ts.security.missing-ownership-validation.rule.yaml +35 -0
  92. package/rules/typescript/ts.security.missing-request-timeout-or-retry.rule.yaml +35 -0
  93. package/rules/typescript/ts.security.no-dynamic-execution.rule.yaml +34 -0
  94. package/rules/typescript/ts.security.no-innerhtml-assignment.rule.yaml +36 -0
  95. package/rules/typescript/ts.security.non-literal-fs-filename.rule.yaml +36 -0
  96. package/rules/typescript/ts.security.observable-timing-discrepancy.rule.yaml +37 -0
  97. package/rules/typescript/ts.security.open-redirect.rule.yaml +37 -0
  98. package/rules/typescript/ts.security.permissive-allow-origin.rule.yaml +36 -0
  99. package/rules/typescript/ts.security.permissive-file-permissions.rule.yaml +37 -0
  100. package/rules/typescript/ts.security.postmessage-wildcard-origin.rule.yaml +36 -0
  101. package/rules/typescript/ts.security.predictable-token-generation.rule.yaml +36 -0
  102. package/rules/typescript/ts.security.raw-html-using-user-input.rule.yaml +37 -0
  103. package/rules/typescript/ts.security.sensitive-data-egress.rule.yaml +36 -0
  104. package/rules/typescript/ts.security.sensitive-data-in-exception.rule.yaml +37 -0
  105. package/rules/typescript/ts.security.sensitive-data-written-to-file.rule.yaml +37 -0
  106. package/rules/typescript/ts.security.ssrf.rule.yaml +34 -0
  107. package/rules/typescript/ts.security.token-or-session-not-validated.rule.yaml +35 -0
  108. package/rules/typescript/ts.security.ui-redress.rule.yaml +37 -0
  109. package/rules/typescript/ts.security.unsanitized-http-response.rule.yaml +36 -0
  110. package/rules/typescript/ts.security.unvalidated-external-input.rule.yaml +35 -0
  111. package/rules/typescript/ts.security.user-controlled-sendfile.rule.yaml +36 -0
  112. package/rules/typescript/ts.security.user-controlled-view-render.rule.yaml +36 -0
  113. package/rules/typescript/ts.security.weak-cipher-or-mode.rule.yaml +35 -0
  114. package/rules/typescript/ts.security.weak-key-strength.rule.yaml +36 -0
  115. package/rules/typescript/ts.security.weak-tls-version.rule.yaml +36 -0
  116. package/src/index.d.ts +1 -0
  117. package/src/index.js +5 -0
  118. package/src/index.js.map +1 -0
  119. package/src/lib/rules-package.d.ts +3 -0
  120. package/src/lib/rules-package.js +16 -0
  121. package/src/lib/rules-package.js.map +1 -0
@@ -0,0 +1,42 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: security.no-hardcoded-credentials
5
+ title: Hardcoded API keys or credentials
6
+ summary: Source files should not embed credential-like string literals.
7
+ rationale: Hardcoded credentials are difficult to rotate and are easily leaked through source control.
8
+ tags:
9
+ - security
10
+ - secrets
11
+ - credentials
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: file
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ - go
20
+ - python
21
+ - java
22
+ - php
23
+ - ruby
24
+ - rust
25
+ match:
26
+ fact:
27
+ kind: security.hardcoded-credentials
28
+ bind: credential
29
+ emit:
30
+ finding:
31
+ category: security.secrets
32
+ severity: critical
33
+ confidence: 0.95
34
+ tags:
35
+ - security
36
+ - secrets
37
+ - credentials
38
+ message:
39
+ title: Avoid hardcoded credentials in `${captures.credential.text}`
40
+ summary: "`${captures.credential.text}` appears to embed a credential-like literal in source code."
41
+ remediation:
42
+ summary: Move the secret to a secure runtime secret store or environment-backed config path.
@@ -0,0 +1,42 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: security.no-request-path-file-read
5
+ title: Path traversal via user input
6
+ summary: File access calls must not use request-controlled paths directly.
7
+ rationale: User-controlled paths can escape the intended directory and expose sensitive files.
8
+ tags:
9
+ - security
10
+ - filesystem
11
+ - path-traversal
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ - go
20
+ - python
21
+ - java
22
+ - php
23
+ - ruby
24
+ - rust
25
+ match:
26
+ fact:
27
+ kind: security.request-path-file-read
28
+ bind: fileRead
29
+ emit:
30
+ finding:
31
+ category: security.filesystem
32
+ severity: high
33
+ confidence: 0.85
34
+ tags:
35
+ - security
36
+ - filesystem
37
+ - path-traversal
38
+ message:
39
+ title: Avoid request-controlled file access in `${captures.fileRead.text}`
40
+ summary: "`${captures.fileRead.text}` reads from a path derived from request data without an allowlist or boundary check."
41
+ remediation:
42
+ summary: Resolve the path against a trusted base directory and reject values that escape it.
@@ -0,0 +1,44 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: security.no-sensitive-data-in-logs-and-telemetry
5
+ title: Avoid sensitive data in logs and telemetry
6
+ summary: Sensitive fields should not be sent to logging, tracing, or analytics sinks.
7
+ rationale: Observability payloads often leave the service boundary and can expose secrets, account identifiers, or personal data if they carry raw request or user fields.
8
+ tags:
9
+ - security
10
+ - privacy
11
+ - logging
12
+ - telemetry
13
+ - rules-catalog
14
+ stability: stable
15
+ appliesTo: function
16
+ scope:
17
+ languages:
18
+ - typescript
19
+ - javascript
20
+ - go
21
+ - python
22
+ - java
23
+ - php
24
+ - ruby
25
+ - rust
26
+ match:
27
+ fact:
28
+ kind: security.sensitive-data-in-logs-and-telemetry
29
+ bind: issue
30
+ emit:
31
+ finding:
32
+ category: security.privacy
33
+ severity: high
34
+ confidence: 0.85
35
+ tags:
36
+ - security
37
+ - privacy
38
+ - logging
39
+ - telemetry
40
+ message:
41
+ title: Remove sensitive data from logs and telemetry
42
+ summary: "`${captures.issue.text}` reaches a logging or telemetry sink with sensitive data."
43
+ remediation:
44
+ summary: Redact, hash, or drop the sensitive field before it reaches the sink.
@@ -0,0 +1,42 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: security.no-sql-interpolation
5
+ title: Avoid raw or interpolated SQL
6
+ summary: Database query sinks must not receive request-driven or dynamically interpolated SQL text.
7
+ rationale: Raw or interpolated SQL can let attackers control query structure when values are not passed separately.
8
+ tags:
9
+ - security
10
+ - sql
11
+ - injection
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ - go
20
+ - python
21
+ - java
22
+ - php
23
+ - ruby
24
+ - rust
25
+ match:
26
+ fact:
27
+ kind: security.sql-interpolation
28
+ bind: queryCall
29
+ emit:
30
+ finding:
31
+ category: security.injection
32
+ severity: high
33
+ confidence: 0.95
34
+ tags:
35
+ - security
36
+ - sql
37
+ - injection
38
+ message:
39
+ title: Avoid interpolated SQL in `${captures.queryCall.text}`
40
+ summary: "`${captures.queryCall.text}` builds or forwards SQL text directly into a raw query sink."
41
+ remediation:
42
+ summary: Use prepared statements, placeholder parameters, or a typed query builder instead of executing raw SQL text.
@@ -0,0 +1,42 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: security.tls-verification-disabled
5
+ title: TLS verification disabled
6
+ summary: Transport clients should not disable certificate verification.
7
+ rationale: Trust-all TLS settings accept any certificate and undermine transport security.
8
+ tags:
9
+ - security
10
+ - transport
11
+ - tls
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ - go
20
+ - python
21
+ - java
22
+ - php
23
+ - ruby
24
+ - rust
25
+ match:
26
+ fact:
27
+ kind: security.tls-verification-disabled
28
+ bind: issue
29
+ emit:
30
+ finding:
31
+ category: security.transport
32
+ severity: high
33
+ confidence: 0.9
34
+ tags:
35
+ - security
36
+ - transport
37
+ - tls
38
+ message:
39
+ title: TLS verification disabled in `${captures.issue.text}`
40
+ summary: "`${captures.issue.text}` disables certificate verification or trust validation."
41
+ remediation:
42
+ summary: Use trusted certificate validation and remove trust-all overrides outside local development.
@@ -0,0 +1,41 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: security.unsafe-deserialization
5
+ title: Protect deserialization trust boundaries
6
+ summary: Deserializers should not consume untrusted payloads directly across a trust boundary.
7
+ rationale: Deserializing untrusted payloads can let attacker-controlled data reshape parser state, object graphs, or downstream runtime behavior.
8
+ tags:
9
+ - security
10
+ - deserialization
11
+ - rules-catalog
12
+ - crq-sec-028
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ - go
20
+ - python
21
+ - java
22
+ - php
23
+ - ruby
24
+ - rust
25
+ match:
26
+ fact:
27
+ kind: security.unsafe-deserialization
28
+ bind: issue
29
+ emit:
30
+ finding:
31
+ category: security.deserialization
32
+ severity: high
33
+ confidence: 0.85
34
+ tags:
35
+ - security
36
+ - deserialization
37
+ message:
38
+ title: Constrain the trust boundary before `${captures.issue.text}`
39
+ summary: "`${captures.issue.text}` deserializes an untrusted payload across a trust boundary."
40
+ remediation:
41
+ summary: Deserialize only from trusted producers, or validate and constrain the payload shape before crossing the deserialization boundary.
@@ -0,0 +1,41 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: security.weak-hash-algorithm
5
+ title: Avoid weak hash algorithms
6
+ summary: Cryptographic hashing should use modern, collision-resistant algorithms.
7
+ rationale: Weak digests such as MD5 and SHA-1 are vulnerable to collisions and should not be used for security-sensitive hashing.
8
+ tags:
9
+ - security
10
+ - crypto
11
+ - rules-catalog
12
+ stability: stable
13
+ appliesTo: block
14
+ scope:
15
+ languages:
16
+ - typescript
17
+ - javascript
18
+ - go
19
+ - python
20
+ - java
21
+ - php
22
+ - ruby
23
+ - rust
24
+ match:
25
+ fact:
26
+ kind: security.weak-hash-algorithm
27
+ bind: issue
28
+ emit:
29
+ finding:
30
+ category: security.secrets
31
+ severity: high
32
+ confidence: 0.9
33
+ tags:
34
+ - security
35
+ - crypto
36
+ - hash
37
+ message:
38
+ title: Avoid weak hash algorithms
39
+ summary: "`${captures.issue.text}` uses a weak hash algorithm."
40
+ remediation:
41
+ summary: Use SHA-256, SHA-384, SHA-512, or a stronger approved hashing primitive instead.
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.config.no-process-env-outside-config
5
+ title: Avoid direct `process.env` access outside config
6
+ summary: Keep environment variable access inside config modules.
7
+ rationale: Centralized config makes environment handling predictable and testable.
8
+ tags:
9
+ - config
10
+ - rules-catalog
11
+ scope:
12
+ languages:
13
+ - typescript
14
+ paths:
15
+ exclude:
16
+ - "**/config/**"
17
+ match:
18
+ node:
19
+ kind: MemberExpression
20
+ bind: envAccess
21
+ where:
22
+ - path: object.object.text
23
+ equals: process
24
+ - path: object.property.text
25
+ equals: env
26
+ emit:
27
+ finding:
28
+ category: maintainability
29
+ severity: medium
30
+ confidence: high
31
+ tags:
32
+ - config
33
+ message:
34
+ title: Avoid `${captures.envAccess.text}`
35
+ summary: Keep `${captures.envAccess.text}` access inside config modules.
36
+ remediation:
37
+ summary: Read the environment value in a config module and inject it where needed.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.blocking-call-in-async-flow
5
+ title: Blocking call inside async flow
6
+ summary: Async functions should not call synchronous blocking APIs on the hot path.
7
+ rationale: Blocking sync APIs stall the event loop and erase the throughput benefits of async control flow.
8
+ tags:
9
+ - correctness
10
+ - async
11
+ - rules-catalog
12
+ - crq-cor-013
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: async.blocking-call-in-async-flow
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.async
26
+ severity: medium
27
+ confidence: 0.75
28
+ tags:
29
+ - correctness
30
+ - async
31
+ message:
32
+ title: Avoid blocking sync calls in async flows
33
+ summary: "`${captures.issue.text}` uses a blocking sync API inside an async function."
34
+ remediation:
35
+ summary: Replace the sync API with its asynchronous equivalent or move the blocking work out of the async request path.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.constant-condition
5
+ title: Always-true or always-false condition
6
+ summary: Flow-control conditions should not resolve to a constant boolean value.
7
+ rationale: Constant conditions hide dead branches and usually signal leftover debug code or a mistaken comparison.
8
+ tags:
9
+ - correctness
10
+ - logic
11
+ - rules-catalog
12
+ - crq-cor-006
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: control-flow.constant-condition
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.logic
26
+ severity: medium
27
+ confidence: 0.95
28
+ tags:
29
+ - correctness
30
+ - logic
31
+ message:
32
+ title: Review constant condition
33
+ summary: "`${captures.issue.text}` always resolves to the same boolean value."
34
+ remediation:
35
+ summary: Replace the constant predicate with a real runtime check or remove the dead branch.
@@ -0,0 +1,34 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.implicit-undefined-return
5
+ title: Implicit undefined return in function
6
+ summary: Functions that return a value on some paths must not fall through implicitly.
7
+ rationale: Mixed value-return and implicit-fallthrough paths are a common source of undefined behavior.
8
+ tags:
9
+ - correctness
10
+ - control-flow
11
+ - rules-catalog
12
+ - crq-cor-005
13
+ stability: stable
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: control-flow.implicit-undefined-return
22
+ emit:
23
+ finding:
24
+ category: correctness.control-flow
25
+ severity: medium
26
+ confidence: 0.9
27
+ tags:
28
+ - correctness
29
+ - control-flow
30
+ message:
31
+ title: Avoid implicit undefined return
32
+ summary: This function returns a value on some paths but falls through without returning on others.
33
+ remediation:
34
+ summary: Return a value on every reachable path or make the function consistently void.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.incorrect-boolean-logic
5
+ title: Incorrect boolean logic (AND/OR misuse)
6
+ summary: Comparison chains on the same value must use the boolean operator that matches the intended logic.
7
+ rationale: Using `&&` for mutually exclusive equality checks or `||` for inequality chains produces conditions that can never behave as intended.
8
+ tags:
9
+ - correctness
10
+ - logic
11
+ - rules-catalog
12
+ - crq-cor-008
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: control-flow.incorrect-boolean-logic
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.logic
26
+ severity: medium
27
+ confidence: 0.9
28
+ tags:
29
+ - correctness
30
+ - logic
31
+ message:
32
+ title: Review boolean comparison logic
33
+ summary: "`${captures.issue.text}` uses an AND/OR comparison chain that cannot behave as intended."
34
+ remediation:
35
+ summary: Use `||` for equality alternatives or `&&` for inequality exclusions, depending on the intended condition.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.missing-await-on-async-call
5
+ title: Missing await on async call
6
+ summary: Async functions should not drop direct async calls without awaiting them.
7
+ rationale: Unawaited async work in an async function often indicates a missed dependency or a promise that can reject outside the intended control flow.
8
+ tags:
9
+ - correctness
10
+ - async
11
+ - rules-catalog
12
+ - crq-cor-011
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: async.missing-await
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.async
26
+ severity: high
27
+ confidence: 0.9
28
+ tags:
29
+ - correctness
30
+ - async
31
+ message:
32
+ title: Await direct async work
33
+ summary: "`${captures.issue.text}` starts async work without `await`."
34
+ remediation:
35
+ summary: Await the call, return the promise explicitly, or document a deliberate fire-and-forget path outside the async flow.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.missing-default-dispatch
5
+ title: Missing default case in switch or conditional dispatch
6
+ summary: Dispatch constructs should include an explicit default or final else path.
7
+ rationale: Default handling makes control-flow intent explicit and avoids silent fallthrough for unhandled values.
8
+ tags:
9
+ - correctness
10
+ - control-flow
11
+ - rules-catalog
12
+ - crq-cor-007
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: control-flow.missing-default-dispatch
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.control-flow
26
+ severity: medium
27
+ confidence: 0.85
28
+ tags:
29
+ - correctness
30
+ - control-flow
31
+ message:
32
+ title: Add an explicit default dispatch path
33
+ summary: "Review `${captures.issue.text}` and add a `default` case or final `else`."
34
+ remediation:
35
+ summary: Handle the fallback branch explicitly so unexpected values do not rely on implicit behavior.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.missing-timeout-on-external-call
5
+ title: Missing timeout on external call
6
+ summary: External HTTP calls should declare timeout or cancellation behavior.
7
+ rationale: Network calls without explicit timeouts can hang indefinitely and make retry or fallback behavior unreliable.
8
+ tags:
9
+ - correctness
10
+ - resilience
11
+ - rules-catalog
12
+ - crq-cor-014
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: resilience.missing-timeout-on-external-call
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.resilience
26
+ severity: high
27
+ confidence: 0.9
28
+ tags:
29
+ - correctness
30
+ - resilience
31
+ message:
32
+ title: Configure timeouts on external calls
33
+ summary: "`${captures.issue.text}` performs an external call without explicit timeout or cancellation settings."
34
+ remediation:
35
+ summary: Add a timeout-bearing config object, such as `signal` for `fetch` or `timeout` for axios.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.nested-property-access-without-check
5
+ title: Nested property access without existence check
6
+ summary: Deep property chains derived from external input should verify intermediate values before access.
7
+ rationale: Multi-hop access into request or payload objects is brittle when any segment can be absent, renamed, or malformed.
8
+ tags:
9
+ - correctness
10
+ - "null"
11
+ - rules-catalog
12
+ - crq-cor-002
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: data-flow.nested-property-access-without-check
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.null
26
+ severity: medium
27
+ confidence: 0.8
28
+ tags:
29
+ - correctness
30
+ - "null"
31
+ message:
32
+ title: Check nested external-input paths before use
33
+ summary: "`${captures.issue.text}` walks a deep property chain without checking that each segment exists."
34
+ remediation:
35
+ summary: Add guards for the intermediate objects or switch the chain to explicit optional access with a fallback.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.correctness.off-by-one-loop-boundary
5
+ title: Off-by-one error in loop boundaries
6
+ summary: Index-based loops should not skip the first element or iterate one step past the collection boundary.
7
+ rationale: Off-by-one loop conditions frequently cause undefined reads, missed work, or stale guard logic around array bounds.
8
+ tags:
9
+ - correctness
10
+ - logic
11
+ - rules-catalog
12
+ - crq-cor-009
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: control-flow.off-by-one-loop-boundary
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: correctness.logic
26
+ severity: medium
27
+ confidence: 0.85
28
+ tags:
29
+ - correctness
30
+ - logic
31
+ message:
32
+ title: Review loop boundary condition
33
+ summary: "`${captures.issue.text}` likely skips or overruns one loop iteration."
34
+ remediation:
35
+ summary: Use `< collection.length` for ascending loops and `>= 0` for descending loops that start at `length - 1`.