@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,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.quality.deep-nesting
|
|
5
|
+
title: Deep nesting reducing readability
|
|
6
|
+
summary: Deeply nested control flow should be flattened where practical.
|
|
7
|
+
rationale: Deep nesting increases cognitive load and makes edge cases harder to reason about during review.
|
|
8
|
+
tags:
|
|
9
|
+
- quality
|
|
10
|
+
- structure
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-qua-042
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: function
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: quality.deep-nesting
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: quality.structure
|
|
26
|
+
severity: low
|
|
27
|
+
confidence: 0.9
|
|
28
|
+
tags:
|
|
29
|
+
- quality
|
|
30
|
+
- structure
|
|
31
|
+
message:
|
|
32
|
+
title: Flatten deeply nested control flow
|
|
33
|
+
summary: Review `${captures.issue.text}` and reduce indentation depth.
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Use guard clauses, helper functions, or early returns to keep the main path shallow.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.quality.duplicate-code-block
|
|
5
|
+
title: Duplicate code block
|
|
6
|
+
summary: Large duplicated function bodies across files make behavior harder to maintain safely.
|
|
7
|
+
rationale: Duplicated logic often diverges over time and increases the cost of fixes, testing, and future changes.
|
|
8
|
+
tags:
|
|
9
|
+
- quality
|
|
10
|
+
- duplication
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-qua-043
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: file
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: quality.duplicate-code-block
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: quality.duplication
|
|
26
|
+
severity: low
|
|
27
|
+
confidence: 0.75
|
|
28
|
+
tags:
|
|
29
|
+
- quality
|
|
30
|
+
- duplication
|
|
31
|
+
message:
|
|
32
|
+
title: Extract duplicated logic into a shared unit
|
|
33
|
+
summary: "`${captures.issue.text}` duplicates a substantial code block already present elsewhere in the project."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Extract the shared logic into a common helper or module and keep one maintained implementation.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.quality.function-too-large-or-complex
|
|
5
|
+
title: Function too large or too complex
|
|
6
|
+
summary: Oversized or overly complex functions should be split into smaller units.
|
|
7
|
+
rationale: Large functions are harder to test, review, and change safely because behavior and branching accumulate in one place.
|
|
8
|
+
tags:
|
|
9
|
+
- quality
|
|
10
|
+
- structure
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-qua-041
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: function
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: quality.function-too-large-or-complex
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: quality.structure
|
|
26
|
+
severity: low
|
|
27
|
+
confidence: 0.95
|
|
28
|
+
tags:
|
|
29
|
+
- quality
|
|
30
|
+
- structure
|
|
31
|
+
message:
|
|
32
|
+
title: Split large or complex functions
|
|
33
|
+
summary: Review `${captures.issue.text}` and extract smaller units of behavior.
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Break the function into helpers, reduce branching, and isolate independent responsibilities.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.quality.hardcoded-configuration-values
|
|
5
|
+
title: Hardcoded configuration values
|
|
6
|
+
summary: Config-like values should usually come from configuration sources rather than source literals.
|
|
7
|
+
rationale: Hardcoded service URLs, timeouts, and regions make deployments harder to vary and review safely.
|
|
8
|
+
tags:
|
|
9
|
+
- quality
|
|
10
|
+
- configuration
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-qua-044
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: file
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: quality.hardcoded-configuration-values
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: quality.configuration
|
|
26
|
+
severity: low
|
|
27
|
+
confidence: 0.8
|
|
28
|
+
tags:
|
|
29
|
+
- quality
|
|
30
|
+
- configuration
|
|
31
|
+
message:
|
|
32
|
+
title: Externalize config-like literals
|
|
33
|
+
summary: Review `${captures.issue.text}` and move config-like literals behind a configuration source.
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Load the value from env, params, or a dedicated config module instead of hardcoding it in source.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.quality.logic-change-without-test-updates
|
|
5
|
+
title: Logic change without corresponding test updates
|
|
6
|
+
summary: Diffs that change critical logic should usually update the matching tests in the same change.
|
|
7
|
+
rationale: Critical logic changes without test updates are easy to miss in review and increase regression risk.
|
|
8
|
+
tags:
|
|
9
|
+
- quality
|
|
10
|
+
- testing
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-qua-050
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: project
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
changedLinesOnly: true
|
|
20
|
+
match:
|
|
21
|
+
fact:
|
|
22
|
+
kind: quality.logic-change-without-test-updates
|
|
23
|
+
bind: issue
|
|
24
|
+
emit:
|
|
25
|
+
finding:
|
|
26
|
+
category: quality.testing
|
|
27
|
+
severity: medium
|
|
28
|
+
confidence: 0.7
|
|
29
|
+
tags:
|
|
30
|
+
- quality
|
|
31
|
+
- testing
|
|
32
|
+
message:
|
|
33
|
+
title: Update tests alongside critical logic changes
|
|
34
|
+
summary: "`${captures.issue.text}` changed without a corresponding test file change in the same diff."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Update or add the matching tests in the same change so the new behavior is exercised by the diff.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.quality.magic-numbers-or-strings
|
|
5
|
+
title: Magic numbers or magic strings
|
|
6
|
+
summary: Non-trivial literals in logic should be named to explain their meaning.
|
|
7
|
+
rationale: Bare literals hide domain meaning and make future changes riskier because intent is not captured in code.
|
|
8
|
+
tags:
|
|
9
|
+
- quality
|
|
10
|
+
- readability
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-qua-045
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: quality.magic-numbers-or-strings
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: quality.readability
|
|
26
|
+
severity: low
|
|
27
|
+
confidence: 0.65
|
|
28
|
+
tags:
|
|
29
|
+
- quality
|
|
30
|
+
- readability
|
|
31
|
+
message:
|
|
32
|
+
title: Name magic literals
|
|
33
|
+
summary: Review `${captures.issue.text}` and replace unexplained literals with named constants.
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Extract the literal into a descriptive constant or enum so the intent is explicit.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.quality.missing-error-context
|
|
5
|
+
title: Missing error context or logging
|
|
6
|
+
summary: Catch blocks should include the caught error when they log or rethrow.
|
|
7
|
+
rationale: Logging or rethrowing without the original error strips the context needed to diagnose the failure.
|
|
8
|
+
tags:
|
|
9
|
+
- quality
|
|
10
|
+
- error-handling
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-qua-048
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: error-handling.missing-error-context
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: quality.error-handling
|
|
26
|
+
severity: low
|
|
27
|
+
confidence: 0.8
|
|
28
|
+
tags:
|
|
29
|
+
- quality
|
|
30
|
+
- error-handling
|
|
31
|
+
message:
|
|
32
|
+
title: Preserve the original error context
|
|
33
|
+
summary: "Review `${captures.issue.text}` and include the caught error in the log or rethrow."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Pass the caught error to the logger or preserve it when constructing the replacement error.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.quality.missing-tests-for-critical-logic
|
|
5
|
+
title: Missing tests for critical logic
|
|
6
|
+
summary: Critical auth, payment, or similar business logic should have a matching test file.
|
|
7
|
+
rationale: Important business and security logic needs direct regression coverage to keep changes safe and reviewable.
|
|
8
|
+
tags:
|
|
9
|
+
- quality
|
|
10
|
+
- testing
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-qua-049
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: project
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: quality.missing-tests-for-critical-logic
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: quality.testing
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.8
|
|
28
|
+
tags:
|
|
29
|
+
- quality
|
|
30
|
+
- testing
|
|
31
|
+
message:
|
|
32
|
+
title: Add tests for critical logic paths
|
|
33
|
+
summary: "`${captures.issue.text}` looks like critical logic but no matching test file was found."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Add a focused unit or integration test that covers the critical behavior before future changes land.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.quality.swallowed-error
|
|
5
|
+
title: Errors swallowed silently
|
|
6
|
+
summary: Catch blocks must log, reject, or rethrow failures instead of dropping them silently.
|
|
7
|
+
rationale: Silent catch blocks hide failures and make production diagnosis unnecessarily difficult.
|
|
8
|
+
tags:
|
|
9
|
+
- quality
|
|
10
|
+
- error-handling
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-qua-047
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: error-handling.swallowed-error
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: quality.error-handling
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.95
|
|
28
|
+
tags:
|
|
29
|
+
- quality
|
|
30
|
+
- error-handling
|
|
31
|
+
message:
|
|
32
|
+
title: Do not swallow caught errors
|
|
33
|
+
summary: "Review `${captures.issue.text}` and propagate or record the failure."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Rethrow the error, reject the async flow, or log the failure through a recognized error sink.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.quality.tight-module-coupling
|
|
5
|
+
title: Tight coupling between modules
|
|
6
|
+
summary: Direct import cycles between modules increase coupling and make change boundaries harder to maintain.
|
|
7
|
+
rationale: Cyclic dependencies complicate initialization order, testing, and architecture boundaries.
|
|
8
|
+
tags:
|
|
9
|
+
- quality
|
|
10
|
+
- architecture
|
|
11
|
+
- rules-catalog
|
|
12
|
+
- crq-qua-046
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: project
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: quality.tight-module-coupling
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: quality.architecture
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.9
|
|
28
|
+
tags:
|
|
29
|
+
- quality
|
|
30
|
+
- architecture
|
|
31
|
+
message:
|
|
32
|
+
title: Break direct cyclic imports between modules
|
|
33
|
+
summary: "`${captures.issue.text}` participates in a direct module import cycle."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Extract shared types or helpers into a third module, or invert the dependency so the cycle disappears.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.random.no-math-random-in-core
|
|
5
|
+
title: Avoid `Math.random()` in core code
|
|
6
|
+
summary: Core code should not depend on nondeterministic random generation.
|
|
7
|
+
rationale: Randomness in core logic makes behavior hard to test and reason about.
|
|
8
|
+
tags:
|
|
9
|
+
- determinism
|
|
10
|
+
- rules-catalog
|
|
11
|
+
scope:
|
|
12
|
+
languages:
|
|
13
|
+
- typescript
|
|
14
|
+
paths:
|
|
15
|
+
include:
|
|
16
|
+
- "**/core/**"
|
|
17
|
+
match:
|
|
18
|
+
node:
|
|
19
|
+
kind: CallExpression
|
|
20
|
+
bind: randomCall
|
|
21
|
+
where:
|
|
22
|
+
- path: callee.object.text
|
|
23
|
+
equals: Math
|
|
24
|
+
- path: callee.property.text
|
|
25
|
+
equals: random
|
|
26
|
+
emit:
|
|
27
|
+
finding:
|
|
28
|
+
category: maintainability
|
|
29
|
+
severity: medium
|
|
30
|
+
confidence: high
|
|
31
|
+
tags:
|
|
32
|
+
- determinism
|
|
33
|
+
message:
|
|
34
|
+
title: Avoid `${captures.randomCall.text}`
|
|
35
|
+
summary: Replace `${captures.randomCall.text}` with an injected randomness source.
|
|
36
|
+
remediation:
|
|
37
|
+
summary: Pass a random source into core logic instead of calling `Math.random()` directly.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.react.no-cascaded-effect-fetches
|
|
5
|
+
title: Avoid cascaded fetches inside React effects
|
|
6
|
+
summary: React effects should not serialize independent fetches that can run in parallel or move server-side.
|
|
7
|
+
rationale: Waterfall-style fetches delay rendering and hide data-loading cost inside client effects.
|
|
8
|
+
tags:
|
|
9
|
+
- performance
|
|
10
|
+
- react
|
|
11
|
+
- next
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: experimental
|
|
14
|
+
appliesTo: function
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: performance.react-effect-fetch-waterfall
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: performance.ui
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.82
|
|
28
|
+
tags:
|
|
29
|
+
- performance
|
|
30
|
+
- react
|
|
31
|
+
- next
|
|
32
|
+
message:
|
|
33
|
+
title: Avoid cascaded fetches inside React effects
|
|
34
|
+
summary: "`${captures.issue.text}` serializes fetches inside a React effect."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Parallelize the requests, move data loading server-side, or cache the first response before issuing the next request.
|
|
37
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.runtime.no-debugger-statement
|
|
5
|
+
title: Remove `debugger;`
|
|
6
|
+
summary: Remove debugger statements before committing source files.
|
|
7
|
+
rationale: Debugger statements interrupt runtime execution and should not ship.
|
|
8
|
+
tags:
|
|
9
|
+
- runtime
|
|
10
|
+
- rules-catalog
|
|
11
|
+
scope:
|
|
12
|
+
languages:
|
|
13
|
+
- typescript
|
|
14
|
+
match:
|
|
15
|
+
node:
|
|
16
|
+
kind: DebuggerStatement
|
|
17
|
+
bind: statement
|
|
18
|
+
emit:
|
|
19
|
+
finding:
|
|
20
|
+
category: maintainability
|
|
21
|
+
severity: medium
|
|
22
|
+
confidence: high
|
|
23
|
+
tags:
|
|
24
|
+
- runtime
|
|
25
|
+
message:
|
|
26
|
+
title: Remove `debugger;`
|
|
27
|
+
summary: Remove the debugger statement before committing the file.
|
|
28
|
+
remediation:
|
|
29
|
+
summary: Delete the debugger statement.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.bind-to-all-interfaces
|
|
5
|
+
title: Avoid binding to all interfaces
|
|
6
|
+
summary: Network-facing services should not explicitly bind to every interface unless public exposure is intentional and protected.
|
|
7
|
+
rationale: Binding to `0.0.0.0` or `::` can expose a service beyond the expected trust boundary and widen the reachable attack surface.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- network
|
|
11
|
+
- exposure
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.bind-to-all-interfaces
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.network
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.9
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- network
|
|
31
|
+
- exposure
|
|
32
|
+
message:
|
|
33
|
+
title: Restrict interface binding in `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` explicitly binds a network-facing service to every interface."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Bind to loopback or a specific interface unless public exposure is an intentional deployment requirement with compensating controls.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.browser-token-storage
|
|
5
|
+
title: Avoid browser token storage
|
|
6
|
+
summary: Access and session tokens should not be stored in long-lived browser storage.
|
|
7
|
+
rationale: Long-lived browser storage exposes tokens to script access and increases the impact of XSS or device compromise.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- authentication
|
|
11
|
+
- storage
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: ts.security.browser-token-storage
|
|
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
|
+
- storage
|
|
32
|
+
message:
|
|
33
|
+
title: Avoid storing tokens in `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` stores an access or session token in browser storage."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Keep tokens in HttpOnly cookies or in memory, and avoid long-lived cleartext browser storage.
|
|
37
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.dangerous-insert-html
|
|
5
|
+
title: Avoid unsafe DOM HTML insertion sinks
|
|
6
|
+
summary: "`outerHTML`, `document.write*`, and `insertAdjacentHTML` should only receive fixed or explicitly sanitized HTML."
|
|
7
|
+
rationale: HTML-capable DOM insertion sinks can execute attacker-controlled markup unless the HTML is fixed or strongly sanitized first.
|
|
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.dangerous-insert-html
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.output-encoding
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.92
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- xss
|
|
31
|
+
- output-encoding
|
|
32
|
+
message:
|
|
33
|
+
title: Avoid unsafe HTML insertion in `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` uses an HTML-capable DOM sink with non-literal, non-sanitized content."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Insert text with safe DOM APIs, or pass only fixed or explicitly sanitized HTML to the sink.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.dangerously-set-inner-html
|
|
5
|
+
title: Avoid unsafe `dangerouslySetInnerHTML`
|
|
6
|
+
summary: React `dangerouslySetInnerHTML` should only render fixed or explicitly sanitized HTML.
|
|
7
|
+
rationale: React bypasses its normal escaping model when `dangerouslySetInnerHTML` is used, which makes unsanitized HTML a direct XSS sink.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- xss
|
|
11
|
+
- react
|
|
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.dangerously-set-inner-html
|
|
23
|
+
bind: issue
|
|
24
|
+
emit:
|
|
25
|
+
finding:
|
|
26
|
+
category: security.output-encoding
|
|
27
|
+
severity: high
|
|
28
|
+
confidence: 0.93
|
|
29
|
+
tags:
|
|
30
|
+
- security
|
|
31
|
+
- xss
|
|
32
|
+
- react
|
|
33
|
+
- output-encoding
|
|
34
|
+
message:
|
|
35
|
+
title: Avoid unsafe `dangerouslySetInnerHTML` in `${captures.issue.text}`
|
|
36
|
+
summary: "`${captures.issue.text}` bypasses React escaping with non-literal, non-sanitized HTML."
|
|
37
|
+
remediation:
|
|
38
|
+
summary: Prefer normal React rendering, or pass only fixed or explicitly sanitized HTML to `dangerouslySetInnerHTML`.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.datadog-browser-track-user-interactions
|
|
5
|
+
title: Review Datadog RUM user interaction capture
|
|
6
|
+
summary: Datadog Browser RUM should not enable broad user interaction capture without a privacy review.
|
|
7
|
+
rationale: Automatic interaction capture can leak sensitive page content or element labels to third-party telemetry.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- privacy
|
|
11
|
+
- telemetry
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.datadog-browser-track-user-interactions
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.privacy
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.9
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- privacy
|
|
31
|
+
- telemetry
|
|
32
|
+
message:
|
|
33
|
+
title: Review `${captures.issue.text}` before enabling interaction capture
|
|
34
|
+
summary: "`${captures.issue.text}` turns on Datadog RUM user interaction tracking, which can capture sensitive UI context."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Disable broad interaction capture or add explicit scrubbing and allowlisted action naming before enabling it.
|
|
37
|
+
|