@critiq/rules 0.0.2 → 0.1.0
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 +52 -4
- package/catalog.yaml +985 -19
- package/package.json +6 -1
- package/rules/go/go.performance.no-regex-construction-in-loop.rule.yaml +33 -0
- package/rules/go/go.performance.no-sync-fs-in-request-path.rule.yaml +33 -0
- package/rules/go/go.performance.no-unbounded-concurrency.rule.yaml +33 -0
- package/rules/go/go.security.echo-sensitive-binding-without-validation.rule.yaml +46 -0
- package/rules/go/go.security.echo-unsafe-multipart-upload.rule.yaml +45 -0
- package/rules/go/go.security.fiber-sensitive-binding-without-validation.rule.yaml +45 -0
- package/rules/go/go.security.fiber-unsafe-multipart-upload.rule.yaml +45 -0
- package/rules/go/go.security.gin-sensitive-binding-without-validation.rule.yaml +45 -0
- package/rules/go/go.security.gin-trust-all-proxies.rule.yaml +45 -0
- package/rules/go/go.security.gin-wildcard-cors-with-credentials.rule.yaml +47 -0
- package/rules/go/go.security.net-http-missing-timeouts.rule.yaml +45 -0
- package/rules/go/go.security.sensitive-data-egress.rule.yaml +46 -0
- package/rules/go/go.security.tar-path-traversal.rule.yaml +45 -0
- package/rules/go/go.security.template-unescaped-request-value.rule.yaml +45 -0
- package/rules/go/go.testing.real-network-in-unit-test.rule.yaml +33 -0
- package/rules/go/go.testing.t-skip-without-ticket-reference.rule.yaml +33 -0
- package/rules/go/go.testing.time-sleep-in-unit-test.rule.yaml +33 -0
- package/rules/java/java.performance.no-regex-construction-in-loop.rule.yaml +33 -0
- package/rules/java/java.performance.no-sync-fs-in-request-path.rule.yaml +33 -0
- package/rules/java/java.performance.no-unbounded-concurrency.rule.yaml +33 -0
- package/rules/java/java.security.android-screenshot-exposure.rule.yaml +35 -0
- package/rules/java/java.security.android-world-readable-mode.rule.yaml +35 -0
- package/rules/java/java.security.jpa-concatenated-query.rule.yaml +47 -0
- package/rules/java/java.security.reflected-output-from-request.rule.yaml +35 -0
- package/rules/java/java.security.servlet-insecure-cookie.rule.yaml +35 -0
- package/rules/java/java.security.spring-actuator-health-details-always.rule.yaml +40 -0
- package/rules/java/java.security.spring-actuator-sensitive-exposure.rule.yaml +40 -0
- package/rules/java/java.security.spring-csrf-globally-disabled.rule.yaml +49 -0
- package/rules/java/java.security.spring-debug-exposure.rule.yaml +35 -0
- package/rules/java/java.security.spring-permit-all-default.rule.yaml +47 -0
- package/rules/java/java.security.spring-webmvc-unrestricted-data-binding.rule.yaml +47 -0
- package/rules/java/java.security.template-unescaped-user-output.rule.yaml +49 -0
- package/rules/java/java.testing.disabled-without-ticket-reference.rule.yaml +33 -0
- package/rules/java/java.testing.http-client-in-unit-test.rule.yaml +33 -0
- package/rules/java/java.testing.thread-sleep-in-unit-test.rule.yaml +33 -0
- package/rules/php/php.performance.no-regex-construction-in-loop.rule.yaml +33 -0
- package/rules/php/php.performance.no-sync-fs-in-request-path.rule.yaml +33 -0
- package/rules/php/php.performance.no-unbounded-concurrency.rule.yaml +33 -0
- package/rules/php/php.security.insecure-cors-wildcard-with-credentials.rule.yaml +41 -0
- package/rules/php/php.security.insecure-mail-or-file-transport.rule.yaml +41 -0
- package/rules/php/php.security.insecure-session-or-cookie-config.rule.yaml +42 -0
- package/rules/php/php.security.laravel-sensitive-csrf-exclusion.rule.yaml +42 -0
- package/rules/php/php.security.laravel-unsafe-blade-output.rule.yaml +42 -0
- package/rules/php/php.security.laravel-unsafe-mass-assignment.rule.yaml +45 -0
- package/rules/php/php.security.sensitive-data-egress.rule.yaml +42 -0
- package/rules/php/php.security.symfony-csrf-disabled.rule.yaml +42 -0
- package/rules/php/php.security.symfony-debug-exposure.rule.yaml +44 -0
- package/rules/php/php.security.unsafe-file-upload-handling.rule.yaml +41 -0
- package/rules/php/php.security.wordpress-missing-nonce-or-capability.rule.yaml +42 -0
- package/rules/php/php.security.wordpress-unprepared-sql.rule.yaml +42 -0
- package/rules/php/php.testing.curl-in-unit-test.rule.yaml +33 -0
- package/rules/php/php.testing.mark-test-skipped-without-ticket-reference.rule.yaml +33 -0
- package/rules/php/php.testing.sleep-in-unit-test.rule.yaml +33 -0
- package/rules/python/py.performance.no-regex-construction-in-loop.rule.yaml +33 -0
- package/rules/python/py.performance.no-sync-fs-in-request-path.rule.yaml +33 -0
- package/rules/python/py.performance.no-unbounded-concurrency.rule.yaml +33 -0
- package/rules/python/py.security.django-csrf-exempt-state-changing.rule.yaml +46 -0
- package/rules/python/py.security.django-missing-csrf-middleware.rule.yaml +47 -0
- package/rules/python/py.security.django-unsafe-production-settings.rule.yaml +47 -0
- package/rules/python/py.security.drf-allow-any-default.rule.yaml +46 -0
- package/rules/python/py.security.drf-allow-any-unsafe-method.rule.yaml +46 -0
- package/rules/python/py.security.fastapi-insecure-cors.rule.yaml +43 -0
- package/rules/python/py.security.flask-missing-upload-body-limit.rule.yaml +44 -0
- package/rules/python/py.security.flask-unsafe-html-output.rule.yaml +44 -0
- package/rules/python/py.security.flask-unsafe-upload-filename.rule.yaml +44 -0
- package/rules/python/py.testing.pytest-skip-without-ticket-reference.rule.yaml +33 -0
- package/rules/python/py.testing.real-network-in-unit-test.rule.yaml +33 -0
- package/rules/python/py.testing.time-sleep-in-unit-test.rule.yaml +33 -0
- package/rules/ruby/ruby.performance.no-regex-construction-in-loop.rule.yaml +33 -0
- package/rules/ruby/ruby.performance.no-sync-fs-in-request-path.rule.yaml +33 -0
- package/rules/ruby/ruby.performance.no-unbounded-concurrency.rule.yaml +33 -0
- package/rules/ruby/ruby.security.rails-csrf-disabled.rule.yaml +45 -0
- package/rules/ruby/ruby.security.rails-detailed-exceptions-enabled.rule.yaml +44 -0
- package/rules/ruby/ruby.security.rails-open-redirect.rule.yaml +45 -0
- package/rules/ruby/ruby.security.rails-unsafe-html-output.rule.yaml +46 -0
- package/rules/ruby/ruby.security.rails-unsafe-render.rule.yaml +45 -0
- package/rules/ruby/ruby.security.rails-unsafe-session-or-cookie-store.rule.yaml +45 -0
- package/rules/ruby/ruby.security.rails-unsafe-strong-parameters.rule.yaml +46 -0
- package/rules/ruby/ruby.security.sensitive-data-egress.rule.yaml +45 -0
- package/rules/ruby/ruby.security.sidekiq-web-unauthenticated-mount.rule.yaml +45 -0
- package/rules/ruby/ruby.testing.focused-example.rule.yaml +33 -0
- package/rules/ruby/ruby.testing.pending-without-ticket-reference.rule.yaml +33 -0
- package/rules/ruby/ruby.testing.real-network-in-unit-test.rule.yaml +33 -0
- package/rules/ruby/ruby.testing.skip-without-ticket-reference.rule.yaml +33 -0
- package/rules/ruby/ruby.testing.sleep-in-unit-test.rule.yaml +33 -0
- package/rules/rust/rust.performance.no-regex-construction-in-loop.rule.yaml +33 -0
- package/rules/rust/rust.performance.no-sync-fs-in-request-path.rule.yaml +33 -0
- package/rules/rust/rust.performance.no-unbounded-concurrency.rule.yaml +33 -0
- package/rules/rust/rust.security.actix-wildcard-cors-with-credentials.rule.yaml +47 -0
- package/rules/rust/rust.security.axum-body-limit-disabled.rule.yaml +45 -0
- package/rules/rust/rust.security.axum-insecure-cors-with-credentials.rule.yaml +47 -0
- package/rules/rust/rust.security.rocket-panic-prone-request-handler.rule.yaml +45 -0
- package/rules/rust/rust.security.rocket-unsafe-template-output.rule.yaml +47 -0
- package/rules/rust/rust.security.sqlx-diesel-raw-interpolated-query.rule.yaml +47 -0
- package/rules/rust/rust.security.template-unescaped-request-value.rule.yaml +47 -0
- package/rules/rust/rust.security.warp-blocking-or-panic-in-async-handler.rule.yaml +45 -0
- package/rules/rust/rust.testing.ignore-without-ticket-reference.rule.yaml +33 -0
- package/rules/rust/rust.testing.real-network-in-unit-test.rule.yaml +33 -0
- package/rules/rust/rust.testing.thread-sleep-in-unit-test.rule.yaml +33 -0
- package/rules/shared/security.archive-path-traversal.rule.yaml +41 -0
- package/rules/shared/security.external-file-upload.rule.yaml +40 -0
- package/rules/shared/security.permissive-file-permissions.rule.yaml +40 -0
- package/rules/shared/security.sensitive-data-egress.rule.yaml +36 -0
- package/rules/typescript/ts.correctness.assignment-in-condition.rule.yaml +36 -0
- package/rules/typescript/ts.correctness.assignment-to-import-binding.rule.yaml +36 -0
- package/rules/typescript/ts.correctness.async-promise-executor.rule.yaml +36 -0
- package/rules/typescript/ts.correctness.duplicate-function-parameter.rule.yaml +36 -0
- package/rules/typescript/ts.correctness.duplicate-import-source.rule.yaml +36 -0
- package/rules/typescript/ts.correctness.duplicate-object-key.rule.yaml +36 -0
- package/rules/typescript/ts.correctness.duplicate-switch-case.rule.yaml +36 -0
- package/rules/typescript/ts.correctness.empty-block-statement.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.identical-comparison-operands.rule.yaml +36 -0
- package/rules/typescript/ts.correctness.reassign-catch-binding.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.regexp-pattern-unusual-control-character.rule.yaml +35 -0
- package/rules/typescript/ts.correctness.self-assignment.rule.yaml +36 -0
- package/rules/typescript/ts.next.server-action-missing-local-auth.rule.yaml +35 -0
- package/rules/typescript/ts.performance.no-array-spread-in-hot-loop.rule.yaml +32 -0
- package/rules/typescript/ts.performance.no-cache-miss-from-unstable-key.rule.yaml +32 -0
- package/rules/typescript/ts.performance.no-expensive-sort-in-render-path.rule.yaml +32 -0
- package/rules/typescript/ts.performance.no-json-parse-stringify-clone.rule.yaml +32 -0
- package/rules/typescript/ts.performance.no-large-object-spread-in-loop.rule.yaml +32 -0
- package/rules/typescript/ts.performance.no-n-plus-one-await-in-map.rule.yaml +32 -0
- package/rules/typescript/ts.performance.no-redundant-network-fetch.rule.yaml +32 -0
- package/rules/typescript/ts.performance.no-regex-construction-in-loop.rule.yaml +32 -0
- package/rules/typescript/ts.performance.no-sync-fs-in-request-path.rule.yaml +32 -0
- package/rules/typescript/ts.performance.no-unbounded-concurrency.rule.yaml +32 -0
- package/rules/typescript/ts.quality.no-ambiguous-abbreviations.rule.yaml +27 -0
- package/rules/typescript/ts.quality.no-barrel-file-cycle.rule.yaml +27 -0
- package/rules/typescript/ts.quality.no-boolean-parameter-trap.rule.yaml +27 -0
- package/rules/typescript/ts.quality.no-dead-export.rule.yaml +27 -0
- package/rules/typescript/ts.quality.no-hidden-side-effect-import.rule.yaml +27 -0
- package/rules/typescript/ts.quality.no-inconsistent-error-shape.rule.yaml +27 -0
- package/rules/typescript/ts.quality.no-mixed-abstraction-level.rule.yaml +27 -0
- package/rules/typescript/ts.quality.no-primitive-obsession-in-domain-model.rule.yaml +27 -0
- package/rules/typescript/ts.quality.no-temporal-coupling.rule.yaml +27 -0
- package/rules/typescript/ts.quality.no-wide-public-surface.rule.yaml +27 -0
- package/rules/typescript/ts.react.no-accessibility-label-missing.rule.yaml +36 -0
- package/rules/typescript/ts.react.no-activedescendant-on-non-focusable-host.rule.yaml +36 -0
- package/rules/typescript/ts.react.no-click-without-keyboard-handler.rule.yaml +36 -0
- package/rules/typescript/ts.react.no-deprecated-create-factory.rule.yaml +34 -0
- package/rules/typescript/ts.react.no-deprecated-react-dom-root-api.rule.yaml +34 -0
- package/rules/typescript/ts.react.no-derived-state-from-props.rule.yaml +34 -0
- package/rules/typescript/ts.react.no-effect-fetch-without-cancellation.rule.yaml +35 -0
- package/rules/typescript/ts.react.no-find-dom-node.rule.yaml +34 -0
- package/rules/typescript/ts.react.no-img-missing-alt-text.rule.yaml +36 -0
- package/rules/typescript/ts.react.no-index-as-key-in-dynamic-list.rule.yaml +34 -0
- package/rules/typescript/ts.react.no-interactive-role-on-static-semantics.rule.yaml +36 -0
- package/rules/typescript/ts.react.no-invalid-anchor-href.rule.yaml +36 -0
- package/rules/typescript/ts.react.no-keyboard-interaction-without-widget-role.rule.yaml +36 -0
- package/rules/typescript/ts.react.no-legacy-lifecycle.rule.yaml +34 -0
- package/rules/typescript/ts.react.no-missing-error-boundary.rule.yaml +36 -0
- package/rules/typescript/ts.react.no-positive-tabindex.rule.yaml +36 -0
- package/rules/typescript/ts.react.no-static-element-with-synthetic-handlers.rule.yaml +36 -0
- package/rules/typescript/ts.react.no-string-ref.rule.yaml +34 -0
- package/rules/typescript/ts.react.no-uncontrolled-to-controlled-input.rule.yaml +34 -0
- package/rules/typescript/ts.react.no-widget-role-without-tabindex.rule.yaml +36 -0
- package/rules/typescript/ts.security.ajv-insecure-configuration.rule.yaml +34 -0
- package/rules/typescript/ts.security.angular-dom-sanitizer-bypass-untrusted-input.rule.yaml +35 -0
- package/rules/typescript/ts.security.apollo-server-csrf-disabled.rule.yaml +36 -0
- package/rules/typescript/ts.security.apollo-server-graphql-dev-tooling-exposure.rule.yaml +36 -0
- package/rules/typescript/ts.security.apollo-server-introspection-exposure.rule.yaml +35 -0
- package/rules/typescript/ts.security.apollo-server-missing-query-limits.rule.yaml +35 -0
- package/rules/typescript/ts.security.astro-vite-public-secret-define.rule.yaml +39 -0
- package/rules/typescript/ts.security.debug-statement-in-source.rule.yaml +36 -0
- package/rules/typescript/ts.security.electron-dangerous-webpreferences.rule.yaml +35 -0
- package/rules/typescript/ts.security.electron-insecure-local-state.rule.yaml +35 -0
- package/rules/typescript/ts.security.electron-missing-ipc-origin-check.rule.yaml +35 -0
- package/rules/typescript/ts.security.electron-shell-open-external-unvalidated.rule.yaml +35 -0
- package/rules/typescript/ts.security.express-error-handler-information-disclosure.rule.yaml +35 -0
- package/rules/typescript/ts.security.express-static-dotfiles-allow.rule.yaml +35 -0
- package/rules/typescript/ts.security.express-unbounded-body-parser.rule.yaml +34 -0
- package/rules/typescript/ts.security.express-user-controlled-static-mount.rule.yaml +35 -0
- package/rules/typescript/ts.security.fastify-excessive-body-limit.rule.yaml +34 -0
- package/rules/typescript/ts.security.fastify-public-bind-without-trust-proxy.rule.yaml +38 -0
- package/rules/typescript/ts.security.graphql-upload-without-csrf-guard.rule.yaml +36 -0
- package/rules/typescript/ts.security.iframe-missing-sandbox-attribute.rule.yaml +35 -0
- package/rules/typescript/ts.security.insecure-content-security-policy-literal.rule.yaml +35 -0
- package/rules/typescript/ts.security.insecure-helmet-hardening-options.rule.yaml +36 -0
- package/rules/typescript/ts.security.jwt-insecure-signing-algorithm.rule.yaml +35 -0
- package/rules/typescript/ts.security.legacy-buffer-constructor.rule.yaml +35 -0
- package/rules/typescript/ts.security.log-injection.rule.yaml +36 -0
- package/rules/typescript/ts.security.nestjs-helmet-after-route-mount.rule.yaml +34 -0
- package/rules/typescript/ts.security.nestjs-missing-global-validation-pipe.rule.yaml +35 -0
- package/rules/typescript/ts.security.nestjs-skip-throttle-sensitive-route.rule.yaml +35 -0
- package/rules/typescript/ts.security.nestjs-validation-pipe-without-whitelist.rule.yaml +36 -0
- package/rules/typescript/ts.security.nuxt-public-runtime-secret.rule.yaml +38 -0
- package/rules/typescript/ts.security.open-redirect.rule.yaml +2 -0
- package/rules/typescript/ts.security.request-driven-array-index-access.rule.yaml +33 -0
- package/rules/typescript/ts.security.sensitive-data-egress.rule.yaml +1 -0
- package/rules/typescript/ts.security.ssrf.rule.yaml +1 -0
- package/rules/typescript/ts.security.unsafe-dompurify-version.rule.yaml +36 -0
- package/rules/typescript/ts.security.unsafe-marked-version.rule.yaml +36 -0
- package/rules/typescript/ts.security.xml-parse-string-with-untrusted-input.rule.yaml +35 -0
- package/rules/typescript/ts.testing.no-flaky-timer-test.rule.yaml +38 -0
- package/rules/typescript/ts.testing.no-focused-test.rule.yaml +34 -0
- package/rules/typescript/ts.testing.no-missing-edge-case-tests.rule.yaml +35 -0
- package/rules/typescript/ts.testing.no-network-call-in-unit-test.rule.yaml +38 -0
- package/rules/typescript/ts.testing.no-skipped-test-without-ticket.rule.yaml +34 -0
- package/rules/typescript/ts.testing.no-snapshot-without-intent.rule.yaml +34 -0
- package/rules/typescript/ts.testing.no-test-only-code-in-production.rule.yaml +38 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.insecure-content-security-policy-literal
|
|
5
|
+
title: Avoid unsafe Content-Security-Policy literals
|
|
6
|
+
summary: Static CSP header values should not rely on unsafe-inline, unsafe-eval, or unsafe-hashes without nonces.
|
|
7
|
+
rationale: Permissive CSP keywords weaken XSS defenses for every response that carries the header.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- csp
|
|
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.insecure-content-security-policy-literal
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.misconfiguration
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.8
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- csp
|
|
31
|
+
message:
|
|
32
|
+
title: "Tighten Content-Security-Policy in ${captures.issue.text}"
|
|
33
|
+
summary: "${captures.issue.text} sets a CSP that includes unsafe directives without a nonce-based escape hatch."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Prefer nonces or hashes, remove unsafe-inline and unsafe-eval, and scope directives to the smallest required surface.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.insecure-helmet-hardening-options
|
|
5
|
+
title: Avoid disabling core Helmet protections
|
|
6
|
+
summary: Helmet should keep nosniff, HSTS, DNS prefetch control, Expect-CT, and referrer policy enabled unless another gateway enforces them.
|
|
7
|
+
rationale: Turning off individual Helmet middlewares removes baseline HTTP hardening that is a high-signal misconfiguration risk.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- express
|
|
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.insecure-helmet-hardening-options
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.misconfiguration
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.86
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- express
|
|
31
|
+
- headers
|
|
32
|
+
message:
|
|
33
|
+
title: "Review disabled Helmet option in ${captures.issue.text}"
|
|
34
|
+
summary: "${captures.issue.text} disables a Helmet protection that should usually remain enabled."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Remove false overrides for nosniff, HSTS, DNS prefetch control, Expect-CT, and referrer policy unless a documented compensating control applies.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.jwt-insecure-signing-algorithm
|
|
5
|
+
title: Do not sign JWTs with the none algorithm
|
|
6
|
+
summary: JSON Web Token signing options must not enable the none algorithm.
|
|
7
|
+
rationale: The none algorithm allows tokens to be accepted without verification, defeating authentication.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- jwt
|
|
11
|
+
- authentication
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: ts.security.jwt-insecure-signing-algorithm
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.authentication
|
|
26
|
+
severity: critical
|
|
27
|
+
confidence: 0.95
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- jwt
|
|
31
|
+
message:
|
|
32
|
+
title: "Remove insecure JWT algorithm from ${captures.issue.text}"
|
|
33
|
+
summary: "${captures.issue.text} is configured with the none algorithm or algorithm list."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Require asymmetric or HMAC algorithms explicitly and reject none at signing and verification layers.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.legacy-buffer-constructor
|
|
5
|
+
title: Replace legacy Buffer constructors
|
|
6
|
+
summary: Use Buffer.from, Buffer.alloc, or Buffer.allocUnsafe instead of the deprecated Buffer constructor.
|
|
7
|
+
rationale: Legacy constructors behave differently across Node versions and are harder to audit for safe allocation.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- node
|
|
11
|
+
- memory
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.legacy-buffer-constructor
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.misconfiguration
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.9
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- node
|
|
31
|
+
message:
|
|
32
|
+
title: "Replace ${captures.issue.text}"
|
|
33
|
+
summary: "${captures.issue.text} uses the deprecated Buffer constructor API."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Prefer Buffer.from for encoded data and Buffer.alloc for zero-filled buffers sized by trusted logic.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.log-injection
|
|
5
|
+
title: Sanitize user-controlled values before they reach log messages
|
|
6
|
+
summary: Logger calls in pino, winston, bunyan, and consola should not interpolate or concatenate request input directly into the message text.
|
|
7
|
+
rationale: Unsanitized request data in log messages enables CRLF injection, control-character smuggling, and downstream log-parser confusion. Wrapping the value with a structured field, JSON encoder, or CRLF-stripping replace neutralizes the vector.
|
|
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.log-injection
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.input-validation
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.85
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- logging
|
|
31
|
+
- input-validation
|
|
32
|
+
message:
|
|
33
|
+
title: Sanitize user-controlled values before reaching `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` interpolates request data into a log message without an obvious sanitizer."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Pass request data as a structured field, JSON-encode it, or strip CRLF and control characters before concatenating it into the log message.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.nestjs-helmet-after-route-mount
|
|
5
|
+
title: Register Helmet before Nest route mounts
|
|
6
|
+
summary: Nest bootstrap files should apply Helmet before mounting path-bound routers.
|
|
7
|
+
rationale: Middleware order determines whether framed routes inherit Helmet protections; mounting routers too early widens exposure.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- nestjs
|
|
11
|
+
- rules-catalog
|
|
12
|
+
stability: experimental
|
|
13
|
+
appliesTo: block
|
|
14
|
+
scope:
|
|
15
|
+
languages:
|
|
16
|
+
- typescript
|
|
17
|
+
- javascript
|
|
18
|
+
match:
|
|
19
|
+
fact:
|
|
20
|
+
kind: security.nestjs-helmet-after-route-mount
|
|
21
|
+
bind: issue
|
|
22
|
+
emit:
|
|
23
|
+
finding:
|
|
24
|
+
category: security.misconfiguration
|
|
25
|
+
severity: medium
|
|
26
|
+
confidence: 0.8
|
|
27
|
+
tags:
|
|
28
|
+
- security
|
|
29
|
+
- nestjs
|
|
30
|
+
message:
|
|
31
|
+
title: Move Helmet ahead of routed middleware
|
|
32
|
+
summary: Helmet runs after a route-mounted `app.use` in this Nest bootstrap.
|
|
33
|
+
remediation:
|
|
34
|
+
summary: Call `helmet()` before registering routers bound to external paths unless another gateway applies equivalent protections.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.nestjs-missing-global-validation-pipe
|
|
5
|
+
title: Add a global Nest ValidationPipe
|
|
6
|
+
summary: Nest bootstrap entries should register `ValidationPipe` globally when controllers parse bodies or DTOs.
|
|
7
|
+
rationale: Without a validation pipe unexpected fields can reach controllers and weaken input hygiene.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- nestjs
|
|
11
|
+
- rules-catalog
|
|
12
|
+
stability: experimental
|
|
13
|
+
appliesTo: block
|
|
14
|
+
scope:
|
|
15
|
+
languages:
|
|
16
|
+
- typescript
|
|
17
|
+
- javascript
|
|
18
|
+
match:
|
|
19
|
+
fact:
|
|
20
|
+
kind: security.nestjs-missing-global-validation-pipe
|
|
21
|
+
bind: issue
|
|
22
|
+
emit:
|
|
23
|
+
finding:
|
|
24
|
+
category: security.misconfiguration
|
|
25
|
+
severity: medium
|
|
26
|
+
confidence: 0.68
|
|
27
|
+
tags:
|
|
28
|
+
- security
|
|
29
|
+
- nestjs
|
|
30
|
+
message:
|
|
31
|
+
title: Register `useGlobalPipes` with ValidationPipe
|
|
32
|
+
summary: Nest bootstrap completes without calling `useGlobalPipes`.
|
|
33
|
+
remediation:
|
|
34
|
+
summary: >-
|
|
35
|
+
Call app.useGlobalPipes with ValidationPipe using whitelist and forbidNonWhitelisted flags near bootstrap completion.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.nestjs-skip-throttle-sensitive-route
|
|
5
|
+
title: Do not skip throttling on credential routes
|
|
6
|
+
summary: Sensitive Nest routes should not disable `@nestjs/throttler` protections without a compensating throttle.
|
|
7
|
+
rationale: Authentication endpoints are brute-force magnets; removing throttling removes basic abuse resistance.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- nestjs
|
|
11
|
+
- rules-catalog
|
|
12
|
+
stability: experimental
|
|
13
|
+
appliesTo: block
|
|
14
|
+
scope:
|
|
15
|
+
languages:
|
|
16
|
+
- typescript
|
|
17
|
+
- javascript
|
|
18
|
+
match:
|
|
19
|
+
fact:
|
|
20
|
+
kind: security.nestjs-skip-throttle-sensitive-route
|
|
21
|
+
bind: issue
|
|
22
|
+
emit:
|
|
23
|
+
finding:
|
|
24
|
+
category: security.authentication
|
|
25
|
+
severity: medium
|
|
26
|
+
confidence: 0.79
|
|
27
|
+
tags:
|
|
28
|
+
- security
|
|
29
|
+
- nestjs
|
|
30
|
+
- throttling
|
|
31
|
+
message:
|
|
32
|
+
title: Restore throttling for brute-force sensitive handlers
|
|
33
|
+
summary: "`${captures.issue.text}` disables throttling on an authentication-sensitive route."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Remove `@SkipThrottle()` or pair it with an explicit `@Throttle` policy tuned for the handler.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.nestjs-validation-pipe-without-whitelist
|
|
5
|
+
title: Harden Nest ValidationPipe with whitelist mode
|
|
6
|
+
summary: Global ValidationPipe instances should enable whitelist-style stripping for unexpected fields.
|
|
7
|
+
rationale: Allowing undeclared fields preserves attack surface for mass-assignment style bugs.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- nestjs
|
|
11
|
+
- rules-catalog
|
|
12
|
+
stability: experimental
|
|
13
|
+
appliesTo: block
|
|
14
|
+
scope:
|
|
15
|
+
languages:
|
|
16
|
+
- typescript
|
|
17
|
+
- javascript
|
|
18
|
+
match:
|
|
19
|
+
fact:
|
|
20
|
+
kind: security.nestjs-validation-pipe-without-whitelist
|
|
21
|
+
bind: issue
|
|
22
|
+
emit:
|
|
23
|
+
finding:
|
|
24
|
+
category: security.misconfiguration
|
|
25
|
+
severity: medium
|
|
26
|
+
confidence: 0.74
|
|
27
|
+
tags:
|
|
28
|
+
- security
|
|
29
|
+
- nestjs
|
|
30
|
+
message:
|
|
31
|
+
title: Enable ValidationPipe whitelist hardening
|
|
32
|
+
summary: >-
|
|
33
|
+
ValidationPipe is configured without literal whitelist true.
|
|
34
|
+
remediation:
|
|
35
|
+
summary: >-
|
|
36
|
+
Enable whitelist true and usually forbidNonWhitelisted true on the global ValidationPipe.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.nuxt-public-runtime-secret
|
|
5
|
+
title: Keep secrets out of Nuxt public runtime config
|
|
6
|
+
summary: >-
|
|
7
|
+
Sensitive credentials must not be exposed through runtimeConfig.public, which is visible to client bundles.
|
|
8
|
+
rationale: >-
|
|
9
|
+
Nuxt exposes runtimeConfig.public to the browser; placing secret material there leaks API keys, database passwords, and signing material to every visitor.
|
|
10
|
+
tags:
|
|
11
|
+
- security
|
|
12
|
+
- nuxt
|
|
13
|
+
- rules-catalog
|
|
14
|
+
stability: experimental
|
|
15
|
+
appliesTo: block
|
|
16
|
+
scope:
|
|
17
|
+
languages:
|
|
18
|
+
- typescript
|
|
19
|
+
- javascript
|
|
20
|
+
match:
|
|
21
|
+
fact:
|
|
22
|
+
kind: security.nuxt-public-runtime-secret
|
|
23
|
+
bind: issue
|
|
24
|
+
emit:
|
|
25
|
+
finding:
|
|
26
|
+
category: security.misconfiguration
|
|
27
|
+
severity: high
|
|
28
|
+
confidence: 0.86
|
|
29
|
+
tags:
|
|
30
|
+
- security
|
|
31
|
+
- nuxt
|
|
32
|
+
message:
|
|
33
|
+
title: Move ${captures.issue.text} out of runtimeConfig.public
|
|
34
|
+
summary: >-
|
|
35
|
+
runtimeConfig.public declares ${captures.issue.text}, which looks like a secret or private credential.
|
|
36
|
+
remediation:
|
|
37
|
+
summary: >-
|
|
38
|
+
Keep secrets in the private runtimeConfig tree (non-public) and expose only publishable identifiers to the client after reviewing Nuxt runtime config documentation.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.request-driven-array-index-access
|
|
5
|
+
title: Avoid request-driven array indexing without bounds checks
|
|
6
|
+
summary: Arrays indexed with request-derived keys can read or write out-of-bounds entries.
|
|
7
|
+
rationale: Attacker-controlled indexes bypass assumptions about array length and element initialization.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- correctness
|
|
11
|
+
- rules-catalog
|
|
12
|
+
stability: stable
|
|
13
|
+
appliesTo: block
|
|
14
|
+
scope:
|
|
15
|
+
languages:
|
|
16
|
+
- typescript
|
|
17
|
+
- javascript
|
|
18
|
+
match:
|
|
19
|
+
fact:
|
|
20
|
+
kind: security.request-driven-array-index-access
|
|
21
|
+
bind: issue
|
|
22
|
+
emit:
|
|
23
|
+
finding:
|
|
24
|
+
category: security.input-validation
|
|
25
|
+
severity: medium
|
|
26
|
+
confidence: 0.72
|
|
27
|
+
tags:
|
|
28
|
+
- security
|
|
29
|
+
message:
|
|
30
|
+
title: "Validate index ${captures.issue.text} before use"
|
|
31
|
+
summary: "Array access uses a computed index derived from ${captures.issue.text}."
|
|
32
|
+
remediation:
|
|
33
|
+
summary: Parse and bound-check indexes, prefer maps keyed by stable identifiers, or avoid indexing arrays with request data.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.unsafe-dompurify-version
|
|
5
|
+
title: Upgrade DOM sanitization dependency
|
|
6
|
+
summary: DOM sanitization libraries should stay on patched versions before they are trusted for untrusted HTML.
|
|
7
|
+
rationale: Older sanitizer versions can miss browser parsing edge cases and leave XSS protections incomplete.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- dependency
|
|
11
|
+
- xss
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: experimental
|
|
14
|
+
appliesTo: project
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.dependency.dompurify-unsafe-version
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.dependency
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.82
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- dependency
|
|
31
|
+
- xss
|
|
32
|
+
message:
|
|
33
|
+
title: Upgrade `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` is below the minimum sanitizer version Critiq treats as safe for untrusted HTML."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Upgrade the package, then keep HTML sanitizer usage behind a small reviewed wrapper.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.unsafe-marked-version
|
|
5
|
+
title: Upgrade Markdown rendering dependency
|
|
6
|
+
summary: Markdown renderers should stay on patched versions before rendering untrusted content.
|
|
7
|
+
rationale: Older Markdown renderer versions can expose unsafe HTML handling and parser edge cases.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- dependency
|
|
11
|
+
- xss
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: experimental
|
|
14
|
+
appliesTo: project
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.dependency.marked-unsafe-version
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.dependency
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.82
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- dependency
|
|
31
|
+
- xss
|
|
32
|
+
message:
|
|
33
|
+
title: Upgrade `${captures.issue.text}`
|
|
34
|
+
summary: "`${captures.issue.text}` is below the minimum Markdown renderer version Critiq treats as safe for untrusted content."
|
|
35
|
+
remediation:
|
|
36
|
+
summary: Upgrade the package and keep untrusted Markdown rendering behind explicit sanitization.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.security.xml-parse-string-with-untrusted-input
|
|
5
|
+
title: Do not parse untrusted XML with permissive parsers
|
|
6
|
+
summary: parseString and similar XML helpers should not consume request-controlled payloads without hardening.
|
|
7
|
+
rationale: Untrusted XML can enable XXE-style parser abuse depending on the underlying implementation and parser flags.
|
|
8
|
+
tags:
|
|
9
|
+
- security
|
|
10
|
+
- xml
|
|
11
|
+
- deserialization
|
|
12
|
+
- rules-catalog
|
|
13
|
+
stability: stable
|
|
14
|
+
appliesTo: block
|
|
15
|
+
scope:
|
|
16
|
+
languages:
|
|
17
|
+
- typescript
|
|
18
|
+
- javascript
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: security.xml-parse-string-with-untrusted-input
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: security.deserialization
|
|
26
|
+
severity: high
|
|
27
|
+
confidence: 0.78
|
|
28
|
+
tags:
|
|
29
|
+
- security
|
|
30
|
+
- xml
|
|
31
|
+
message:
|
|
32
|
+
title: "Validate XML parsing for ${captures.issue.text}"
|
|
33
|
+
summary: "${captures.issue.text} parses XML that appears request-driven."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Disable external entities, validate payloads against a strict schema, and parse with a hardened XML configuration.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.testing.no-flaky-timer-test
|
|
5
|
+
title: Prefer fake timers in unit tests
|
|
6
|
+
summary: Real timers, sleeps, or wall-clock reads in unit tests are flaky unless fake timers are enabled for the file.
|
|
7
|
+
rationale: Wall-clock based tests race CI load and parallelization; fake timers keep behavior deterministic.
|
|
8
|
+
tags:
|
|
9
|
+
- testing
|
|
10
|
+
- quality
|
|
11
|
+
- rules-catalog
|
|
12
|
+
stability: experimental
|
|
13
|
+
appliesTo: block
|
|
14
|
+
scope:
|
|
15
|
+
languages:
|
|
16
|
+
- typescript
|
|
17
|
+
- javascript
|
|
18
|
+
paths:
|
|
19
|
+
exclude:
|
|
20
|
+
- "**/e2e/**"
|
|
21
|
+
- "**/*.integration.test.*"
|
|
22
|
+
match:
|
|
23
|
+
fact:
|
|
24
|
+
kind: testing.flaky-timer-in-test
|
|
25
|
+
bind: issue
|
|
26
|
+
emit:
|
|
27
|
+
finding:
|
|
28
|
+
category: quality.testing
|
|
29
|
+
severity: low
|
|
30
|
+
confidence: 0.68
|
|
31
|
+
tags:
|
|
32
|
+
- testing
|
|
33
|
+
- timers
|
|
34
|
+
message:
|
|
35
|
+
title: Stabilize timer usage in `${captures.issue.text}`
|
|
36
|
+
summary: "`${captures.issue.text}` uses real timers or wall-clock reads without `jest.useFakeTimers` / `vi.useFakeTimers` in the same file."
|
|
37
|
+
remediation:
|
|
38
|
+
summary: Enable fake timers for the suite, inject a clock abstraction, or move timing assertions behind a test double.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.testing.no-focused-test
|
|
5
|
+
title: Remove focused or exclusive tests before merge
|
|
6
|
+
summary: Focused tests such as it.only or describe.only should not ship because they silence the rest of the suite in CI.
|
|
7
|
+
rationale: Exclusive tests hide failures in sibling cases and are a common accidental merge footgun.
|
|
8
|
+
tags:
|
|
9
|
+
- testing
|
|
10
|
+
- quality
|
|
11
|
+
- rules-catalog
|
|
12
|
+
stability: experimental
|
|
13
|
+
appliesTo: block
|
|
14
|
+
scope:
|
|
15
|
+
languages:
|
|
16
|
+
- typescript
|
|
17
|
+
- javascript
|
|
18
|
+
match:
|
|
19
|
+
fact:
|
|
20
|
+
kind: testing.focused-only-invocation
|
|
21
|
+
bind: issue
|
|
22
|
+
emit:
|
|
23
|
+
finding:
|
|
24
|
+
category: quality.testing
|
|
25
|
+
severity: medium
|
|
26
|
+
confidence: 0.88
|
|
27
|
+
tags:
|
|
28
|
+
- testing
|
|
29
|
+
- ci
|
|
30
|
+
message:
|
|
31
|
+
title: Remove focused test `${captures.issue.text}`
|
|
32
|
+
summary: "`${captures.issue.text}` runs in exclusive mode so other tests in the file or suite are skipped."
|
|
33
|
+
remediation:
|
|
34
|
+
summary: Remove `.only` / `fit` / `fdescribe` style exclusivity and rely on the full suite in CI.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.testing.no-missing-edge-case-tests
|
|
5
|
+
title: Update tests when branch-heavy service logic changes
|
|
6
|
+
summary: Diffs that touch many branches in critical service paths should update paired tests in the same change.
|
|
7
|
+
rationale: Branch-heavy edits without test updates often miss boundary and failure behavior reviewers expect.
|
|
8
|
+
tags:
|
|
9
|
+
- testing
|
|
10
|
+
- quality
|
|
11
|
+
- rules-catalog
|
|
12
|
+
stability: experimental
|
|
13
|
+
appliesTo: project
|
|
14
|
+
scope:
|
|
15
|
+
languages:
|
|
16
|
+
- typescript
|
|
17
|
+
- javascript
|
|
18
|
+
changedLinesOnly: false
|
|
19
|
+
match:
|
|
20
|
+
fact:
|
|
21
|
+
kind: testing.missing-edge-case-tests-for-changes
|
|
22
|
+
bind: issue
|
|
23
|
+
emit:
|
|
24
|
+
finding:
|
|
25
|
+
category: quality.testing
|
|
26
|
+
severity: medium
|
|
27
|
+
confidence: 0.66
|
|
28
|
+
tags:
|
|
29
|
+
- testing
|
|
30
|
+
- diff
|
|
31
|
+
message:
|
|
32
|
+
title: Exercise new branches in `${captures.issue.text}`
|
|
33
|
+
summary: "`${captures.issue.text}` changes branch-heavy logic on a critical path without a corresponding test file change."
|
|
34
|
+
remediation:
|
|
35
|
+
summary: Extend the paired unit test with cases for new branches, guards, and failure paths touched by the diff.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
apiVersion: critiq.dev/v1alpha1
|
|
2
|
+
kind: Rule
|
|
3
|
+
metadata:
|
|
4
|
+
id: ts.testing.no-network-call-in-unit-test
|
|
5
|
+
title: Avoid real network calls in unit tests
|
|
6
|
+
summary: Unit tests should not open real sockets; prefer doubles, recordings, or local fakes.
|
|
7
|
+
rationale: Real network calls make tests flaky, slow, and unsafe against live systems.
|
|
8
|
+
tags:
|
|
9
|
+
- testing
|
|
10
|
+
- quality
|
|
11
|
+
- rules-catalog
|
|
12
|
+
stability: experimental
|
|
13
|
+
appliesTo: block
|
|
14
|
+
scope:
|
|
15
|
+
languages:
|
|
16
|
+
- typescript
|
|
17
|
+
- javascript
|
|
18
|
+
paths:
|
|
19
|
+
exclude:
|
|
20
|
+
- "**/e2e/**"
|
|
21
|
+
- "**/*.integration.test.*"
|
|
22
|
+
match:
|
|
23
|
+
fact:
|
|
24
|
+
kind: testing.real-network-in-unit-test
|
|
25
|
+
bind: issue
|
|
26
|
+
emit:
|
|
27
|
+
finding:
|
|
28
|
+
category: quality.testing
|
|
29
|
+
severity: medium
|
|
30
|
+
confidence: 0.74
|
|
31
|
+
tags:
|
|
32
|
+
- testing
|
|
33
|
+
- network
|
|
34
|
+
message:
|
|
35
|
+
title: Replace live network call `${captures.issue.text}`
|
|
36
|
+
summary: "`${captures.issue.text}` performs an outbound HTTP style call inside a unit test path."
|
|
37
|
+
remediation:
|
|
38
|
+
summary: Mock HTTP clients, use an in-memory server, or relocate the scenario to an explicit integration suite.
|