@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.
- package/README.md +169 -0
- package/catalog.yaml +599 -0
- package/package.json +21 -0
- package/rules/shared/security.insecure-http-transport.rule.yaml +42 -0
- package/rules/shared/security.no-command-execution-with-request-input.rule.yaml +42 -0
- package/rules/shared/security.no-hardcoded-credentials.rule.yaml +42 -0
- package/rules/shared/security.no-request-path-file-read.rule.yaml +42 -0
- package/rules/shared/security.no-sensitive-data-in-logs-and-telemetry.rule.yaml +44 -0
- package/rules/shared/security.no-sql-interpolation.rule.yaml +42 -0
- package/rules/shared/security.tls-verification-disabled.rule.yaml +42 -0
- package/rules/shared/security.unsafe-deserialization.rule.yaml +41 -0
- package/rules/shared/security.weak-hash-algorithm.rule.yaml +41 -0
- package/rules/typescript/ts.config.no-process-env-outside-config.rule.yaml +37 -0
- package/rules/typescript/ts.correctness.blocking-call-in-async-flow.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.constant-condition.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.implicit-undefined-return.rule.yaml +34 -0
- package/rules/typescript/ts.correctness.incorrect-boolean-logic.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.missing-await-on-async-call.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.missing-default-dispatch.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.missing-timeout-on-external-call.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.nested-property-access-without-check.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.off-by-one-loop-boundary.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.optional-value-without-fallback.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.possible-null-dereference.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.shared-state-race.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.unchecked-map-key-access.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.unhandled-async-error.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.unreachable-statement.rule.yaml +40 -0
- package/rules/typescript/ts.logging.no-console-error.rule.yaml +34 -0
- package/rules/typescript/ts.logging.no-console-log.rule.yaml +34 -0
- package/rules/typescript/ts.next.no-server-client-boundary-leaks.rule.yaml +36 -0
- package/rules/typescript/ts.performance.inefficient-data-structure-usage.rule.yaml +35 -0
- package/rules/typescript/ts.performance.large-payload-without-streaming.rule.yaml +35 -0
- package/rules/typescript/ts.performance.missing-batch-operations.rule.yaml +35 -0
- package/rules/typescript/ts.performance.nested-loops-hot-path.rule.yaml +35 -0
- package/rules/typescript/ts.performance.repeated-expensive-computation.rule.yaml +35 -0
- package/rules/typescript/ts.performance.repeated-io-in-loop.rule.yaml +35 -0
- package/rules/typescript/ts.performance.retained-large-object.rule.yaml +35 -0
- package/rules/typescript/ts.performance.sequential-async-calls.rule.yaml +35 -0
- package/rules/typescript/ts.performance.unbounded-growth-memory-leak.rule.yaml +35 -0
- package/rules/typescript/ts.performance.unnecessary-rerenders-from-state-misuse.rule.yaml +35 -0
- package/rules/typescript/ts.quality.deep-nesting.rule.yaml +35 -0
- package/rules/typescript/ts.quality.duplicate-code-block.rule.yaml +35 -0
- package/rules/typescript/ts.quality.function-too-large-or-complex.rule.yaml +35 -0
- package/rules/typescript/ts.quality.hardcoded-configuration-values.rule.yaml +35 -0
- package/rules/typescript/ts.quality.logic-change-without-test-updates.rule.yaml +36 -0
- package/rules/typescript/ts.quality.magic-numbers-or-strings.rule.yaml +35 -0
- package/rules/typescript/ts.quality.missing-error-context.rule.yaml +35 -0
- package/rules/typescript/ts.quality.missing-tests-for-critical-logic.rule.yaml +35 -0
- package/rules/typescript/ts.quality.swallowed-error.rule.yaml +35 -0
- package/rules/typescript/ts.quality.tight-module-coupling.rule.yaml +35 -0
- package/rules/typescript/ts.random.no-math-random-in-core.rule.yaml +37 -0
- package/rules/typescript/ts.react.no-cascaded-effect-fetches.rule.yaml +37 -0
- package/rules/typescript/ts.runtime.no-debugger-statement.rule.yaml +29 -0
- package/rules/typescript/ts.security.bind-to-all-interfaces.rule.yaml +36 -0
- package/rules/typescript/ts.security.browser-token-storage.rule.yaml +37 -0
- package/rules/typescript/ts.security.dangerous-insert-html.rule.yaml +36 -0
- package/rules/typescript/ts.security.dangerously-set-inner-html.rule.yaml +38 -0
- package/rules/typescript/ts.security.datadog-browser-track-user-interactions.rule.yaml +37 -0
- package/rules/typescript/ts.security.debug-mode-enabled.rule.yaml +38 -0
- package/rules/typescript/ts.security.dynamodb-query-injection.rule.yaml +36 -0
- package/rules/typescript/ts.security.exposed-directory-listing.rule.yaml +37 -0
- package/rules/typescript/ts.security.express-cookie-missing-http-only.rule.yaml +36 -0
- package/rules/typescript/ts.security.express-default-cookie-config.rule.yaml +39 -0
- package/rules/typescript/ts.security.express-default-session-config.rule.yaml +37 -0
- package/rules/typescript/ts.security.express-insecure-cookie.rule.yaml +36 -0
- package/rules/typescript/ts.security.express-missing-helmet.rule.yaml +37 -0
- package/rules/typescript/ts.security.express-nosql-injection.rule.yaml +36 -0
- package/rules/typescript/ts.security.express-permissive-cookie-config.rule.yaml +38 -0
- package/rules/typescript/ts.security.express-reduce-fingerprint.rule.yaml +37 -0
- package/rules/typescript/ts.security.express-static-assets-after-session.rule.yaml +37 -0
- package/rules/typescript/ts.security.external-file-upload.rule.yaml +36 -0
- package/rules/typescript/ts.security.file-generation.rule.yaml +36 -0
- package/rules/typescript/ts.security.format-string-using-user-input.rule.yaml +36 -0
- package/rules/typescript/ts.security.frontend-only-authorization.rule.yaml +35 -0
- package/rules/typescript/ts.security.handlebars-no-escape.rule.yaml +38 -0
- package/rules/typescript/ts.security.hardcoded-auth-secret.rule.yaml +37 -0
- package/rules/typescript/ts.security.import-using-user-input.rule.yaml +36 -0
- package/rules/typescript/ts.security.information-leakage.rule.yaml +38 -0
- package/rules/typescript/ts.security.insecure-allow-origin.rule.yaml +36 -0
- package/rules/typescript/ts.security.insecure-auth-cookie-flags.rule.yaml +37 -0
- package/rules/typescript/ts.security.insecure-password-hash-configuration.rule.yaml +37 -0
- package/rules/typescript/ts.security.insecure-websocket-transport.rule.yaml +37 -0
- package/rules/typescript/ts.security.insufficiently-random-values.rule.yaml +36 -0
- package/rules/typescript/ts.security.jwt-not-revoked.rule.yaml +37 -0
- package/rules/typescript/ts.security.jwt-sensitive-claims.rule.yaml +37 -0
- package/rules/typescript/ts.security.manual-html-sanitization.rule.yaml +37 -0
- package/rules/typescript/ts.security.missing-authorization-before-sensitive-action.rule.yaml +35 -0
- package/rules/typescript/ts.security.missing-integrity-check.rule.yaml +36 -0
- package/rules/typescript/ts.security.missing-message-origin-check.rule.yaml +36 -0
- package/rules/typescript/ts.security.missing-ownership-validation.rule.yaml +35 -0
- package/rules/typescript/ts.security.missing-request-timeout-or-retry.rule.yaml +35 -0
- package/rules/typescript/ts.security.no-dynamic-execution.rule.yaml +34 -0
- package/rules/typescript/ts.security.no-innerhtml-assignment.rule.yaml +36 -0
- package/rules/typescript/ts.security.non-literal-fs-filename.rule.yaml +36 -0
- package/rules/typescript/ts.security.observable-timing-discrepancy.rule.yaml +37 -0
- package/rules/typescript/ts.security.open-redirect.rule.yaml +37 -0
- package/rules/typescript/ts.security.permissive-allow-origin.rule.yaml +36 -0
- package/rules/typescript/ts.security.permissive-file-permissions.rule.yaml +37 -0
- package/rules/typescript/ts.security.postmessage-wildcard-origin.rule.yaml +36 -0
- package/rules/typescript/ts.security.predictable-token-generation.rule.yaml +36 -0
- package/rules/typescript/ts.security.raw-html-using-user-input.rule.yaml +37 -0
- package/rules/typescript/ts.security.sensitive-data-egress.rule.yaml +36 -0
- package/rules/typescript/ts.security.sensitive-data-in-exception.rule.yaml +37 -0
- package/rules/typescript/ts.security.sensitive-data-written-to-file.rule.yaml +37 -0
- package/rules/typescript/ts.security.ssrf.rule.yaml +34 -0
- package/rules/typescript/ts.security.token-or-session-not-validated.rule.yaml +35 -0
- package/rules/typescript/ts.security.ui-redress.rule.yaml +37 -0
- package/rules/typescript/ts.security.unsanitized-http-response.rule.yaml +36 -0
- package/rules/typescript/ts.security.unvalidated-external-input.rule.yaml +35 -0
- package/rules/typescript/ts.security.user-controlled-sendfile.rule.yaml +36 -0
- package/rules/typescript/ts.security.user-controlled-view-render.rule.yaml +36 -0
- package/rules/typescript/ts.security.weak-cipher-or-mode.rule.yaml +35 -0
- package/rules/typescript/ts.security.weak-key-strength.rule.yaml +36 -0
- package/rules/typescript/ts.security.weak-tls-version.rule.yaml +36 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +5 -0
- package/src/index.js.map +1 -0
- package/src/lib/rules-package.d.ts +3 -0
- package/src/lib/rules-package.js +16 -0
- 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
|
+
|