@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,38 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.debug-mode-enabled
5
+ title: Do not expose debug routes or middleware in production
6
+ summary: Debug handlers, stack-showing middleware, and diagnostic endpoints should stay behind explicit development-only guards.
7
+ rationale: Debug endpoints and stack-showing middleware can disclose internal topology, environment details, and request data with very little attacker effort.
8
+ tags:
9
+ - security
10
+ - express
11
+ - diagnostics
12
+ - misconfiguration
13
+ - rules-catalog
14
+ stability: stable
15
+ appliesTo: block
16
+ scope:
17
+ languages:
18
+ - typescript
19
+ - javascript
20
+ match:
21
+ fact:
22
+ kind: security.debug-mode-enabled
23
+ bind: issue
24
+ emit:
25
+ finding:
26
+ category: security.misconfiguration
27
+ severity: medium
28
+ confidence: 0.92
29
+ tags:
30
+ - security
31
+ - express
32
+ - diagnostics
33
+ - misconfiguration
34
+ message:
35
+ title: Guard `${captures.issue.text}` behind an explicit development-only check
36
+ summary: "`${captures.issue.text}` enables debug or diagnostic exposure without a visible same-file development guard."
37
+ remediation:
38
+ summary: Wrap the registration in an explicit development-only guard or remove the endpoint or middleware from production builds.
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.dynamodb-query-injection
5
+ title: Avoid request-driven DynamoDB queries
6
+ summary: DynamoDB query and scan inputs should not be built directly from request input.
7
+ rationale: Raw request data in DynamoDB helpers can widen query scope or let attackers control expressions, filters, and key conditions.
8
+ tags:
9
+ - security
10
+ - injection
11
+ - dynamodb
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.dynamodb-query-injection
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.input-validation
26
+ severity: critical
27
+ confidence: 0.9
28
+ tags:
29
+ - security
30
+ - injection
31
+ - dynamodb
32
+ message:
33
+ title: Constrain `${captures.issue.text}` to a fixed DynamoDB query shape
34
+ summary: "`${captures.issue.text}` receives request-controlled DynamoDB input without narrowing it to trusted expressions or key maps."
35
+ remediation:
36
+ summary: Build DynamoDB requests from fixed expressions and allowlisted fields instead of forwarding request-shaped input.
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.exposed-directory-listing
5
+ title: Avoid exposed directory listings
6
+ summary: Directory listing middleware should not be enabled on public paths without a deliberate review.
7
+ rationale: Directory listings expose internal file names and make unintended resources easier to discover and fetch.
8
+ tags:
9
+ - security
10
+ - express
11
+ - filesystem
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.exposed-directory-listing
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.misconfiguration
26
+ severity: medium
27
+ confidence: 0.95
28
+ tags:
29
+ - security
30
+ - express
31
+ - filesystem
32
+ message:
33
+ title: Review `${captures.issue.text}` before exposing directory listings
34
+ summary: "`${captures.issue.text}` enables public directory listing behavior."
35
+ remediation:
36
+ summary: Remove directory listing middleware or protect it behind strict authorization and path scoping.
37
+
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.express-cookie-missing-http-only
5
+ title: Set `HttpOnly` on Express session cookies
6
+ summary: Express session and cookie-session configs should not disable the `HttpOnly` flag.
7
+ rationale: Script-readable session cookies are easier to steal after an XSS bug.
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: security.express-cookie-missing-http-only
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
+ - cookies
32
+ message:
33
+ title: Turn `HttpOnly` back on for `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` disables the `HttpOnly` cookie flag in Express session configuration."
35
+ remediation:
36
+ summary: "Set `httpOnly: true` so browser scripts cannot read the session cookie."
@@ -0,0 +1,39 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.express-default-cookie-config
5
+ title: Override Express cookie defaults
6
+ summary: Express session cookie settings should not omit explicit lifetime, scope, and transport attributes.
7
+ rationale: Implicit cookie defaults vary by middleware and make auth state harder to audit consistently.
8
+ tags:
9
+ - security
10
+ - authentication
11
+ - express
12
+ - cookies
13
+ - rules-catalog
14
+ stability: stable
15
+ appliesTo: block
16
+ scope:
17
+ languages:
18
+ - typescript
19
+ - javascript
20
+ match:
21
+ fact:
22
+ kind: security.express-default-cookie-config
23
+ bind: issue
24
+ emit:
25
+ finding:
26
+ category: security.authentication
27
+ severity: medium
28
+ confidence: 0.88
29
+ tags:
30
+ - security
31
+ - authentication
32
+ - express
33
+ - cookies
34
+ message:
35
+ title: Make the cookie policy explicit in `${captures.issue.text}`
36
+ summary: "`${captures.issue.text}` leaves key Express cookie settings at implicit defaults."
37
+ remediation:
38
+ summary: Set explicit cookie lifetime, scope, and transport attributes instead of relying on middleware defaults.
39
+
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.express-default-session-config
5
+ title: Override Express session defaults
6
+ summary: Express session middleware should not rely on default session naming and configuration.
7
+ rationale: Default session settings make applications easier to fingerprint and often skip explicit hardening choices.
8
+ tags:
9
+ - security
10
+ - authentication
11
+ - express
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.express-default-session-config
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.authentication
26
+ severity: medium
27
+ confidence: 0.88
28
+ tags:
29
+ - security
30
+ - authentication
31
+ - express
32
+ message:
33
+ title: Replace the defaults in `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` relies on default Express session configuration."
35
+ remediation:
36
+ summary: Set an explicit session name and hardening options instead of relying on middleware defaults.
37
+
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.express-insecure-cookie
5
+ title: Set `Secure` on Express session cookies
6
+ summary: Express session and cookie-session configs should not disable the `Secure` flag.
7
+ rationale: Cookies sent over non-HTTPS transport are easier to intercept or replay.
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: security.express-insecure-cookie
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
+ - cookies
32
+ message:
33
+ title: Turn `Secure` back on for `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` disables the `Secure` cookie flag in Express session configuration."
35
+ remediation:
36
+ summary: "Set `secure: true` and serve the cookie only over HTTPS."
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.express-missing-helmet
5
+ title: Apply Helmet to Express apps
6
+ summary: Express apps should use Helmet or equivalent header hardening middleware.
7
+ rationale: Helmet packages several response-header protections that are easy to miss or drift when managed ad hoc.
8
+ tags:
9
+ - security
10
+ - express
11
+ - headers
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: file
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.express-missing-helmet
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.misconfiguration
26
+ severity: medium
27
+ confidence: 0.82
28
+ tags:
29
+ - security
30
+ - express
31
+ - headers
32
+ message:
33
+ title: Add Helmet or equivalent header hardening to this Express app
34
+ summary: This Express app is initialized without visible Helmet-style header hardening.
35
+ remediation:
36
+ summary: Apply `helmet()` or an equivalent set of header protections near application startup.
37
+
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.express-nosql-injection
5
+ title: Avoid request-driven model queries
6
+ summary: Express handlers should not pass raw request objects into NoSQL filters, query helpers, or aggregation pipelines.
7
+ rationale: Request-shaped filters, operators, or pipelines can expand query scope and inject unintended behavior.
8
+ tags:
9
+ - security
10
+ - injection
11
+ - nosql
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.express-nosql-injection
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.input-validation
26
+ severity: critical
27
+ confidence: 0.92
28
+ tags:
29
+ - security
30
+ - injection
31
+ - nosql
32
+ message:
33
+ title: Narrow the query passed to `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` receives request-controlled query input without an allowlisted query or pipeline shape."
35
+ remediation:
36
+ summary: Build the NoSQL query or aggregation pipeline from fixed fields or validated filter builders instead of passing request data directly.
@@ -0,0 +1,38 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.express-permissive-cookie-config
5
+ title: Avoid permissive Express session cookie scope
6
+ summary: Express session cookies should not explicitly opt into cross-site or wildcard-style scope.
7
+ rationale: Broad cookie scope increases where session cookies are sent and makes cross-site misuse harder to contain.
8
+ tags:
9
+ - security
10
+ - authentication
11
+ - express
12
+ - cookies
13
+ - rules-catalog
14
+ stability: stable
15
+ appliesTo: block
16
+ scope:
17
+ languages:
18
+ - typescript
19
+ - javascript
20
+ match:
21
+ fact:
22
+ kind: security.express-permissive-cookie-config
23
+ bind: issue
24
+ emit:
25
+ finding:
26
+ category: security.authentication
27
+ severity: medium
28
+ confidence: 0.89
29
+ tags:
30
+ - security
31
+ - authentication
32
+ - express
33
+ - cookies
34
+ message:
35
+ title: Tighten cookie scope in `${captures.issue.text}`
36
+ summary: "`${captures.issue.text}` explicitly widens session cookie scope with cross-site or wildcard-style settings."
37
+ remediation:
38
+ summary: Prefer exact cookie domains and `SameSite=Lax` or `Strict` unless a reviewed cross-site requirement exists.
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.express-reduce-fingerprint
5
+ title: Reduce Express fingerprinting
6
+ summary: Express apps should disable `x-powered-by` or equivalent fingerprinting headers.
7
+ rationale: Framework fingerprinting gives attackers unnecessary detail about the stack they are targeting.
8
+ tags:
9
+ - security
10
+ - express
11
+ - headers
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: file
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.express-reduce-fingerprint
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.misconfiguration
26
+ severity: medium
27
+ confidence: 0.84
28
+ tags:
29
+ - security
30
+ - express
31
+ - headers
32
+ message:
33
+ title: Disable default Express fingerprinting headers
34
+ summary: This Express app does not visibly disable `x-powered-by` or equivalent fingerprinting behavior.
35
+ remediation:
36
+ summary: Disable `x-powered-by` or use equivalent middleware to reduce framework fingerprinting.
37
+
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.express-static-assets-after-session
5
+ title: Serve static assets before session middleware
6
+ summary: Static assets should be mounted before session middleware when they do not need session state.
7
+ rationale: Serving public assets after session middleware broadens the session surface and adds unnecessary auth-state handling to static traffic.
8
+ tags:
9
+ - security
10
+ - express
11
+ - middleware-order
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: file
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.express-static-assets-after-session
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.misconfiguration
26
+ severity: medium
27
+ confidence: 0.85
28
+ tags:
29
+ - security
30
+ - express
31
+ - middleware-order
32
+ message:
33
+ title: Move static asset middleware ahead of session handling
34
+ summary: Static asset middleware is mounted after session middleware in this file.
35
+ remediation:
36
+ summary: Mount `express.static()` before session middleware unless the static path genuinely requires session state.
37
+
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.external-file-upload
5
+ title: Do not persist upload filenames directly
6
+ summary: Upload handlers should not store attacker-controlled filenames without generating or validating a safe local name.
7
+ rationale: Upload filenames can carry traversal payloads, collisions, or misleading extensions that break local containment.
8
+ tags:
9
+ - security
10
+ - filesystem
11
+ - upload
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.external-file-upload
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.filesystem
26
+ severity: high
27
+ confidence: 0.93
28
+ tags:
29
+ - security
30
+ - filesystem
31
+ - upload
32
+ message:
33
+ title: Generate a trusted local filename for `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` persists an upload filename derived from attacker-controlled input."
35
+ remediation:
36
+ summary: Generate a server-side filename or apply a strict allowlist before storing uploaded content.
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.file-generation
5
+ title: Constrain local file generation paths
6
+ summary: Local file writes should not derive their destination path from request or upload input.
7
+ rationale: Attacker-controlled write paths can overwrite local state, escape intended directories, or create files in sensitive locations.
8
+ tags:
9
+ - security
10
+ - filesystem
11
+ - file-write
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.file-generation
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.filesystem
26
+ severity: high
27
+ confidence: 0.92
28
+ tags:
29
+ - security
30
+ - filesystem
31
+ - file-write
32
+ message:
33
+ title: Validate the local write path used by `${captures.issue.text}`
34
+ summary: "`${captures.issue.text}` writes to a path derived from external input without a trusted local filename."
35
+ remediation:
36
+ summary: Generate the destination name on the server or constrain writes to an allowlisted directory and filename set.
@@ -0,0 +1,36 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.format-string-using-user-input
5
+ title: Avoid request-controlled format strings
6
+ summary: Logging and formatting helpers should not take request input as the format string itself.
7
+ rationale: Request-controlled format strings can corrupt logs, leak structure, or produce unexpected formatting behavior.
8
+ tags:
9
+ - security
10
+ - logging
11
+ - input-validation
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.format-string-using-user-input
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.input-validation
26
+ severity: high
27
+ confidence: 0.88
28
+ tags:
29
+ - security
30
+ - logging
31
+ - input-validation
32
+ message:
33
+ title: Treat `${captures.issue.text}` as data, not a format string
34
+ summary: "`${captures.issue.text}` uses request-controlled input as the formatting template."
35
+ remediation:
36
+ summary: Keep the format string fixed and pass request data as ordinary arguments or structured fields.
@@ -0,0 +1,35 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.frontend-only-authorization
5
+ title: Authorization enforced only on frontend
6
+ summary: Backend routes should enforce authorization directly instead of relying on frontend gating alone.
7
+ rationale: Frontend checks are easy to bypass, so sensitive routes need server-side authorization on the backend path itself.
8
+ tags:
9
+ - security
10
+ - authorization
11
+ - rules-catalog
12
+ - crq-sec-024
13
+ stability: experimental
14
+ appliesTo: project
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.frontend-only-authorization
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.authorization
26
+ severity: high
27
+ confidence: 0.65
28
+ tags:
29
+ - security
30
+ - authorization
31
+ message:
32
+ title: Backend authorization must not live only in the frontend
33
+ summary: "Route `${captures.issue.text}` appears gated in frontend code but not on the backend handler."
34
+ remediation:
35
+ summary: Add a backend authorization or permission check on the matching route handler.
@@ -0,0 +1,38 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.handlebars-no-escape
5
+ title: Keep Handlebars escaping enabled at template trust boundaries
6
+ summary: "Server-side Handlebars compilation should not disable HTML escaping with `noEscape: true`."
7
+ rationale: Disabling Handlebars escaping weakens the template trust boundary and can turn server-rendered output into attacker-controlled HTML.
8
+ tags:
9
+ - security
10
+ - xss
11
+ - templating
12
+ - output-encoding
13
+ - rules-catalog
14
+ stability: stable
15
+ appliesTo: block
16
+ scope:
17
+ languages:
18
+ - typescript
19
+ - javascript
20
+ match:
21
+ fact:
22
+ kind: security.handlebars-no-escape
23
+ bind: issue
24
+ emit:
25
+ finding:
26
+ category: security.output-encoding
27
+ severity: high
28
+ confidence: 0.95
29
+ tags:
30
+ - security
31
+ - xss
32
+ - templating
33
+ - output-encoding
34
+ message:
35
+ title: Keep escaping enabled in `${captures.issue.text}`
36
+ summary: "`${captures.issue.text}` disables Handlebars escaping at a server-template trust boundary."
37
+ remediation:
38
+ summary: Leave Handlebars escaping enabled, or treat raw HTML rendering as an explicit, narrowly reviewed trust boundary.
@@ -0,0 +1,37 @@
1
+ apiVersion: critiq.dev/v1alpha1
2
+ kind: Rule
3
+ metadata:
4
+ id: ts.security.hardcoded-auth-secret
5
+ title: Avoid hardcoded auth secrets
6
+ summary: JWT, session, and strategy secrets should not be embedded directly in source code.
7
+ rationale: Hardcoded auth secrets are hard to rotate and are exposed whenever the codebase or build artifacts leak.
8
+ tags:
9
+ - security
10
+ - authentication
11
+ - secrets
12
+ - rules-catalog
13
+ stability: stable
14
+ appliesTo: block
15
+ scope:
16
+ languages:
17
+ - typescript
18
+ - javascript
19
+ match:
20
+ fact:
21
+ kind: security.hardcoded-auth-secret
22
+ bind: issue
23
+ emit:
24
+ finding:
25
+ category: security.authentication
26
+ severity: critical
27
+ confidence: 0.95
28
+ tags:
29
+ - security
30
+ - authentication
31
+ - secrets
32
+ message:
33
+ title: Move the secret used by `${captures.issue.text}` out of source
34
+ summary: "`${captures.issue.text}` uses an inline authentication secret instead of loading it from configuration or a secret manager."
35
+ remediation:
36
+ summary: Load the secret from environment-backed configuration or a secret manager and rotate the exposed value.
37
+