@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,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.import-using-user-input
5
+ title: Constrain module-loading trust boundaries
6
+ summary: "`require()` and dynamic `import()` should not resolve modules from untrusted input."
7
+ rationale: Untrusted module paths let attackers steer module-loading boundaries toward unintended files, packages, or plugins.
8
+ tags:
9
+ - security
10
+ - execution
11
+ - module-loading
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.import-using-user-input
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.execution
26
+ severity: high
27
+ confidence: 0.92
28
+ tags:
29
+ - security
30
+ - execution
31
+ - module-loading
32
+ message:
33
+ title: Resolve `${captures.issue.text}` from a trusted module map
34
+ summary: "`${captures.issue.text}` crosses a module-loading trust boundary with untrusted input."
35
+ remediation:
36
+ summary: Resolve modules from a fixed allowlist or explicit dispatcher instead of untrusted request or event data.
@@ -0,0 +1,38 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.information-leakage
5
+ title: Avoid leaking sensitive or diagnostic state
6
+ summary: Logs, stdout or stderr, and direct response sinks should not expose sensitive fields or internal diagnostic detail.
7
+ rationale: Stack traces, request metadata, auth or session objects, and environment state are often leaked through "temporary" debugging output that later reaches production paths.
8
+ tags:
9
+ - security
10
+ - privacy
11
+ - logging
12
+ - diagnostics
13
+ - rules-catalog
14
+ stability: stable
15
+ appliesTo: block
16
+ scope:
17
+ languages:
18
+ - typescript
19
+ - javascript
20
+ match:
21
+ fact:
22
+ kind: security.information-leakage
23
+ bind: issue
24
+ emit:
25
+ finding:
26
+ category: security.privacy
27
+ severity: high
28
+ confidence: 0.9
29
+ tags:
30
+ - security
31
+ - privacy
32
+ - logging
33
+ - diagnostics
34
+ message:
35
+ title: Remove sensitive or diagnostic data from `${captures.issue.text}`
36
+ summary: "`${captures.issue.text}` exposes sensitive fields or internal diagnostic detail through a direct sink."
37
+ remediation:
38
+ summary: Replace the payload with a fixed summary, redact sensitive fields, and strip stack, env, request, or cookie data from production output.
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.insecure-allow-origin
5
+ title: Do not reflect request origin into CORS policy
6
+ summary: "`Access-Control-Allow-Origin` should not be set from request-controlled input."
7
+ rationale: Reflecting the request origin into a CORS allowlist turns origin validation into a no-op.
8
+ tags:
9
+ - security
10
+ - cors
11
+ - misconfiguration
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.insecure-allow-origin
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.misconfiguration
26
+ severity: high
27
+ confidence: 0.92
28
+ tags:
29
+ - security
30
+ - cors
31
+ - misconfiguration
32
+ message:
33
+ title: Validate the origin before setting `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` reflects request input into `Access-Control-Allow-Origin`."
35
+ remediation:
36
+ summary: Set CORS origins from a fixed allowlist or explicit trusted origin check.
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.insecure-auth-cookie-flags
5
+ title: Harden auth-bearing cookies
6
+ summary: Auth and session cookies should set HttpOnly, Secure, and SameSite.
7
+ rationale: Cookie flags prevent browser scripts, mixed transport, and cross-site requests from exposing session-bearing values.
8
+ tags:
9
+ - security
10
+ - authentication
11
+ - cookies
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: ts.security.insecure-auth-cookie-flags
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.authentication
26
+ severity: high
27
+ confidence: 0.9
28
+ tags:
29
+ - security
30
+ - authentication
31
+ - cookies
32
+ message:
33
+ title: Harden `${captures.issue.text}` for auth cookies
34
+ summary: "`${captures.issue.text}` sets an auth-bearing cookie without the expected protections."
35
+ remediation:
36
+ summary: Add `HttpOnly`, `Secure`, and an explicit `SameSite` policy before the cookie is used for session or auth state.
37
+
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.insecure-password-hash-configuration
5
+ title: Avoid legacy Argon2 password hash modes
6
+ summary: Password hashing should not use `argon2i` or `argon2d` when safer modern modes are available.
7
+ rationale: Older Argon2 modes are weaker choices for password storage than the modern hybrid mode.
8
+ tags:
9
+ - security
10
+ - cryptography
11
+ - password-storage
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.insecure-password-hash-configuration
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.cryptography
26
+ severity: high
27
+ confidence: 0.9
28
+ tags:
29
+ - security
30
+ - cryptography
31
+ - password-storage
32
+ message:
33
+ title: Upgrade the hash mode used by `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` uses an older Argon2 mode for password hashing."
35
+ remediation:
36
+ summary: Prefer `argon2id` and keep the password hash configuration aligned with current password-storage guidance.
37
+
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.insecure-websocket-transport
5
+ title: Use secure WebSocket transport
6
+ summary: WebSocket clients should not connect over cleartext `ws://` when sensitive application data is involved.
7
+ rationale: Cleartext WebSocket transport exposes application traffic to interception and manipulation.
8
+ tags:
9
+ - security
10
+ - transport
11
+ - websocket
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.insecure-websocket-transport
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.transport
26
+ severity: high
27
+ confidence: 0.95
28
+ tags:
29
+ - security
30
+ - transport
31
+ - websocket
32
+ message:
33
+ title: Replace `${captures.issue.text}` with a secure WebSocket URL
34
+ summary: "`${captures.issue.text}` uses cleartext WebSocket transport."
35
+ remediation:
36
+ summary: Switch the endpoint to `wss://` and keep certificate validation enabled.
37
+
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.insufficiently-random-values
5
+ title: Use enough entropy for secrets and tokens
6
+ summary: Secret-bearing tokens and secrets should use at least 16 bytes of cryptographic entropy.
7
+ rationale: Short random values are harder to brute-force than predictable values, but they can still be guessed faster than modern secret-bearing flows should allow.
8
+ tags:
9
+ - security
10
+ - cryptography
11
+ - randomness
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.insufficiently-random-values
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.cryptography
26
+ severity: high
27
+ confidence: 0.9
28
+ tags:
29
+ - security
30
+ - cryptography
31
+ - randomness
32
+ message:
33
+ title: Increase the entropy used by `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` uses a cryptographically random source, but not enough entropy for a secret-bearing value."
35
+ remediation:
36
+ summary: Generate at least 16 bytes of entropy for reset tokens, invitation codes, session secrets, and similar secret-bearing values.
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.jwt-not-revoked
5
+ title: Add a JWT revocation hook
6
+ summary: Express JWT middleware should check revocation state when bearer tokens can be invalidated early.
7
+ rationale: Signature validation alone does not handle logout, compromise, or forced token invalidation.
8
+ tags:
9
+ - security
10
+ - authentication
11
+ - jwt
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.jwt-not-revoked
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.authentication
26
+ severity: medium
27
+ confidence: 0.9
28
+ tags:
29
+ - security
30
+ - authentication
31
+ - jwt
32
+ message:
33
+ title: Add revocation handling to `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` configures Express JWT validation without an `isRevoked` check."
35
+ remediation:
36
+ summary: Add an `isRevoked` callback or equivalent revocation check for tokens that can be invalidated before expiry.
37
+
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.jwt-sensitive-claims
5
+ title: Remove sensitive claims from JWT payloads
6
+ summary: JWT payloads should avoid embedding PII or secrets unless absolutely required.
7
+ rationale: Client-visible tokens often outlive a single request and can leak more data than intended.
8
+ tags:
9
+ - security
10
+ - privacy
11
+ - jwt
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: ts.security.jwt-sensitive-claims
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.privacy
26
+ severity: high
27
+ confidence: 0.9
28
+ tags:
29
+ - security
30
+ - privacy
31
+ - jwt
32
+ message:
33
+ title: Remove sensitive claims from `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` includes claims that expose personal or secret data in a token payload."
35
+ remediation:
36
+ summary: Keep JWT claims minimal. Prefer stable identifiers, not direct PII or secret-bearing fields.
37
+
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.manual-html-sanitization
5
+ title: Avoid ad hoc HTML sanitization
6
+ summary: Hand-rolled HTML escaping and sanitization should be replaced with vetted sanitizers or safe rendering paths.
7
+ rationale: String replacement chains miss edge cases and are easy to bypass as rendering behavior evolves.
8
+ tags:
9
+ - security
10
+ - xss
11
+ - sanitization
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.manual-html-sanitization
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.output-encoding
26
+ severity: medium
27
+ confidence: 0.88
28
+ tags:
29
+ - security
30
+ - xss
31
+ - sanitization
32
+ message:
33
+ title: Replace `${captures.issue.text}` with a vetted sanitizer
34
+ summary: "`${captures.issue.text}` performs manual HTML escaping instead of using a trusted sanitization or safe rendering path."
35
+ remediation:
36
+ summary: Use a vetted sanitizer or framework-native escaping model instead of string replacement chains.
37
+
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.missing-authorization-before-sensitive-action
5
+ title: Missing authorization before sensitive action
6
+ summary: Sensitive backend actions should be guarded by an authorization or permission check.
7
+ rationale: Calling destructive or privileged actions without an authorization guard increases the risk of broken access control.
8
+ tags:
9
+ - security
10
+ - authorization
11
+ - rules-catalog
12
+ - crq-sec-021
13
+ stability: stable
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.missing-authorization-before-sensitive-action
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.authorization
26
+ severity: high
27
+ confidence: 0.75
28
+ tags:
29
+ - security
30
+ - authorization
31
+ message:
32
+ title: Add authorization before sensitive backend actions
33
+ summary: "`${captures.issue.text}` performs a sensitive action without a matching authorization guard."
34
+ remediation:
35
+ summary: Add an explicit authorization or permission check before the sensitive action executes.
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.missing-integrity-check
5
+ title: Use authenticated encryption for secrets and tokens
6
+ summary: Session, cookie, and token encryption should provide integrity protection in the same helper.
7
+ rationale: Confidentiality-only encryption leaves secret-bearing values vulnerable to tampering unless the code also applies an integrity check or uses an authenticated mode.
8
+ tags:
9
+ - security
10
+ - cryptography
11
+ - integrity
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.missing-integrity-check
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.cryptography
26
+ severity: high
27
+ confidence: 0.9
28
+ tags:
29
+ - security
30
+ - cryptography
31
+ - integrity
32
+ message:
33
+ title: Add integrity protection to `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` encrypts a secret-bearing value without authenticated encryption or a same-helper integrity check."
35
+ remediation:
36
+ summary: Prefer authenticated encryption such as AES-GCM, or pair non-AEAD encryption with an explicit integrity check in the same helper.
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.missing-message-origin-check
5
+ title: Verify `message` event origins
6
+ summary: "`message` handlers should validate `event.origin` before trusting cross-window data."
7
+ rationale: Without an origin check, hostile pages can post crafted messages into the handler.
8
+ tags:
9
+ - security
10
+ - browser
11
+ - messaging
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.missing-message-origin-check
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.browser
26
+ severity: high
27
+ confidence: 0.92
28
+ tags:
29
+ - security
30
+ - browser
31
+ - messaging
32
+ message:
33
+ title: Check `event.origin` before processing `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` handles cross-window messages without validating the sender origin."
35
+ remediation:
36
+ summary: Gate the handler on a strict allowlist of expected origins before reading `event.data`.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.missing-ownership-validation
5
+ title: Missing ownership validation
6
+ summary: Resource identifiers from request input should be checked against the caller before sensitive actions run.
7
+ rationale: Authorization alone is not enough when handlers act on caller-provided resource ids that may belong to someone else.
8
+ tags:
9
+ - security
10
+ - authorization
11
+ - rules-catalog
12
+ - crq-sec-022
13
+ stability: stable
14
+ appliesTo: function
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.missing-ownership-validation
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.authorization
26
+ severity: high
27
+ confidence: 0.75
28
+ tags:
29
+ - security
30
+ - authorization
31
+ message:
32
+ title: Validate ownership before acting on caller-supplied resource ids
33
+ summary: "`${captures.issue.text}` is used in a sensitive path without a matching ownership check."
34
+ remediation:
35
+ summary: Compare the request-derived resource id to the authenticated caller or load the resource through an ownership-enforcing query.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.missing-request-timeout-or-retry
5
+ title: Missing request timeout or retry protection
6
+ summary: External calls should define timeout, cancellation, or retry behavior before they enter security-sensitive flows.
7
+ rationale: Authentication and dependency calls that have neither timeout nor retry protection fail unpredictably under network stress.
8
+ tags:
9
+ - security
10
+ - resilience
11
+ - rules-catalog
12
+ - crq-sec-030
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.missing-request-timeout-or-retry
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.resilience
26
+ severity: medium
27
+ confidence: 0.8
28
+ tags:
29
+ - security
30
+ - resilience
31
+ message:
32
+ title: Add timeout or retry protection to external calls
33
+ summary: "`${captures.issue.text}` performs an external call without timeout, cancellation, or retry handling."
34
+ remediation:
35
+ summary: Add explicit timeout or cancellation support, wrap the call in retry handling, or do both when the dependency is critical.
@@ -0,0 +1,34 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.no-dynamic-execution
5
+ title: Eval or dynamic code execution
6
+ summary: Eval-like helpers, `vm` execution APIs, and string-evaluated timers should not execute dynamic code.
7
+ rationale: Dynamic execution turns data into code, widens the attack surface, and bypasses normal control flow.
8
+ tags:
9
+ - security
10
+ - execution
11
+ - rules-catalog
12
+ stability: stable
13
+ appliesTo: block
14
+ scope:
15
+ languages:
16
+ - typescript
17
+ - javascript
18
+ match:
19
+ fact:
20
+ kind: security.dynamic-execution
21
+ bind: issue
22
+ emit:
23
+ finding:
24
+ category: security.execution
25
+ severity: high
26
+ confidence: 0.95
27
+ tags:
28
+ - security
29
+ - execution
30
+ message:
31
+ title: Avoid `${captures.issue.text}`
32
+ summary: "`${captures.issue.text}` executes dynamic code and should be replaced with a safer alternative."
33
+ remediation:
34
+ summary: Replace dynamic execution with explicit parsing, fixed dispatch tables, or normal function callbacks.
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.no-innerhtml-assignment
5
+ title: Avoid unsafe `innerHTML` assignment
6
+ summary: "`innerHTML` assignments should only use fixed or explicitly sanitized HTML."
7
+ rationale: Direct HTML injection can allow untrusted or weakly reviewed content to execute in the browser.
8
+ tags:
9
+ - security
10
+ - output-encoding
11
+ - xss
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.no-innerhtml-assignment
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.output-encoding
26
+ severity: high
27
+ confidence: 0.92
28
+ tags:
29
+ - security
30
+ - xss
31
+ - output-encoding
32
+ message:
33
+ title: Avoid unsafe `innerHTML` assignment in `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` inserts non-literal, non-sanitized HTML into `innerHTML`."
35
+ remediation:
36
+ summary: Prefer text-only rendering APIs or assign only fixed or explicitly sanitized HTML.
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.non-literal-fs-filename
5
+ title: Avoid attacker-controlled filesystem read paths
6
+ summary: Direct filesystem read APIs should not consume request- or upload-controlled filenames.
7
+ rationale: Dynamic read paths can expose unintended local files or bypass expected file-selection constraints.
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
+ match:
20
+ fact:
21
+ kind: security.non-literal-fs-filename
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.filesystem
26
+ severity: high
27
+ confidence: 0.9
28
+ tags:
29
+ - security
30
+ - filesystem
31
+ - path-traversal
32
+ message:
33
+ title: Constrain the filename used by `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` reads from a filename derived from external input."
35
+ remediation:
36
+ summary: Resolve reads from a trusted allowlist or a validated server-controlled mapping instead of external filenames.