@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,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.observable-timing-discrepancy
|
|
5
|
+
title: Use constant-time secret comparison
|
|
6
|
+
summary: Secrets and tokens should not be compared with ordinary equality operators.
|
|
7
|
+
rationale: Ordinary string comparison can leak timing differences that help attackers guess secret material.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- cryptography
|
|
11
|
+
- timing
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.observable-timing-discrepancy
|
|
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
|
+
- timing
|
|
32
|
+
message:
|
|
33
|
+
title: Replace `${captures.issue.text}` with a constant-time comparison
|
|
34
|
+
summary: "`${captures.issue.text}` compares a likely secret value with ordinary equality."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Use a constant-time comparison helper such as `crypto.timingSafeEqual` for secrets, tokens, and password hashes.
|
|
37
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.open-redirect
|
|
5
|
+
title: Open redirect via request-controlled target
|
|
6
|
+
summary: Redirect and navigation sinks should not use request-controlled destinations without validation.
|
|
7
|
+
rationale: Redirect targets that are derived from user input can send authenticated users to attacker-controlled destinations.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- input-validation
|
|
11
|
+
- redirect
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.open-redirect
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.input-validation
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.85
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- redirect
|
|
31
|
+
- input-validation
|
|
32
|
+
message:
|
|
33
|
+
title: Validate redirect target before using `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` redirects to a request-controlled destination without a strict allowlist or internal-path check."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Normalize the target to an internal path or validate it against a trusted origin allowlist before redirecting.
|
|
37
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.permissive-allow-origin
|
|
5
|
+
title: Do not allow every origin in CORS policy
|
|
6
|
+
summary: CORS should not fall back to wildcard or implicit allow-all origin settings.
|
|
7
|
+
rationale: Wildcard or implicit allow-all CORS policies expose authenticated browser responses across origins.
|
|
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.permissive-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: Restrict `${captures.issue.text}` to trusted origins
|
|
34
|
+
summary: "`${captures.issue.text}` allows any origin through wildcard or implicit CORS policy."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Configure an explicit allowlist or validated origin callback instead of allowing all origins.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.permissive-file-permissions
|
|
5
|
+
title: Avoid permissive file modes
|
|
6
|
+
summary: Files that can carry user or security data should not be created with world-accessible modes.
|
|
7
|
+
rationale: Broad file permissions expose application data to local users or processes that should not read or modify it.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- filesystem
|
|
11
|
+
- permissions
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.permissive-file-permissions
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.filesystem
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.95
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- filesystem
|
|
31
|
+
- permissions
|
|
32
|
+
message:
|
|
33
|
+
title: Tighten the mode used by `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` sets a file mode that grants world access."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Use the minimum required file mode and remove world-readable or world-writable bits.
|
|
37
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.postmessage-wildcard-origin
|
|
5
|
+
title: Avoid wildcard `postMessage` targets
|
|
6
|
+
summary: "`postMessage` calls should not use `*` as the target origin when they carry application data."
|
|
7
|
+
rationale: Wildcard targets allow the browser to deliver the message to any origin that receives the window reference.
|
|
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.postmessage-wildcard-origin
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.browser
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.95
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- browser
|
|
31
|
+
- messaging
|
|
32
|
+
message:
|
|
33
|
+
title: Replace the wildcard target in `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` uses `*` as the `postMessage` target origin."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Set the target origin to a strict expected origin instead of `*`.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.predictable-token-generation
|
|
5
|
+
title: Avoid predictable token generation
|
|
6
|
+
summary: Tokens, reset links, and session secrets should be generated from cryptographically strong randomness.
|
|
7
|
+
rationale: Predictable token material makes it easier to guess reset links, invite codes, and session secrets.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- authentication
|
|
11
|
+
- crypto
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.predictable-token-generation
|
|
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
|
+
- crypto
|
|
32
|
+
message:
|
|
33
|
+
title: Avoid predictable token generation
|
|
34
|
+
summary: "`${captures.issue.text}` builds a token-like value from predictable inputs."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Generate the value with `crypto.randomBytes`, `crypto.randomUUID`, or an approved secure token source.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.raw-html-using-user-input
|
|
5
|
+
title: Avoid raw HTML with request input
|
|
6
|
+
summary: Request-derived values should not be interpolated into raw HTML strings.
|
|
7
|
+
rationale: Raw HTML construction with request data is a common path to reflected and stored XSS.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- xss
|
|
11
|
+
- output-encoding
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.raw-html-using-user-input
|
|
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: Remove request input from `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` interpolates request-derived content into raw HTML."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Use framework escaping, a trusted sanitizer, or safe DOM APIs instead of raw HTML interpolation.
|
|
37
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.sensitive-data-egress
|
|
5
|
+
title: Sensitive data egress to third-party processors
|
|
6
|
+
summary: Sensitive values should not be sent to external processors or outbound SDKs without minimization or redaction.
|
|
7
|
+
rationale: Sending regulated or secret data to third-party services increases privacy exposure and creates downstream processor risk.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- privacy
|
|
11
|
+
- data-exposure
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: experimental
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.sensitive-data-egress
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.privacy
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.82
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- privacy
|
|
31
|
+
- data-exposure
|
|
32
|
+
message:
|
|
33
|
+
title: Avoid sending sensitive data through `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` sends normalized sensitive datatypes to an outbound processor or external service."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Minimize the payload, redact the sensitive fields, or route the data only to approved processors.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.sensitive-data-in-exception
|
|
5
|
+
title: Avoid sensitive data in thrown errors
|
|
6
|
+
summary: Exceptions and rejection payloads should not include raw secrets or personal data.
|
|
7
|
+
rationale: Exception payloads often reach logs, APM tools, and client responses with less review than normal business data.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- privacy
|
|
11
|
+
- errors
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.sensitive-data-in-exception
|
|
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
|
+
- errors
|
|
32
|
+
message:
|
|
33
|
+
title: Remove sensitive data from `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` includes sensitive values in an exception or rejection payload."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Replace raw secrets and personal data with opaque identifiers or redacted summaries before throwing or rejecting.
|
|
37
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.sensitive-data-written-to-file
|
|
5
|
+
title: Avoid writing sensitive data to files
|
|
6
|
+
summary: Data exports and local file writes should not persist raw secrets or personal fields.
|
|
7
|
+
rationale: Static files, exports, and backups are easy to copy or retain beyond their intended lifetime.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- privacy
|
|
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.sensitive-data-written-to-file
|
|
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
|
+
- filesystem
|
|
32
|
+
message:
|
|
33
|
+
title: Remove sensitive fields before `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` writes sensitive data into a local file sink."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Redact, hash, or exclude the sensitive fields before writing the file.
|
|
37
|
+
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.ssrf
|
|
5
|
+
title: Server-side request forgery
|
|
6
|
+
summary: Outbound requests should not use attacker-controlled targets or private hosts.
|
|
7
|
+
rationale: Request-controlled targets can force the server to call internal services, metadata endpoints, or attacker-controlled infrastructure.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- network
|
|
11
|
+
- ssrf
|
|
12
|
+
- rules-catalog
|
|
13
|
+
scope:
|
|
14
|
+
languages:
|
|
15
|
+
- typescript
|
|
16
|
+
- javascript
|
|
17
|
+
match:
|
|
18
|
+
fact:
|
|
19
|
+
kind: security.ssrf
|
|
20
|
+
bind: ssrfCall
|
|
21
|
+
emit:
|
|
22
|
+
finding:
|
|
23
|
+
category: security.transport
|
|
24
|
+
severity: high
|
|
25
|
+
confidence: 0.85
|
|
26
|
+
tags:
|
|
27
|
+
- security
|
|
28
|
+
- network
|
|
29
|
+
- ssrf
|
|
30
|
+
message:
|
|
31
|
+
title: Avoid SSRF in `${captures.ssrfCall.text}`
|
|
32
|
+
summary: "`${captures.ssrfCall.text}` sends an outbound request to a request-controlled or private target."
|
|
33
|
+
remediation:
|
|
34
|
+
summary: Resolve URLs against a trusted allowlist, reject private hosts, and proxy outbound requests through a vetted server-side helper.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.token-or-session-not-validated
|
|
5
|
+
title: Token or session not validated
|
|
6
|
+
summary: Session and token values from external input should be verified before authentication or identity use.
|
|
7
|
+
rationale: Parsing or loading session state without verification allows forged or stale credentials to influence authorization paths.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- authentication
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-sec-023
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: function
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.token-or-session-not-validated
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.authentication
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.85
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- authentication
|
|
31
|
+
message:
|
|
32
|
+
title: Validate tokens and sessions before use
|
|
33
|
+
summary: "`${captures.issue.text}` uses token or session input without any preceding validation step."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Verify or authenticate the token or session value before decoding, loading, or deriving identity from it.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.ui-redress
|
|
5
|
+
title: Do not derive anti-framing headers from request input
|
|
6
|
+
summary: Framing and CSP headers should not be set from request-controlled values.
|
|
7
|
+
rationale: Request-controlled anti-framing headers weaken protections against clickjacking and UI redress attacks.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- clickjacking
|
|
11
|
+
- headers
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.ui-redress
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.misconfiguration
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.88
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- clickjacking
|
|
31
|
+
- headers
|
|
32
|
+
message:
|
|
33
|
+
title: Set `${captures.issue.text}` from trusted policy only
|
|
34
|
+
summary: "`${captures.issue.text}` derives anti-framing or CSP header values from request input."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Set framing and CSP headers from fixed server policy instead of request data.
|
|
37
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.unsanitized-http-response
|
|
5
|
+
title: Avoid unsafe raw HTTP response output
|
|
6
|
+
summary: Raw response writers should not echo request data into HTML-capable responses without trusted escaping or sanitization.
|
|
7
|
+
rationale: Directly reflecting request data into HTML-capable response sinks creates reflected XSS and content injection risk.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- xss
|
|
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.unsanitized-http-response
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.output-encoding
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.88
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- xss
|
|
31
|
+
- express
|
|
32
|
+
message:
|
|
33
|
+
title: Remove request data from `${captures.issue.text}` or escape it first
|
|
34
|
+
summary: "`${captures.issue.text}` writes request-controlled data into a raw HTTP response sink without a trusted HTML escaping model."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Escape or sanitize the data with a trusted helper, or switch to a response format that does not treat it as executable markup.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.unvalidated-external-input
|
|
5
|
+
title: Validate untrusted input before parser construction
|
|
6
|
+
summary: Untrusted input should be validated before it is used to construct sensitive parsers or runtime objects.
|
|
7
|
+
rationale: Passing untrusted text across regex or URL construction boundaries increases the risk of parser abuse, denial of service, and downstream policy bypass.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- input-validation
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-sec-027
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.unvalidated-external-input
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.input-validation
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.8
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- input-validation
|
|
31
|
+
message:
|
|
32
|
+
title: Validate the trust boundary before `${captures.issue.text}`
|
|
33
|
+
summary: "`${captures.issue.text}` constructs a sensitive parser or runtime object from untrusted input without a trust-boundary check."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Validate, sanitize, or normalize the untrusted value before passing it into URL, RegExp, or similarly sensitive constructors.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.user-controlled-sendfile
|
|
5
|
+
title: Constrain `res.sendFile` to a trusted root
|
|
6
|
+
summary: "`res.sendFile()` should not resolve filenames or options from request input without a trusted root."
|
|
7
|
+
rationale: Request-controlled file responses are a common path to path traversal and unintended local file disclosure.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- filesystem
|
|
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.user-controlled-sendfile
|
|
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
|
+
- express
|
|
32
|
+
message:
|
|
33
|
+
title: Validate the file path used by `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` serves a request-controlled file path or options object without a trusted root."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Resolve files from an allowlisted directory and validate request input before it reaches `res.sendFile()`.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.user-controlled-view-render
|
|
5
|
+
title: Constrain `res.render()` trust boundaries
|
|
6
|
+
summary: Express view names should not cross into server-side rendering from untrusted input.
|
|
7
|
+
rationale: Untrusted template names can expose internal views, bypass intended route behavior, or widen a server-side template boundary.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- express
|
|
11
|
+
- rendering
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.user-controlled-view-render
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.output-encoding
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.9
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- express
|
|
31
|
+
- rendering
|
|
32
|
+
message:
|
|
33
|
+
title: Resolve the view for `${captures.issue.text}` from a trusted route map
|
|
34
|
+
summary: "`${captures.issue.text}` selects a server-side template across a trust boundary using untrusted input."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Resolve the template from an allowlist or fixed route mapping before calling `res.render()`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.weak-cipher-or-mode
|
|
5
|
+
title: Avoid weak cipher algorithms and modes
|
|
6
|
+
summary: Cryptographic ciphers should use modern authenticated modes and approved algorithms.
|
|
7
|
+
rationale: Weak modes such as ECB and legacy ciphers such as DES or RC4 do not provide adequate confidentiality.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- crypto
|
|
11
|
+
- rules-catalog
|
|
12
|
+
stability: stable
|
|
13
|
+
appliesTo: block
|
|
14
|
+
scope:
|
|
15
|
+
languages:
|
|
16
|
+
- typescript
|
|
17
|
+
- javascript
|
|
18
|
+
match:
|
|
19
|
+
fact:
|
|
20
|
+
kind: security.weak-cipher-or-mode
|
|
21
|
+
bind: issue
|
|
22
|
+
emit:
|
|
23
|
+
finding:
|
|
24
|
+
category: security.secrets
|
|
25
|
+
severity: high
|
|
26
|
+
confidence: 0.9
|
|
27
|
+
tags:
|
|
28
|
+
- security
|
|
29
|
+
- crypto
|
|
30
|
+
- cipher
|
|
31
|
+
message:
|
|
32
|
+
title: Avoid weak cipher algorithms and modes
|
|
33
|
+
summary: "`${captures.issue.text}` uses a weak cipher algorithm or mode."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Use modern authenticated encryption such as AES-GCM with approved key sizes and IV handling.
|