eslint-plugin-secure-coding 2.3.2 → 2.3.3
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 +1 -0
- package/package.json +3 -10
- package/src/index.ts +605 -0
- package/src/rules/__tests__/integration-demo.test.ts +290 -0
- package/src/rules/__tests__/integration-llm.test.ts +89 -0
- package/src/rules/database-injection/database-injection.test.ts +456 -0
- package/src/rules/database-injection/index.ts +488 -0
- package/src/rules/detect-child-process/detect-child-process.test.ts +207 -0
- package/src/rules/detect-child-process/index.ts +634 -0
- package/src/rules/detect-eval-with-expression/detect-eval-with-expression.test.ts +416 -0
- package/src/rules/detect-eval-with-expression/index.ts +463 -0
- package/src/rules/detect-mixed-content/detect-mixed-content.test.ts +28 -0
- package/src/rules/detect-mixed-content/index.ts +52 -0
- package/src/rules/detect-non-literal-fs-filename/detect-non-literal-fs-filename.test.ts +269 -0
- package/src/rules/detect-non-literal-fs-filename/index.ts +551 -0
- package/src/rules/detect-non-literal-regexp/detect-non-literal-regexp.test.ts +189 -0
- package/src/rules/detect-non-literal-regexp/index.ts +490 -0
- package/src/rules/detect-object-injection/detect-object-injection.test.ts +440 -0
- package/src/rules/detect-object-injection/index.ts +674 -0
- package/src/rules/detect-suspicious-dependencies/detect-suspicious-dependencies.test.ts +32 -0
- package/src/rules/detect-suspicious-dependencies/index.ts +84 -0
- package/src/rules/detect-weak-password-validation/detect-weak-password-validation.test.ts +31 -0
- package/src/rules/detect-weak-password-validation/index.ts +68 -0
- package/src/rules/no-allow-arbitrary-loads/index.ts +54 -0
- package/src/rules/no-allow-arbitrary-loads/no-allow-arbitrary-loads.test.ts +28 -0
- package/src/rules/no-arbitrary-file-access/index.ts +238 -0
- package/src/rules/no-arbitrary-file-access/no-arbitrary-file-access.test.ts +119 -0
- package/src/rules/no-buffer-overread/index.ts +724 -0
- package/src/rules/no-buffer-overread/no-buffer-overread.test.ts +313 -0
- package/src/rules/no-clickjacking/index.ts +481 -0
- package/src/rules/no-clickjacking/no-clickjacking.test.ts +253 -0
- package/src/rules/no-client-side-auth-logic/index.ts +81 -0
- package/src/rules/no-client-side-auth-logic/no-client-side-auth-logic.test.ts +33 -0
- package/src/rules/no-credentials-in-query-params/index.ts +69 -0
- package/src/rules/no-credentials-in-query-params/no-credentials-in-query-params.test.ts +33 -0
- package/src/rules/no-credentials-in-storage-api/index.ts +64 -0
- package/src/rules/no-credentials-in-storage-api/no-credentials-in-storage-api.test.ts +31 -0
- package/src/rules/no-data-in-temp-storage/index.ts +75 -0
- package/src/rules/no-data-in-temp-storage/no-data-in-temp-storage.test.ts +33 -0
- package/src/rules/no-debug-code-in-production/index.ts +59 -0
- package/src/rules/no-debug-code-in-production/no-debug-code-in-production.test.ts +26 -0
- package/src/rules/no-directive-injection/index.ts +551 -0
- package/src/rules/no-directive-injection/no-directive-injection.test.ts +305 -0
- package/src/rules/no-disabled-certificate-validation/index.ts +72 -0
- package/src/rules/no-disabled-certificate-validation/no-disabled-certificate-validation.test.ts +33 -0
- package/src/rules/no-document-cookie/index.ts +113 -0
- package/src/rules/no-document-cookie/no-document-cookie.test.ts +382 -0
- package/src/rules/no-dynamic-dependency-loading/index.ts +60 -0
- package/src/rules/no-dynamic-dependency-loading/no-dynamic-dependency-loading.test.ts +27 -0
- package/src/rules/no-electron-security-issues/index.ts +504 -0
- package/src/rules/no-electron-security-issues/no-electron-security-issues.test.ts +324 -0
- package/src/rules/no-exposed-debug-endpoints/index.ts +73 -0
- package/src/rules/no-exposed-debug-endpoints/no-exposed-debug-endpoints.test.ts +40 -0
- package/src/rules/no-exposed-sensitive-data/index.ts +428 -0
- package/src/rules/no-exposed-sensitive-data/no-exposed-sensitive-data.test.ts +75 -0
- package/src/rules/no-format-string-injection/index.ts +801 -0
- package/src/rules/no-format-string-injection/no-format-string-injection.test.ts +437 -0
- package/src/rules/no-graphql-injection/index.ts +508 -0
- package/src/rules/no-graphql-injection/no-graphql-injection.test.ts +371 -0
- package/src/rules/no-hardcoded-credentials/index.ts +478 -0
- package/src/rules/no-hardcoded-credentials/no-hardcoded-credentials.test.ts +639 -0
- package/src/rules/no-hardcoded-session-tokens/index.ts +69 -0
- package/src/rules/no-hardcoded-session-tokens/no-hardcoded-session-tokens.test.ts +42 -0
- package/src/rules/no-http-urls/index.ts +131 -0
- package/src/rules/no-http-urls/no-http-urls.test.ts +60 -0
- package/src/rules/no-improper-sanitization/index.ts +502 -0
- package/src/rules/no-improper-sanitization/no-improper-sanitization.test.ts +156 -0
- package/src/rules/no-improper-type-validation/index.ts +572 -0
- package/src/rules/no-improper-type-validation/no-improper-type-validation.test.ts +372 -0
- package/src/rules/no-insecure-comparison/index.ts +232 -0
- package/src/rules/no-insecure-comparison/no-insecure-comparison.test.ts +218 -0
- package/src/rules/no-insecure-cookie-settings/index.ts +391 -0
- package/src/rules/no-insecure-cookie-settings/no-insecure-cookie-settings.test.ts +409 -0
- package/src/rules/no-insecure-jwt/index.ts +467 -0
- package/src/rules/no-insecure-jwt/no-insecure-jwt.test.ts +259 -0
- package/src/rules/no-insecure-redirects/index.ts +267 -0
- package/src/rules/no-insecure-redirects/no-insecure-redirects.test.ts +108 -0
- package/src/rules/no-insecure-websocket/index.ts +72 -0
- package/src/rules/no-insecure-websocket/no-insecure-websocket.test.ts +42 -0
- package/src/rules/no-insufficient-postmessage-validation/index.ts +497 -0
- package/src/rules/no-insufficient-postmessage-validation/no-insufficient-postmessage-validation.test.ts +360 -0
- package/src/rules/no-insufficient-random/index.ts +288 -0
- package/src/rules/no-insufficient-random/no-insufficient-random.test.ts +246 -0
- package/src/rules/no-ldap-injection/index.ts +547 -0
- package/src/rules/no-ldap-injection/no-ldap-injection.test.ts +317 -0
- package/src/rules/no-missing-authentication/index.ts +408 -0
- package/src/rules/no-missing-authentication/no-missing-authentication.test.ts +350 -0
- package/src/rules/no-missing-cors-check/index.ts +453 -0
- package/src/rules/no-missing-cors-check/no-missing-cors-check.test.ts +392 -0
- package/src/rules/no-missing-csrf-protection/index.ts +229 -0
- package/src/rules/no-missing-csrf-protection/no-missing-csrf-protection.test.ts +222 -0
- package/src/rules/no-missing-security-headers/index.ts +266 -0
- package/src/rules/no-missing-security-headers/no-missing-security-headers.test.ts +98 -0
- package/src/rules/no-password-in-url/index.ts +64 -0
- package/src/rules/no-password-in-url/no-password-in-url.test.ts +27 -0
- package/src/rules/no-permissive-cors/index.ts +78 -0
- package/src/rules/no-permissive-cors/no-permissive-cors.test.ts +28 -0
- package/src/rules/no-pii-in-logs/index.ts +83 -0
- package/src/rules/no-pii-in-logs/no-pii-in-logs.test.ts +26 -0
- package/src/rules/no-postmessage-origin-wildcard/index.ts +67 -0
- package/src/rules/no-postmessage-origin-wildcard/no-postmessage-origin-wildcard.test.ts +27 -0
- package/src/rules/no-privilege-escalation/index.ts +403 -0
- package/src/rules/no-privilege-escalation/no-privilege-escalation.test.ts +306 -0
- package/src/rules/no-redos-vulnerable-regex/index.ts +379 -0
- package/src/rules/no-redos-vulnerable-regex/no-redos-vulnerable-regex.test.ts +83 -0
- package/src/rules/no-sensitive-data-exposure/index.ts +294 -0
- package/src/rules/no-sensitive-data-exposure/no-sensitive-data-exposure.test.ts +262 -0
- package/src/rules/no-sensitive-data-in-analytics/index.ts +73 -0
- package/src/rules/no-sensitive-data-in-analytics/no-sensitive-data-in-analytics.test.ts +42 -0
- package/src/rules/no-sensitive-data-in-cache/index.ts +59 -0
- package/src/rules/no-sensitive-data-in-cache/no-sensitive-data-in-cache.test.ts +32 -0
- package/src/rules/no-sql-injection/index.ts +424 -0
- package/src/rules/no-sql-injection/no-sql-injection.test.ts +303 -0
- package/src/rules/no-timing-attack/index.ts +552 -0
- package/src/rules/no-timing-attack/no-timing-attack.test.ts +348 -0
- package/src/rules/no-toctou-vulnerability/index.ts +250 -0
- package/src/rules/no-toctou-vulnerability/no-toctou-vulnerability.test.ts +60 -0
- package/src/rules/no-tracking-without-consent/index.ts +78 -0
- package/src/rules/no-tracking-without-consent/no-tracking-without-consent.test.ts +34 -0
- package/src/rules/no-unchecked-loop-condition/index.ts +781 -0
- package/src/rules/no-unchecked-loop-condition/no-unchecked-loop-condition.test.ts +459 -0
- package/src/rules/no-unencrypted-local-storage/index.ts +73 -0
- package/src/rules/no-unencrypted-local-storage/no-unencrypted-local-storage.test.ts +41 -0
- package/src/rules/no-unencrypted-transmission/index.ts +296 -0
- package/src/rules/no-unencrypted-transmission/no-unencrypted-transmission.test.ts +287 -0
- package/src/rules/no-unescaped-url-parameter/index.ts +424 -0
- package/src/rules/no-unescaped-url-parameter/no-unescaped-url-parameter.test.ts +263 -0
- package/src/rules/no-unlimited-resource-allocation/index.ts +767 -0
- package/src/rules/no-unlimited-resource-allocation/no-unlimited-resource-allocation.test.ts +544 -0
- package/src/rules/no-unsafe-deserialization/index.ts +593 -0
- package/src/rules/no-unsafe-deserialization/no-unsafe-deserialization.test.ts +310 -0
- package/src/rules/no-unsafe-dynamic-require/index.ts +125 -0
- package/src/rules/no-unsafe-dynamic-require/no-unsafe-dynamic-require.test.ts +151 -0
- package/src/rules/no-unsafe-regex-construction/index.ts +370 -0
- package/src/rules/no-unsafe-regex-construction/no-unsafe-regex-construction.test.ts +181 -0
- package/src/rules/no-unsanitized-html/index.ts +400 -0
- package/src/rules/no-unsanitized-html/no-unsanitized-html.test.ts +488 -0
- package/src/rules/no-unvalidated-deeplinks/index.ts +73 -0
- package/src/rules/no-unvalidated-deeplinks/no-unvalidated-deeplinks.test.ts +29 -0
- package/src/rules/no-unvalidated-user-input/index.ts +498 -0
- package/src/rules/no-unvalidated-user-input/no-unvalidated-user-input.test.ts +463 -0
- package/src/rules/no-verbose-error-messages/index.ts +83 -0
- package/src/rules/no-verbose-error-messages/no-verbose-error-messages.test.ts +34 -0
- package/src/rules/no-weak-crypto/index.ts +447 -0
- package/src/rules/no-weak-crypto/no-weak-crypto.test.ts +297 -0
- package/src/rules/no-weak-password-recovery/index.ts +509 -0
- package/src/rules/no-weak-password-recovery/no-weak-password-recovery.test.ts +184 -0
- package/src/rules/no-xpath-injection/index.ts +596 -0
- package/src/rules/no-xpath-injection/no-xpath-injection.test.ts +405 -0
- package/src/rules/no-xxe-injection/index.ts +342 -0
- package/src/rules/no-xxe-injection/no-xxe-injection.test.ts +122 -0
- package/src/rules/no-zip-slip/index.ts +526 -0
- package/src/rules/no-zip-slip/no-zip-slip.test.ts +305 -0
- package/src/rules/require-backend-authorization/index.ts +71 -0
- package/src/rules/require-backend-authorization/require-backend-authorization.test.ts +31 -0
- package/src/rules/require-code-minification/index.ts +54 -0
- package/src/rules/require-code-minification/require-code-minification.test.ts +30 -0
- package/src/rules/require-csp-headers/index.ts +74 -0
- package/src/rules/require-csp-headers/require-csp-headers.test.ts +34 -0
- package/src/rules/require-data-minimization/index.ts +65 -0
- package/src/rules/require-data-minimization/require-data-minimization.test.ts +31 -0
- package/src/rules/require-dependency-integrity/index.ts +78 -0
- package/src/rules/require-dependency-integrity/require-dependency-integrity.test.ts +44 -0
- package/src/rules/require-https-only/index.ts +75 -0
- package/src/rules/require-https-only/require-https-only.test.ts +26 -0
- package/src/rules/require-mime-type-validation/index.ts +77 -0
- package/src/rules/require-mime-type-validation/require-mime-type-validation.test.ts +32 -0
- package/src/rules/require-network-timeout/index.ts +58 -0
- package/src/rules/require-network-timeout/require-network-timeout.test.ts +26 -0
- package/src/rules/require-package-lock/index.ts +75 -0
- package/src/rules/require-package-lock/require-package-lock.test.ts +27 -0
- package/src/rules/require-secure-credential-storage/index.ts +60 -0
- package/src/rules/require-secure-credential-storage/require-secure-credential-storage.test.ts +26 -0
- package/src/rules/require-secure-defaults/index.ts +54 -0
- package/src/rules/require-secure-defaults/require-secure-defaults.test.ts +26 -0
- package/src/rules/require-secure-deletion/index.ts +52 -0
- package/src/rules/require-secure-deletion/require-secure-deletion.test.ts +29 -0
- package/src/rules/require-storage-encryption/index.ts +60 -0
- package/src/rules/require-storage-encryption/require-storage-encryption.test.ts +26 -0
- package/src/rules/require-url-validation/index.ts +85 -0
- package/src/rules/require-url-validation/require-url-validation.test.ts +32 -0
- package/src/types/{index.d.ts → index.ts} +157 -53
- package/src/index.d.ts +0 -32
- package/src/index.js +0 -465
- package/src/rules/database-injection/index.d.ts +0 -13
- package/src/rules/database-injection/index.js +0 -406
- package/src/rules/detect-child-process/index.d.ts +0 -11
- package/src/rules/detect-child-process/index.js +0 -529
- package/src/rules/detect-eval-with-expression/index.d.ts +0 -9
- package/src/rules/detect-eval-with-expression/index.js +0 -392
- package/src/rules/detect-mixed-content/index.d.ts +0 -8
- package/src/rules/detect-mixed-content/index.js +0 -44
- package/src/rules/detect-non-literal-fs-filename/index.d.ts +0 -7
- package/src/rules/detect-non-literal-fs-filename/index.js +0 -454
- package/src/rules/detect-non-literal-regexp/index.d.ts +0 -9
- package/src/rules/detect-non-literal-regexp/index.js +0 -403
- package/src/rules/detect-object-injection/index.d.ts +0 -11
- package/src/rules/detect-object-injection/index.js +0 -560
- package/src/rules/detect-suspicious-dependencies/index.d.ts +0 -8
- package/src/rules/detect-suspicious-dependencies/index.js +0 -71
- package/src/rules/detect-weak-password-validation/index.d.ts +0 -6
- package/src/rules/detect-weak-password-validation/index.js +0 -58
- package/src/rules/no-allow-arbitrary-loads/index.d.ts +0 -8
- package/src/rules/no-allow-arbitrary-loads/index.js +0 -47
- package/src/rules/no-arbitrary-file-access/index.d.ts +0 -13
- package/src/rules/no-arbitrary-file-access/index.js +0 -195
- package/src/rules/no-buffer-overread/index.d.ts +0 -29
- package/src/rules/no-buffer-overread/index.js +0 -606
- package/src/rules/no-clickjacking/index.d.ts +0 -10
- package/src/rules/no-clickjacking/index.js +0 -396
- package/src/rules/no-client-side-auth-logic/index.d.ts +0 -6
- package/src/rules/no-client-side-auth-logic/index.js +0 -69
- package/src/rules/no-credentials-in-query-params/index.d.ts +0 -8
- package/src/rules/no-credentials-in-query-params/index.js +0 -57
- package/src/rules/no-credentials-in-storage-api/index.d.ts +0 -6
- package/src/rules/no-credentials-in-storage-api/index.js +0 -54
- package/src/rules/no-data-in-temp-storage/index.d.ts +0 -6
- package/src/rules/no-data-in-temp-storage/index.js +0 -64
- package/src/rules/no-debug-code-in-production/index.d.ts +0 -8
- package/src/rules/no-debug-code-in-production/index.js +0 -51
- package/src/rules/no-directive-injection/index.d.ts +0 -12
- package/src/rules/no-directive-injection/index.js +0 -457
- package/src/rules/no-disabled-certificate-validation/index.d.ts +0 -6
- package/src/rules/no-disabled-certificate-validation/index.js +0 -61
- package/src/rules/no-document-cookie/index.d.ts +0 -5
- package/src/rules/no-document-cookie/index.js +0 -89
- package/src/rules/no-dynamic-dependency-loading/index.d.ts +0 -8
- package/src/rules/no-dynamic-dependency-loading/index.js +0 -51
- package/src/rules/no-electron-security-issues/index.d.ts +0 -10
- package/src/rules/no-electron-security-issues/index.js +0 -423
- package/src/rules/no-exposed-debug-endpoints/index.d.ts +0 -6
- package/src/rules/no-exposed-debug-endpoints/index.js +0 -62
- package/src/rules/no-exposed-sensitive-data/index.d.ts +0 -11
- package/src/rules/no-exposed-sensitive-data/index.js +0 -340
- package/src/rules/no-format-string-injection/index.d.ts +0 -17
- package/src/rules/no-format-string-injection/index.js +0 -660
- package/src/rules/no-graphql-injection/index.d.ts +0 -12
- package/src/rules/no-graphql-injection/index.js +0 -411
- package/src/rules/no-hardcoded-credentials/index.d.ts +0 -26
- package/src/rules/no-hardcoded-credentials/index.js +0 -376
- package/src/rules/no-hardcoded-session-tokens/index.d.ts +0 -6
- package/src/rules/no-hardcoded-session-tokens/index.js +0 -59
- package/src/rules/no-http-urls/index.d.ts +0 -12
- package/src/rules/no-http-urls/index.js +0 -114
- package/src/rules/no-improper-sanitization/index.d.ts +0 -12
- package/src/rules/no-improper-sanitization/index.js +0 -411
- package/src/rules/no-improper-type-validation/index.d.ts +0 -10
- package/src/rules/no-improper-type-validation/index.js +0 -475
- package/src/rules/no-insecure-comparison/index.d.ts +0 -7
- package/src/rules/no-insecure-comparison/index.js +0 -193
- package/src/rules/no-insecure-cookie-settings/index.d.ts +0 -9
- package/src/rules/no-insecure-cookie-settings/index.js +0 -306
- package/src/rules/no-insecure-jwt/index.d.ts +0 -10
- package/src/rules/no-insecure-jwt/index.js +0 -380
- package/src/rules/no-insecure-redirects/index.d.ts +0 -7
- package/src/rules/no-insecure-redirects/index.js +0 -216
- package/src/rules/no-insecure-websocket/index.d.ts +0 -6
- package/src/rules/no-insecure-websocket/index.js +0 -61
- package/src/rules/no-insufficient-postmessage-validation/index.d.ts +0 -14
- package/src/rules/no-insufficient-postmessage-validation/index.js +0 -392
- package/src/rules/no-insufficient-random/index.d.ts +0 -9
- package/src/rules/no-insufficient-random/index.js +0 -208
- package/src/rules/no-ldap-injection/index.d.ts +0 -10
- package/src/rules/no-ldap-injection/index.js +0 -455
- package/src/rules/no-missing-authentication/index.d.ts +0 -13
- package/src/rules/no-missing-authentication/index.js +0 -333
- package/src/rules/no-missing-cors-check/index.d.ts +0 -9
- package/src/rules/no-missing-cors-check/index.js +0 -399
- package/src/rules/no-missing-csrf-protection/index.d.ts +0 -11
- package/src/rules/no-missing-csrf-protection/index.js +0 -180
- package/src/rules/no-missing-security-headers/index.d.ts +0 -7
- package/src/rules/no-missing-security-headers/index.js +0 -218
- package/src/rules/no-password-in-url/index.d.ts +0 -8
- package/src/rules/no-password-in-url/index.js +0 -54
- package/src/rules/no-permissive-cors/index.d.ts +0 -8
- package/src/rules/no-permissive-cors/index.js +0 -65
- package/src/rules/no-pii-in-logs/index.d.ts +0 -8
- package/src/rules/no-pii-in-logs/index.js +0 -70
- package/src/rules/no-postmessage-origin-wildcard/index.d.ts +0 -8
- package/src/rules/no-postmessage-origin-wildcard/index.js +0 -56
- package/src/rules/no-privilege-escalation/index.d.ts +0 -13
- package/src/rules/no-privilege-escalation/index.js +0 -321
- package/src/rules/no-redos-vulnerable-regex/index.d.ts +0 -7
- package/src/rules/no-redos-vulnerable-regex/index.js +0 -306
- package/src/rules/no-sensitive-data-exposure/index.d.ts +0 -11
- package/src/rules/no-sensitive-data-exposure/index.js +0 -250
- package/src/rules/no-sensitive-data-in-analytics/index.d.ts +0 -8
- package/src/rules/no-sensitive-data-in-analytics/index.js +0 -62
- package/src/rules/no-sensitive-data-in-cache/index.d.ts +0 -8
- package/src/rules/no-sensitive-data-in-cache/index.js +0 -52
- package/src/rules/no-sql-injection/index.d.ts +0 -10
- package/src/rules/no-sql-injection/index.js +0 -335
- package/src/rules/no-timing-attack/index.d.ts +0 -10
- package/src/rules/no-timing-attack/index.js +0 -447
- package/src/rules/no-toctou-vulnerability/index.d.ts +0 -7
- package/src/rules/no-toctou-vulnerability/index.js +0 -208
- package/src/rules/no-tracking-without-consent/index.d.ts +0 -6
- package/src/rules/no-tracking-without-consent/index.js +0 -67
- package/src/rules/no-unchecked-loop-condition/index.d.ts +0 -12
- package/src/rules/no-unchecked-loop-condition/index.js +0 -646
- package/src/rules/no-unencrypted-local-storage/index.d.ts +0 -8
- package/src/rules/no-unencrypted-local-storage/index.js +0 -61
- package/src/rules/no-unencrypted-transmission/index.d.ts +0 -11
- package/src/rules/no-unencrypted-transmission/index.js +0 -236
- package/src/rules/no-unescaped-url-parameter/index.d.ts +0 -9
- package/src/rules/no-unescaped-url-parameter/index.js +0 -355
- package/src/rules/no-unlimited-resource-allocation/index.d.ts +0 -12
- package/src/rules/no-unlimited-resource-allocation/index.js +0 -643
- package/src/rules/no-unsafe-deserialization/index.d.ts +0 -10
- package/src/rules/no-unsafe-deserialization/index.js +0 -491
- package/src/rules/no-unsafe-dynamic-require/index.d.ts +0 -5
- package/src/rules/no-unsafe-dynamic-require/index.js +0 -106
- package/src/rules/no-unsafe-regex-construction/index.d.ts +0 -9
- package/src/rules/no-unsafe-regex-construction/index.js +0 -291
- package/src/rules/no-unsanitized-html/index.d.ts +0 -9
- package/src/rules/no-unsanitized-html/index.js +0 -335
- package/src/rules/no-unvalidated-deeplinks/index.d.ts +0 -6
- package/src/rules/no-unvalidated-deeplinks/index.js +0 -62
- package/src/rules/no-unvalidated-user-input/index.d.ts +0 -9
- package/src/rules/no-unvalidated-user-input/index.js +0 -420
- package/src/rules/no-verbose-error-messages/index.d.ts +0 -8
- package/src/rules/no-verbose-error-messages/index.js +0 -68
- package/src/rules/no-weak-crypto/index.d.ts +0 -11
- package/src/rules/no-weak-crypto/index.js +0 -351
- package/src/rules/no-weak-password-recovery/index.d.ts +0 -12
- package/src/rules/no-weak-password-recovery/index.js +0 -424
- package/src/rules/no-xpath-injection/index.d.ts +0 -10
- package/src/rules/no-xpath-injection/index.js +0 -487
- package/src/rules/no-xxe-injection/index.d.ts +0 -7
- package/src/rules/no-xxe-injection/index.js +0 -266
- package/src/rules/no-zip-slip/index.d.ts +0 -9
- package/src/rules/no-zip-slip/index.js +0 -445
- package/src/rules/require-backend-authorization/index.d.ts +0 -6
- package/src/rules/require-backend-authorization/index.js +0 -60
- package/src/rules/require-code-minification/index.d.ts +0 -8
- package/src/rules/require-code-minification/index.js +0 -47
- package/src/rules/require-csp-headers/index.d.ts +0 -6
- package/src/rules/require-csp-headers/index.js +0 -64
- package/src/rules/require-data-minimization/index.d.ts +0 -8
- package/src/rules/require-data-minimization/index.js +0 -53
- package/src/rules/require-dependency-integrity/index.d.ts +0 -6
- package/src/rules/require-dependency-integrity/index.js +0 -64
- package/src/rules/require-https-only/index.d.ts +0 -8
- package/src/rules/require-https-only/index.js +0 -62
- package/src/rules/require-mime-type-validation/index.d.ts +0 -6
- package/src/rules/require-mime-type-validation/index.js +0 -66
- package/src/rules/require-network-timeout/index.d.ts +0 -8
- package/src/rules/require-network-timeout/index.js +0 -50
- package/src/rules/require-package-lock/index.d.ts +0 -8
- package/src/rules/require-package-lock/index.js +0 -63
- package/src/rules/require-secure-credential-storage/index.d.ts +0 -8
- package/src/rules/require-secure-credential-storage/index.js +0 -50
- package/src/rules/require-secure-defaults/index.d.ts +0 -8
- package/src/rules/require-secure-defaults/index.js +0 -47
- package/src/rules/require-secure-deletion/index.d.ts +0 -8
- package/src/rules/require-secure-deletion/index.js +0 -44
- package/src/rules/require-storage-encryption/index.d.ts +0 -8
- package/src/rules/require-storage-encryption/index.js +0 -50
- package/src/rules/require-url-validation/index.d.ts +0 -6
- package/src/rules/require-url-validation/index.js +0 -72
- package/src/types/index.js +0 -17
|
@@ -1,399 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.noMissingCorsCheck = void 0;
|
|
4
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
5
|
-
const eslint_devkit_2 = require("@interlace/eslint-devkit");
|
|
6
|
-
/**
|
|
7
|
-
* Check if a string matches any ignore pattern
|
|
8
|
-
*/
|
|
9
|
-
function matchesIgnorePattern(text, ignorePatterns) {
|
|
10
|
-
return ignorePatterns.some(pattern => {
|
|
11
|
-
try {
|
|
12
|
-
const regex = new RegExp(pattern, 'i');
|
|
13
|
-
return regex.test(text);
|
|
14
|
-
}
|
|
15
|
-
catch {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
exports.noMissingCorsCheck = (0, eslint_devkit_2.createRule)({
|
|
21
|
-
name: 'no-missing-cors-check',
|
|
22
|
-
meta: {
|
|
23
|
-
type: 'problem',
|
|
24
|
-
deprecated: true,
|
|
25
|
-
replacedBy: ['@see eslint-plugin-express-security/no-permissive-cors'],
|
|
26
|
-
docs: {
|
|
27
|
-
description: 'Detects missing CORS validation (wildcard CORS, missing origin check)',
|
|
28
|
-
},
|
|
29
|
-
hasSuggestions: true,
|
|
30
|
-
messages: {
|
|
31
|
-
missingCorsCheck: (0, eslint_devkit_1.formatLLMMessage)({
|
|
32
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
33
|
-
issueName: 'Missing CORS Validation',
|
|
34
|
-
cwe: 'CWE-346',
|
|
35
|
-
description: 'Missing CORS validation detected: {{issue}}',
|
|
36
|
-
severity: 'HIGH',
|
|
37
|
-
fix: '{{safeAlternative}}',
|
|
38
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/346.html',
|
|
39
|
-
}),
|
|
40
|
-
useOriginValidation: (0, eslint_devkit_1.formatLLMMessage)({
|
|
41
|
-
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
42
|
-
issueName: 'Validate Origin',
|
|
43
|
-
description: 'Validate CORS origin',
|
|
44
|
-
severity: 'LOW',
|
|
45
|
-
fix: 'cors({ origin: (origin, cb) => allowedOrigins.includes(origin) ? cb(null, true) : cb(new Error()) })',
|
|
46
|
-
documentationLink: 'https://github.com/expressjs/cors#configuration-options',
|
|
47
|
-
}),
|
|
48
|
-
useCorsMiddleware: (0, eslint_devkit_1.formatLLMMessage)({
|
|
49
|
-
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
50
|
-
issueName: 'Use CORS Middleware',
|
|
51
|
-
description: 'Use CORS middleware with origin validation',
|
|
52
|
-
severity: 'LOW',
|
|
53
|
-
fix: 'app.use(cors({ origin: allowedOrigins }))',
|
|
54
|
-
documentationLink: 'https://github.com/expressjs/cors',
|
|
55
|
-
}),
|
|
56
|
-
},
|
|
57
|
-
schema: [
|
|
58
|
-
{
|
|
59
|
-
type: 'object',
|
|
60
|
-
properties: {
|
|
61
|
-
allowInTests: {
|
|
62
|
-
type: 'boolean',
|
|
63
|
-
default: false,
|
|
64
|
-
description: 'Allow missing CORS checks in test files',
|
|
65
|
-
},
|
|
66
|
-
trustedLibraries: {
|
|
67
|
-
type: 'array',
|
|
68
|
-
items: { type: 'string' },
|
|
69
|
-
default: [],
|
|
70
|
-
description: 'Custom CORS libraries to trust (wildcard origins in these libraries will not be reported)',
|
|
71
|
-
},
|
|
72
|
-
ignorePatterns: {
|
|
73
|
-
type: 'array',
|
|
74
|
-
items: { type: 'string' },
|
|
75
|
-
default: [],
|
|
76
|
-
description: 'Additional safe patterns to ignore',
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
additionalProperties: false,
|
|
80
|
-
},
|
|
81
|
-
],
|
|
82
|
-
},
|
|
83
|
-
defaultOptions: [
|
|
84
|
-
{
|
|
85
|
-
allowInTests: false,
|
|
86
|
-
trustedLibraries: [], // Empty by default - users can add custom CORS libraries they trust
|
|
87
|
-
ignorePatterns: [],
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
create(context, [options = {}]) {
|
|
91
|
-
const { allowInTests = false, trustedLibraries: corsTrustedLibraries = [], ignorePatterns = [], } = options;
|
|
92
|
-
const trustedLibraries = corsTrustedLibraries;
|
|
93
|
-
const filename = context.getFilename();
|
|
94
|
-
const isTestFile = allowInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
|
|
95
|
-
const sourceCode = context.sourceCode || context.sourceCode;
|
|
96
|
-
function checkLiteral(node) {
|
|
97
|
-
if (isTestFile) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
// Check for wildcard CORS origin
|
|
101
|
-
if (node.value === '*' && typeof node.value === 'string') {
|
|
102
|
-
const text = sourceCode.getText(node);
|
|
103
|
-
// Check if it matches any ignore pattern
|
|
104
|
-
if (matchesIgnorePattern(text, ignorePatterns)) {
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
// Check if it's in contexts handled by other checkers
|
|
108
|
-
// 1. setHeader/header calls - checkMemberExpression handles these
|
|
109
|
-
// 2. app.use(cors({ origin: "*" })) - checkCallExpression handles these with suggestions
|
|
110
|
-
let shouldSkip = false;
|
|
111
|
-
let current = node;
|
|
112
|
-
while (current && current.parent) {
|
|
113
|
-
current = current.parent;
|
|
114
|
-
if (current.type === 'CallExpression') {
|
|
115
|
-
const callText = sourceCode.getText(current);
|
|
116
|
-
// Check if it's a setHeader/header call with Access-Control-Allow-Origin
|
|
117
|
-
// Skip these - checkMemberExpression handles them
|
|
118
|
-
if (/\b(setHeader|header)\s*\(/i.test(callText) && /\bAccess-Control-Allow-Origin\b/i.test(callText)) {
|
|
119
|
-
shouldSkip = true;
|
|
120
|
-
break;
|
|
121
|
-
}
|
|
122
|
-
// Check if it's app.use(cors({ origin: "*" })) - checkCallExpression handles these with suggestions
|
|
123
|
-
if (/\buse\s*\(/i.test(callText) && /\bcors\s*\(/i.test(callText)) {
|
|
124
|
-
// Check if the literal is in an object property named "origin"
|
|
125
|
-
if (node.parent && node.parent.type === 'Property') {
|
|
126
|
-
const prop = node.parent;
|
|
127
|
-
if (prop.key.type === 'Identifier' && prop.key.name === 'origin') {
|
|
128
|
-
shouldSkip = true;
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
// Skip if it's in a context handled by another checker
|
|
136
|
-
if (shouldSkip) {
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
// Check if it's in a CORS-related context
|
|
140
|
-
// Only report if it's actually in a CORS configuration (app.use(cors(...)), etc.)
|
|
141
|
-
// Not just any object with origin: "*"
|
|
142
|
-
let isActualCorsContext = false;
|
|
143
|
-
// Check if it's in app.use(cors(...)) or similar
|
|
144
|
-
current = node;
|
|
145
|
-
while (current && current.parent) {
|
|
146
|
-
current = current.parent;
|
|
147
|
-
if (current.type === 'CallExpression') {
|
|
148
|
-
const callText = sourceCode.getText(current);
|
|
149
|
-
// Check if it's a CORS middleware call
|
|
150
|
-
if (/\b(use|cors)\s*\(/i.test(callText) && /\bcors\s*\(/i.test(callText)) {
|
|
151
|
-
isActualCorsContext = true;
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
// Also check if it's in an object property with name "origin" or "allowedOrigins"
|
|
157
|
-
// but only if it's in a CORS-related call expression
|
|
158
|
-
if (node.parent && node.parent.type === 'Property') {
|
|
159
|
-
const prop = node.parent;
|
|
160
|
-
if (prop.key.type === 'Identifier') {
|
|
161
|
-
const keyName = prop.key.name.toLowerCase();
|
|
162
|
-
if (keyName === 'origin' || keyName === 'allowedorigins') {
|
|
163
|
-
// Check if this property is in a CORS call context
|
|
164
|
-
let inCorsCall = false;
|
|
165
|
-
let checkNode = prop;
|
|
166
|
-
while (checkNode && checkNode.parent) {
|
|
167
|
-
checkNode = checkNode.parent;
|
|
168
|
-
if (checkNode.type === 'CallExpression') {
|
|
169
|
-
const callText = sourceCode.getText(checkNode);
|
|
170
|
-
if (/\bcors\s*\(/i.test(callText) ||
|
|
171
|
-
(/\buse\s*\(/i.test(callText) && /\bcors/i.test(callText))) {
|
|
172
|
-
inCorsCall = true;
|
|
173
|
-
break;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
if (inCorsCall) {
|
|
178
|
-
// Always report wildcard CORS origin - it's never safe
|
|
179
|
-
context.report({
|
|
180
|
-
node,
|
|
181
|
-
messageId: 'missingCorsCheck',
|
|
182
|
-
data: {
|
|
183
|
-
issue: 'Wildcard CORS origin (*) allows all origins',
|
|
184
|
-
safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
|
|
185
|
-
},
|
|
186
|
-
suggest: [
|
|
187
|
-
{
|
|
188
|
-
messageId: 'useOriginValidation',
|
|
189
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
190
|
-
fix: (_fixer) => null,
|
|
191
|
-
},
|
|
192
|
-
],
|
|
193
|
-
});
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
// Only report if it's in an actual CORS context
|
|
200
|
-
if (isActualCorsContext) {
|
|
201
|
-
// Always report wildcard CORS origin - it's never safe
|
|
202
|
-
context.report({
|
|
203
|
-
node,
|
|
204
|
-
messageId: 'missingCorsCheck',
|
|
205
|
-
data: {
|
|
206
|
-
issue: 'Wildcard CORS origin (*) allows all origins',
|
|
207
|
-
safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
|
|
208
|
-
},
|
|
209
|
-
suggest: [
|
|
210
|
-
{
|
|
211
|
-
messageId: 'useOriginValidation',
|
|
212
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
213
|
-
fix: (_fixer) => null,
|
|
214
|
-
},
|
|
215
|
-
],
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
function checkCallExpression(node) {
|
|
221
|
-
if (isTestFile) {
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
// Check for app.use(cors({ origin: "*" })) or similar
|
|
225
|
-
if (node.callee.type === 'MemberExpression') {
|
|
226
|
-
const property = node.callee.property;
|
|
227
|
-
if (property.type === 'Identifier' && property.name === 'use') {
|
|
228
|
-
// Check if CORS is being used
|
|
229
|
-
const text = sourceCode.getText(node);
|
|
230
|
-
// Check if it matches any ignore pattern
|
|
231
|
-
if (matchesIgnorePattern(text, ignorePatterns)) {
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
// Check if it's a CORS middleware call
|
|
235
|
-
// Check for cors() or trusted library calls
|
|
236
|
-
const firstArg = node.arguments.length > 0 ? node.arguments[0] : null;
|
|
237
|
-
let isCorsCall = /\bcors\s*\(/i.test(text);
|
|
238
|
-
if (!isCorsCall && firstArg && firstArg.type === 'CallExpression' && firstArg.callee.type === 'Identifier') {
|
|
239
|
-
const callee = firstArg.callee;
|
|
240
|
-
const calleeName = callee.name.toLowerCase();
|
|
241
|
-
// Check if it's the standard 'cors' library or a trusted library
|
|
242
|
-
isCorsCall = calleeName === 'cors' || trustedLibraries.some(lib => {
|
|
243
|
-
return calleeName.includes(lib.toLowerCase());
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
// Check if it's a trusted library - skip if explicitly trusted
|
|
247
|
-
let isTrustedLibrary = false;
|
|
248
|
-
if (firstArg && firstArg.type === 'CallExpression' && firstArg.callee.type === 'Identifier') {
|
|
249
|
-
const calleeName = firstArg.callee.name.toLowerCase();
|
|
250
|
-
isTrustedLibrary = trustedLibraries.some(lib => calleeName.includes(lib.toLowerCase()));
|
|
251
|
-
}
|
|
252
|
-
if (isTrustedLibrary) {
|
|
253
|
-
return; // Trusted library, skip
|
|
254
|
-
}
|
|
255
|
-
// Check if it's a CORS call
|
|
256
|
-
if (/\bcors\s*\(/i.test(text) || isCorsCall) {
|
|
257
|
-
// Check arguments for wildcard origin
|
|
258
|
-
// For app.use(cors({ origin: "*" })), we need to check the arguments to cors(), not app.use()
|
|
259
|
-
const corsCallArg = firstArg && firstArg.type === 'CallExpression' ? firstArg : null;
|
|
260
|
-
const argsToCheck = corsCallArg ? corsCallArg.arguments : node.arguments;
|
|
261
|
-
for (const arg of argsToCheck) {
|
|
262
|
-
if (arg.type === 'ObjectExpression') {
|
|
263
|
-
// Check for origin property with wildcard value
|
|
264
|
-
for (const prop of arg.properties) {
|
|
265
|
-
if (prop.type === 'Property' &&
|
|
266
|
-
prop.key.type === 'Identifier' &&
|
|
267
|
-
prop.key.name === 'origin' &&
|
|
268
|
-
prop.value.type === 'Literal' &&
|
|
269
|
-
prop.value.value === '*') {
|
|
270
|
-
context.report({
|
|
271
|
-
node: prop.value,
|
|
272
|
-
messageId: 'missingCorsCheck',
|
|
273
|
-
data: {
|
|
274
|
-
issue: 'Wildcard CORS origin (*) allows all origins',
|
|
275
|
-
safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
|
|
276
|
-
},
|
|
277
|
-
suggest: [
|
|
278
|
-
{
|
|
279
|
-
messageId: 'useOriginValidation',
|
|
280
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
281
|
-
fix: (_fixer) => null,
|
|
282
|
-
},
|
|
283
|
-
],
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
else if (arg.type === 'Identifier') {
|
|
289
|
-
// Check if this identifier was assigned an object literal with origin: "*"
|
|
290
|
-
// For cases like: const config = { origin: "*" }; app.use(cors(config));
|
|
291
|
-
const varName = arg.name;
|
|
292
|
-
// Traverse the AST to find the variable declaration
|
|
293
|
-
let current = node;
|
|
294
|
-
while (current) {
|
|
295
|
-
if (current.type === 'Program' || current.type === 'FunctionDeclaration' || current.type === 'FunctionExpression' || current.type === 'ArrowFunctionExpression') {
|
|
296
|
-
// Search for variable declarations in this scope
|
|
297
|
-
const scopeBody = current.type === 'Program' ? current.body :
|
|
298
|
-
(current.type === 'FunctionDeclaration' || current.type === 'FunctionExpression' || current.type === 'ArrowFunctionExpression') ?
|
|
299
|
-
(current.body.type === 'BlockStatement' ? current.body.body : []) : [];
|
|
300
|
-
for (const stmt of scopeBody) {
|
|
301
|
-
if (stmt.type === 'VariableDeclaration') {
|
|
302
|
-
for (const declarator of stmt.declarations) {
|
|
303
|
-
if (declarator.id.type === 'Identifier' && declarator.id.name === varName && declarator.init) {
|
|
304
|
-
// Check if init is an object literal with origin: "*"
|
|
305
|
-
if (declarator.init.type === 'ObjectExpression') {
|
|
306
|
-
for (const prop of declarator.init.properties) {
|
|
307
|
-
if (prop.type === 'Property' &&
|
|
308
|
-
prop.key.type === 'Identifier' &&
|
|
309
|
-
prop.key.name === 'origin' &&
|
|
310
|
-
prop.value.type === 'Literal' &&
|
|
311
|
-
prop.value.value === '*') {
|
|
312
|
-
context.report({
|
|
313
|
-
node: arg,
|
|
314
|
-
messageId: 'missingCorsCheck',
|
|
315
|
-
data: {
|
|
316
|
-
issue: 'Wildcard CORS origin (*) allows all origins',
|
|
317
|
-
safeAlternative: 'Use origin validation: app.use(cors({ origin: (origin, callback) => { if (allowedOrigins.includes(origin)) callback(null, true); else callback(new Error("Not allowed")); } } }));',
|
|
318
|
-
},
|
|
319
|
-
suggest: [
|
|
320
|
-
{
|
|
321
|
-
messageId: 'useOriginValidation',
|
|
322
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
323
|
-
fix: (_fixer) => null,
|
|
324
|
-
},
|
|
325
|
-
],
|
|
326
|
-
});
|
|
327
|
-
return; // Found and reported, exit
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
break; // Only check the immediate scope
|
|
336
|
-
}
|
|
337
|
-
if (current.parent) {
|
|
338
|
-
current = current.parent;
|
|
339
|
-
}
|
|
340
|
-
else {
|
|
341
|
-
break;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
function checkMemberExpression(node) {
|
|
351
|
-
if (isTestFile) {
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
// Check for Access-Control-Allow-Origin header without validation
|
|
355
|
-
if (node.property.type === 'Identifier') {
|
|
356
|
-
const propertyName = node.property.name;
|
|
357
|
-
if (propertyName === 'setHeader' || propertyName === 'header') {
|
|
358
|
-
// Check if it matches any ignore pattern
|
|
359
|
-
const text = sourceCode.getText(node);
|
|
360
|
-
if (matchesIgnorePattern(text, ignorePatterns)) {
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
// Check if it's setting CORS headers
|
|
364
|
-
// Need to check the full call expression, not just the member expression
|
|
365
|
-
const parent = node.parent;
|
|
366
|
-
if (parent && parent.type === 'CallExpression') {
|
|
367
|
-
const callText = sourceCode.getText(parent);
|
|
368
|
-
if (/\bAccess-Control-Allow-Origin\b/i.test(callText)) {
|
|
369
|
-
// Check if the value is a wildcard
|
|
370
|
-
const args = parent.arguments;
|
|
371
|
-
if (args.length >= 2 && args[1].type === 'Literal' && args[1].value === '*') {
|
|
372
|
-
context.report({
|
|
373
|
-
node: args[1],
|
|
374
|
-
messageId: 'missingCorsCheck',
|
|
375
|
-
data: {
|
|
376
|
-
issue: 'Wildcard CORS header allows all origins',
|
|
377
|
-
safeAlternative: 'Validate origin before setting header: res.setHeader("Access-Control-Allow-Origin", allowedOrigins.includes(origin) ? origin : "null");',
|
|
378
|
-
},
|
|
379
|
-
suggest: [
|
|
380
|
-
{
|
|
381
|
-
messageId: 'useOriginValidation',
|
|
382
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
383
|
-
fix: (_fixer) => null,
|
|
384
|
-
},
|
|
385
|
-
],
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
return {
|
|
394
|
-
Literal: checkLiteral,
|
|
395
|
-
CallExpression: checkCallExpression,
|
|
396
|
-
MemberExpression: checkMemberExpression,
|
|
397
|
-
};
|
|
398
|
-
},
|
|
399
|
-
});
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export interface Options {
|
|
2
|
-
/** Allow missing CSRF protection in test files. Default: false */
|
|
3
|
-
allowInTests?: boolean;
|
|
4
|
-
/** CSRF middleware patterns to recognize. Default: ['csrf', 'csurf', 'csrfProtection', 'verifyCsrfToken'] */
|
|
5
|
-
csrfMiddlewarePatterns?: string[];
|
|
6
|
-
/** HTTP methods that require CSRF protection. Default: ['post', 'put', 'delete', 'patch'] */
|
|
7
|
-
protectedMethods?: string[];
|
|
8
|
-
/** Additional safe patterns to ignore. Default: [] */
|
|
9
|
-
ignorePatterns?: string[];
|
|
10
|
-
}
|
|
11
|
-
export declare const noMissingCsrfProtection: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.noMissingCsrfProtection = void 0;
|
|
4
|
-
const eslint_devkit_1 = require("@interlace/eslint-devkit");
|
|
5
|
-
const eslint_devkit_2 = require("@interlace/eslint-devkit");
|
|
6
|
-
/**
|
|
7
|
-
* Default CSRF middleware patterns
|
|
8
|
-
*/
|
|
9
|
-
const DEFAULT_CSRF_MIDDLEWARE_PATTERNS = [
|
|
10
|
-
'csrf',
|
|
11
|
-
'csurf',
|
|
12
|
-
'csrfProtection',
|
|
13
|
-
'verifyCsrfToken',
|
|
14
|
-
'csrfToken',
|
|
15
|
-
'validateCsrf',
|
|
16
|
-
'checkCsrf',
|
|
17
|
-
'csrfMiddleware',
|
|
18
|
-
];
|
|
19
|
-
/**
|
|
20
|
-
* Default HTTP methods that require CSRF protection
|
|
21
|
-
*/
|
|
22
|
-
const DEFAULT_PROTECTED_METHODS = ['post', 'put', 'delete', 'patch'];
|
|
23
|
-
/**
|
|
24
|
-
* Check if a string matches any ignore pattern
|
|
25
|
-
*/
|
|
26
|
-
function matchesIgnorePattern(text, patterns) {
|
|
27
|
-
return patterns.some(pattern => {
|
|
28
|
-
try {
|
|
29
|
-
const regex = new RegExp(pattern, 'i');
|
|
30
|
-
return regex.test(text);
|
|
31
|
-
}
|
|
32
|
-
catch {
|
|
33
|
-
return text.toLowerCase().includes(pattern.toLowerCase());
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
exports.noMissingCsrfProtection = (0, eslint_devkit_2.createRule)({
|
|
38
|
-
name: 'no-missing-csrf-protection',
|
|
39
|
-
meta: {
|
|
40
|
-
type: 'problem',
|
|
41
|
-
deprecated: true,
|
|
42
|
-
replacedBy: ['@see eslint-plugin-express-security/require-csrf-protection'],
|
|
43
|
-
docs: {
|
|
44
|
-
description: 'Detects missing CSRF token validation in POST/PUT/DELETE requests',
|
|
45
|
-
},
|
|
46
|
-
hasSuggestions: true,
|
|
47
|
-
messages: {
|
|
48
|
-
missingCsrfProtection: (0, eslint_devkit_1.formatLLMMessage)({
|
|
49
|
-
icon: eslint_devkit_1.MessageIcons.SECURITY,
|
|
50
|
-
issueName: 'Missing CSRF Protection',
|
|
51
|
-
cwe: 'CWE-352',
|
|
52
|
-
description: 'Missing CSRF protection detected: {{issue}}',
|
|
53
|
-
severity: 'HIGH',
|
|
54
|
-
fix: '{{safeAlternative}}',
|
|
55
|
-
documentationLink: 'https://cwe.mitre.org/data/definitions/352.html',
|
|
56
|
-
}),
|
|
57
|
-
addCsrfValidation: (0, eslint_devkit_1.formatLLMMessage)({
|
|
58
|
-
icon: eslint_devkit_1.MessageIcons.INFO,
|
|
59
|
-
issueName: 'Add CSRF Validation',
|
|
60
|
-
description: 'Add CSRF middleware',
|
|
61
|
-
severity: 'LOW',
|
|
62
|
-
fix: 'app.use(csrf({ cookie: true }))',
|
|
63
|
-
documentationLink: 'https://github.com/expressjs/csurf',
|
|
64
|
-
}),
|
|
65
|
-
},
|
|
66
|
-
schema: [
|
|
67
|
-
{
|
|
68
|
-
type: 'object',
|
|
69
|
-
properties: {
|
|
70
|
-
allowInTests: {
|
|
71
|
-
type: 'boolean',
|
|
72
|
-
default: false,
|
|
73
|
-
description: 'Allow missing CSRF protection in test files',
|
|
74
|
-
},
|
|
75
|
-
csrfMiddlewarePatterns: {
|
|
76
|
-
type: 'array',
|
|
77
|
-
items: { type: 'string' },
|
|
78
|
-
default: [],
|
|
79
|
-
description: 'CSRF middleware patterns to recognize',
|
|
80
|
-
},
|
|
81
|
-
protectedMethods: {
|
|
82
|
-
type: 'array',
|
|
83
|
-
items: { type: 'string' },
|
|
84
|
-
default: [],
|
|
85
|
-
description: 'HTTP methods that require CSRF protection',
|
|
86
|
-
},
|
|
87
|
-
ignorePatterns: {
|
|
88
|
-
type: 'array',
|
|
89
|
-
items: { type: 'string' },
|
|
90
|
-
default: [],
|
|
91
|
-
description: 'Additional safe patterns to ignore',
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
additionalProperties: false,
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
},
|
|
98
|
-
defaultOptions: [
|
|
99
|
-
{
|
|
100
|
-
allowInTests: false,
|
|
101
|
-
csrfMiddlewarePatterns: [],
|
|
102
|
-
protectedMethods: [],
|
|
103
|
-
ignorePatterns: [],
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
create(context, [options = {}]) {
|
|
107
|
-
const { allowInTests = false, csrfMiddlewarePatterns, protectedMethods: customProtectedMethods, ignorePatterns = [], } = options;
|
|
108
|
-
const csrfPatterns = csrfMiddlewarePatterns && csrfMiddlewarePatterns.length > 0
|
|
109
|
-
? csrfMiddlewarePatterns
|
|
110
|
-
: DEFAULT_CSRF_MIDDLEWARE_PATTERNS;
|
|
111
|
-
const protectedMethods = customProtectedMethods && customProtectedMethods.length > 0
|
|
112
|
-
? customProtectedMethods
|
|
113
|
-
: DEFAULT_PROTECTED_METHODS;
|
|
114
|
-
// Pre-compute Set for O(1) lookups (performance optimization)
|
|
115
|
-
const protectedMethodsSet = new Set(protectedMethods.map(m => m.toLowerCase()));
|
|
116
|
-
const filename = context.filename;
|
|
117
|
-
const isTestFile = allowInTests && /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(filename);
|
|
118
|
-
const sourceCode = context.sourceCode;
|
|
119
|
-
function checkCallExpression(node) {
|
|
120
|
-
if (isTestFile) {
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
const callee = node.callee;
|
|
124
|
-
const callText = sourceCode.getText(node);
|
|
125
|
-
// Check if it matches any ignore pattern
|
|
126
|
-
if (matchesIgnorePattern(callText, ignorePatterns)) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
// Check for route handler methods (app.post, router.put, etc.)
|
|
130
|
-
if (callee.type === eslint_devkit_1.AST_NODE_TYPES.MemberExpression && callee.property.type === eslint_devkit_1.AST_NODE_TYPES.Identifier) {
|
|
131
|
-
const methodName = callee.property.name;
|
|
132
|
-
// Only check if it's a route handler that requires CSRF (O(1) Set lookup)
|
|
133
|
-
if (protectedMethodsSet.has(methodName.toLowerCase())) {
|
|
134
|
-
// Must have at least 2 arguments (path and handler)
|
|
135
|
-
if (node.arguments.length < 2) {
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
// Check if CSRF middleware is in the route chain arguments
|
|
139
|
-
let hasCsrfInChain = false;
|
|
140
|
-
// Check if any argument (after the first path argument) is a CSRF middleware
|
|
141
|
-
// Skip the first argument (path) and check the rest
|
|
142
|
-
for (let i = 1; i < node.arguments.length; i++) {
|
|
143
|
-
const arg = node.arguments[i];
|
|
144
|
-
const argText = sourceCode.getText(arg);
|
|
145
|
-
if (csrfPatterns.some(pattern => argText.toLowerCase().includes(pattern.toLowerCase()))) {
|
|
146
|
-
hasCsrfInChain = true;
|
|
147
|
-
break;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
if (!hasCsrfInChain) {
|
|
151
|
-
context.report({
|
|
152
|
-
node,
|
|
153
|
-
messageId: 'missingCsrfProtection',
|
|
154
|
-
data: {
|
|
155
|
-
issue: `${methodName.toUpperCase()} route handler missing CSRF protection`,
|
|
156
|
-
safeAlternative: `Add CSRF middleware: app.${methodName}("/path", csrf(), handler) or use app.use(csrf()) globally`,
|
|
157
|
-
},
|
|
158
|
-
suggest: [
|
|
159
|
-
{
|
|
160
|
-
messageId: 'addCsrfValidation',
|
|
161
|
-
fix(fixer) {
|
|
162
|
-
// Add CSRF middleware after the first argument (path)
|
|
163
|
-
const firstArg = node.arguments[0];
|
|
164
|
-
if (firstArg) {
|
|
165
|
-
return fixer.insertTextAfter(firstArg, ', csrf()');
|
|
166
|
-
}
|
|
167
|
-
return null;
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
],
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
return {
|
|
177
|
-
CallExpression: checkCallExpression,
|
|
178
|
-
};
|
|
179
|
-
},
|
|
180
|
-
});
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export interface Options {
|
|
2
|
-
/** Required security headers. Default: ['Content-Security-Policy', 'X-Frame-Options', 'X-Content-Type-Options'] */
|
|
3
|
-
requiredHeaders?: string[];
|
|
4
|
-
/** Ignore in test files. Default: true */
|
|
5
|
-
ignoreInTests?: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare const noMissingSecurityHeaders: ESLintUtils.RuleModule<MessageIds, Options, unknown, ESLintUtils.RuleListener>;
|