eslint-plugin-crypto 1.0.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/AGENTS.md +110 -0
- package/CHANGELOG.md +68 -0
- package/LICENSE +21 -0
- package/README.md +144 -0
- package/package.json +80 -0
- package/src/index.d.ts +35 -0
- package/src/index.js +213 -0
- package/src/index.js.map +1 -0
- package/src/rules/no-cryptojs/index.d.ts +6 -0
- package/src/rules/no-cryptojs/index.js +99 -0
- package/src/rules/no-cryptojs/index.js.map +1 -0
- package/src/rules/no-cryptojs-weak-random/index.d.ts +6 -0
- package/src/rules/no-cryptojs-weak-random/index.js +107 -0
- package/src/rules/no-cryptojs-weak-random/index.js.map +1 -0
- package/src/rules/no-deprecated-cipher-method/index.d.ts +6 -0
- package/src/rules/no-deprecated-cipher-method/index.js +110 -0
- package/src/rules/no-deprecated-cipher-method/index.js.map +1 -0
- package/src/rules/no-ecb-mode/index.d.ts +6 -0
- package/src/rules/no-ecb-mode/index.js +108 -0
- package/src/rules/no-ecb-mode/index.js.map +1 -0
- package/src/rules/no-hardcoded-crypto-key/index.d.ts +6 -0
- package/src/rules/no-hardcoded-crypto-key/index.js +138 -0
- package/src/rules/no-hardcoded-crypto-key/index.js.map +1 -0
- package/src/rules/no-insecure-key-derivation/index.d.ts +6 -0
- package/src/rules/no-insecure-key-derivation/index.js +111 -0
- package/src/rules/no-insecure-key-derivation/index.js.map +1 -0
- package/src/rules/no-insecure-rsa-padding/index.d.ts +6 -0
- package/src/rules/no-insecure-rsa-padding/index.js +105 -0
- package/src/rules/no-insecure-rsa-padding/index.js.map +1 -0
- package/src/rules/no-key-reuse/index.d.ts +6 -0
- package/src/rules/no-key-reuse/index.js +106 -0
- package/src/rules/no-key-reuse/index.js.map +1 -0
- package/src/rules/no-math-random-crypto/index.d.ts +6 -0
- package/src/rules/no-math-random-crypto/index.js +178 -0
- package/src/rules/no-math-random-crypto/index.js.map +1 -0
- package/src/rules/no-numeric-only-tokens/index.d.ts +6 -0
- package/src/rules/no-numeric-only-tokens/index.js +126 -0
- package/src/rules/no-numeric-only-tokens/index.js.map +1 -0
- package/src/rules/no-predictable-salt/index.d.ts +6 -0
- package/src/rules/no-predictable-salt/index.js +134 -0
- package/src/rules/no-predictable-salt/index.js.map +1 -0
- package/src/rules/no-self-signed-certs/index.d.ts +6 -0
- package/src/rules/no-self-signed-certs/index.js +111 -0
- package/src/rules/no-self-signed-certs/index.js.map +1 -0
- package/src/rules/no-sha1-hash/index.d.ts +6 -0
- package/src/rules/no-sha1-hash/index.js +123 -0
- package/src/rules/no-sha1-hash/index.js.map +1 -0
- package/src/rules/no-static-iv/index.d.ts +6 -0
- package/src/rules/no-static-iv/index.js +142 -0
- package/src/rules/no-static-iv/index.js.map +1 -0
- package/src/rules/no-timing-unsafe-compare/index.d.ts +6 -0
- package/src/rules/no-timing-unsafe-compare/index.js +109 -0
- package/src/rules/no-timing-unsafe-compare/index.js.map +1 -0
- package/src/rules/no-weak-cipher-algorithm/index.d.ts +8 -0
- package/src/rules/no-weak-cipher-algorithm/index.js +185 -0
- package/src/rules/no-weak-cipher-algorithm/index.js.map +1 -0
- package/src/rules/no-weak-hash-algorithm/index.d.ts +8 -0
- package/src/rules/no-weak-hash-algorithm/index.js +213 -0
- package/src/rules/no-weak-hash-algorithm/index.js.map +1 -0
- package/src/rules/no-web-crypto-export/index.d.ts +6 -0
- package/src/rules/no-web-crypto-export/index.js +110 -0
- package/src/rules/no-web-crypto-export/index.js.map +1 -0
- package/src/rules/prefer-native-crypto/index.d.ts +6 -0
- package/src/rules/prefer-native-crypto/index.js +119 -0
- package/src/rules/prefer-native-crypto/index.js.map +1 -0
- package/src/rules/require-authenticated-encryption/index.d.ts +6 -0
- package/src/rules/require-authenticated-encryption/index.js +122 -0
- package/src/rules/require-authenticated-encryption/index.js.map +1 -0
- package/src/rules/require-key-length/index.d.ts +6 -0
- package/src/rules/require-key-length/index.js +108 -0
- package/src/rules/require-key-length/index.js.map +1 -0
- package/src/rules/require-random-iv/index.d.ts +6 -0
- package/src/rules/require-random-iv/index.js +161 -0
- package/src/rules/require-random-iv/index.js.map +1 -0
- package/src/rules/require-secure-pbkdf2-digest/index.d.ts +6 -0
- package/src/rules/require-secure-pbkdf2-digest/index.js +163 -0
- package/src/rules/require-secure-pbkdf2-digest/index.js.map +1 -0
- package/src/rules/require-sufficient-length/index.d.ts +6 -0
- package/src/rules/require-sufficient-length/index.js +122 -0
- package/src/rules/require-sufficient-length/index.js.map +1 -0
- package/src/types/index.d.ts +132 -0
- package/src/types/index.js +6 -0
- package/src/types/index.js.map +1 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# AGENTS.md - AI Agent Context for eslint-plugin-crypto
|
|
2
|
+
|
|
3
|
+
## Plugin Purpose
|
|
4
|
+
|
|
5
|
+
Security-focused ESLint plugin with **24 rules** for cryptographic best practices. Covers Node.js `crypto`, Web Crypto API, and npm packages (crypto-hash, crypto-random-string, crypto-js).
|
|
6
|
+
|
|
7
|
+
## Quick Reference
|
|
8
|
+
|
|
9
|
+
### Core Crypto Rules (8)
|
|
10
|
+
|
|
11
|
+
| Rule | CWE | Detects | Fix |
|
|
12
|
+
| ----------------------------- | --- | -------------- | ---------------- |
|
|
13
|
+
| `no-weak-hash-algorithm` | 327 | MD5, SHA1, MD4 | SHA-256/512 |
|
|
14
|
+
| `no-weak-cipher-algorithm` | 327 | DES, 3DES, RC4 | AES-256-GCM |
|
|
15
|
+
| `no-deprecated-cipher-method` | 327 | createCipher() | createCipheriv() |
|
|
16
|
+
| `no-static-iv` | 329 | Hardcoded IVs | randomBytes(16) |
|
|
17
|
+
| `no-ecb-mode` | 327 | ECB mode | GCM or CBC |
|
|
18
|
+
| `no-insecure-key-derivation` | 916 | PBKDF2 < 100k | ≥100k iterations |
|
|
19
|
+
| `no-hardcoded-crypto-key` | 321 | Literal keys | env vars/KMS |
|
|
20
|
+
| `require-random-iv` | 329 | Non-random IVs | randomBytes() |
|
|
21
|
+
|
|
22
|
+
### CVE-Specific Rules (3)
|
|
23
|
+
|
|
24
|
+
| Rule | CVE | Vulnerability |
|
|
25
|
+
| ------------------------------ | ---------- | ------------- |
|
|
26
|
+
| `no-insecure-rsa-padding` | 2023-46809 | Marvin Attack |
|
|
27
|
+
| `no-cryptojs-weak-random` | 2020-36732 | Weak PRNG |
|
|
28
|
+
| `require-secure-pbkdf2-digest` | 2023-46233 | SHA1 PBKDF2 |
|
|
29
|
+
|
|
30
|
+
### Advanced Security (7)
|
|
31
|
+
|
|
32
|
+
| Rule | CWE | Focus |
|
|
33
|
+
| ---------------------------------- | --- | --------------- |
|
|
34
|
+
| `no-math-random-crypto` | 338 | Insecure PRNG |
|
|
35
|
+
| `no-predictable-salt` | 331 | Weak salts |
|
|
36
|
+
| `require-authenticated-encryption` | 327 | CBC without MAC |
|
|
37
|
+
| `no-key-reuse` | 323 | Same key twice |
|
|
38
|
+
| `no-self-signed-certs` | 295 | TLS bypass |
|
|
39
|
+
| `no-timing-unsafe-compare` | 208 | Timing attacks |
|
|
40
|
+
| `require-key-length` | 326 | AES-128/192 |
|
|
41
|
+
| `no-web-crypto-export` | 321 | Key export |
|
|
42
|
+
|
|
43
|
+
### Package Rules (6)
|
|
44
|
+
|
|
45
|
+
| Rule | Package | Issue |
|
|
46
|
+
| --------------------------- | -------------------- | -------------- |
|
|
47
|
+
| `no-sha1-hash` | crypto-hash | sha1() |
|
|
48
|
+
| `require-sufficient-length` | crypto-random-string | < 32 chars |
|
|
49
|
+
| `no-numeric-only-tokens` | crypto-random-string | Low entropy |
|
|
50
|
+
| `no-cryptojs` | crypto-js | Deprecated |
|
|
51
|
+
| `no-cryptojs-weak-random` | crypto-js | CVE-2020-36732 |
|
|
52
|
+
| `prefer-native-crypto` | Various | Third-party |
|
|
53
|
+
|
|
54
|
+
## Fix Patterns
|
|
55
|
+
|
|
56
|
+
```diff
|
|
57
|
+
# Weak Hash
|
|
58
|
+
- crypto.createHash('md5')
|
|
59
|
+
+ crypto.createHash('sha256')
|
|
60
|
+
|
|
61
|
+
# RSA Padding (CVE-2023-46809)
|
|
62
|
+
- padding: crypto.constants.RSA_PKCS1_PADDING
|
|
63
|
+
+ padding: crypto.constants.RSA_PKCS1_OAEP_PADDING
|
|
64
|
+
|
|
65
|
+
# Math.random for crypto
|
|
66
|
+
- const token = Math.random().toString(36)
|
|
67
|
+
+ const token = crypto.randomBytes(32).toString('hex')
|
|
68
|
+
|
|
69
|
+
# Timing-safe compare
|
|
70
|
+
- if (userToken === storedToken)
|
|
71
|
+
+ if (crypto.timingSafeEqual(Buffer.from(userToken), Buffer.from(storedToken)))
|
|
72
|
+
|
|
73
|
+
# Authenticated encryption
|
|
74
|
+
- crypto.createCipheriv('aes-256-cbc', key, iv)
|
|
75
|
+
+ crypto.createCipheriv('aes-256-gcm', key, iv)
|
|
76
|
+
|
|
77
|
+
# TLS validation
|
|
78
|
+
- { rejectUnauthorized: false }
|
|
79
|
+
+ { rejectUnauthorized: true }
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Presets (5)
|
|
83
|
+
|
|
84
|
+
| Preset | Use Case |
|
|
85
|
+
| -------------------- | ----------------------- |
|
|
86
|
+
| `recommended` | Most projects |
|
|
87
|
+
| `strict` | High-security apps |
|
|
88
|
+
| `cryptojs-migration` | Migrating off crypto-js |
|
|
89
|
+
| `nodejs-only` | Server-side only |
|
|
90
|
+
| `cve-focused` | Known CVE protection |
|
|
91
|
+
|
|
92
|
+
## Architecture
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
src/
|
|
96
|
+
├── index.ts # Plugin entry, 5 configs
|
|
97
|
+
├── types/index.ts # 24 rule option types
|
|
98
|
+
└── rules/ # 24 rule directories
|
|
99
|
+
├── no-weak-hash-algorithm/
|
|
100
|
+
├── no-insecure-rsa-padding/
|
|
101
|
+
└── ...
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## CWE Coverage
|
|
105
|
+
|
|
106
|
+
208, 295, 321, 323, 326, 327, 328, 329, 330, 331, 338, 916, 1104
|
|
107
|
+
|
|
108
|
+
## Version
|
|
109
|
+
|
|
110
|
+
1.0.0 (24 rules)
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `eslint-plugin-crypto` will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2025-12-29
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
#### Core Node.js Crypto Rules (8)
|
|
13
|
+
|
|
14
|
+
- `no-weak-hash-algorithm` - Detect MD5, SHA1, MD4, RIPEMD (CWE-327)
|
|
15
|
+
- `no-weak-cipher-algorithm` - Detect DES, 3DES, RC4, Blowfish (CWE-327)
|
|
16
|
+
- `no-deprecated-cipher-method` - Detect createCipher/createDecipher (CWE-327)
|
|
17
|
+
- `no-static-iv` - Detect hardcoded initialization vectors (CWE-329)
|
|
18
|
+
- `no-ecb-mode` - Detect ECB encryption mode (CWE-327)
|
|
19
|
+
- `no-insecure-key-derivation` - Detect PBKDF2 < 100k iterations (CWE-916)
|
|
20
|
+
- `no-hardcoded-crypto-key` - Detect literal encryption keys (CWE-321)
|
|
21
|
+
- `require-random-iv` - Ensure IV from crypto.randomBytes() (CWE-329)
|
|
22
|
+
|
|
23
|
+
#### CVE-Specific Rules (3)
|
|
24
|
+
|
|
25
|
+
- `no-insecure-rsa-padding` - **CVE-2023-46809** Marvin Attack detection (CWE-327)
|
|
26
|
+
- `no-cryptojs-weak-random` - **CVE-2020-36732** crypto-js weak PRNG (CWE-338)
|
|
27
|
+
- `require-secure-pbkdf2-digest` - **CVE-2023-46233** PBKDF2 SHA1 default (CWE-328)
|
|
28
|
+
|
|
29
|
+
#### Advanced Security Rules (7)
|
|
30
|
+
|
|
31
|
+
- `no-math-random-crypto` - Detect Math.random() in crypto contexts (CWE-338)
|
|
32
|
+
- `no-predictable-salt` - Detect empty/hardcoded salts (CWE-331)
|
|
33
|
+
- `require-authenticated-encryption` - Flag CBC/CTR without MAC (CWE-327)
|
|
34
|
+
- `no-key-reuse` - Warn on key reuse across operations (CWE-323)
|
|
35
|
+
- `no-self-signed-certs` - Detect rejectUnauthorized: false (CWE-295)
|
|
36
|
+
- `no-timing-unsafe-compare` - Detect timing-unsafe secret comparison (CWE-208)
|
|
37
|
+
- `require-key-length` - Recommend AES-256 over AES-128/192 (CWE-326)
|
|
38
|
+
- `no-web-crypto-export` - Warn on key export (CWE-321)
|
|
39
|
+
|
|
40
|
+
#### Package-Specific Rules (6)
|
|
41
|
+
|
|
42
|
+
- `no-sha1-hash` - Detect sha1() from crypto-hash (CWE-327)
|
|
43
|
+
- `require-sufficient-length` - Require crypto-random-string ≥32 chars (CWE-330)
|
|
44
|
+
- `no-numeric-only-tokens` - Warn on type: 'numeric' (CWE-330)
|
|
45
|
+
- `no-cryptojs` - Warn on deprecated crypto-js usage (CWE-1104)
|
|
46
|
+
- `no-cryptojs-weak-random` - CVE-2020-36732 (CWE-338)
|
|
47
|
+
- `prefer-native-crypto` - Recommend native crypto (CWE-1104)
|
|
48
|
+
|
|
49
|
+
#### Presets (5)
|
|
50
|
+
|
|
51
|
+
- `recommended` - Balanced security defaults
|
|
52
|
+
- `strict` - All 24 rules as errors
|
|
53
|
+
- `cryptojs-migration` - For migrating off crypto-js
|
|
54
|
+
- `nodejs-only` - Server-side only (no package rules)
|
|
55
|
+
- `cve-focused` - Rules targeting specific CVEs
|
|
56
|
+
|
|
57
|
+
#### Features
|
|
58
|
+
|
|
59
|
+
- LLM-optimized error messages with CWE references
|
|
60
|
+
- Auto-fix suggestions where safe
|
|
61
|
+
- OWASP-aligned recommendations
|
|
62
|
+
- TypeScript support
|
|
63
|
+
- Comprehensive test coverage (302 edge case tests)
|
|
64
|
+
|
|
65
|
+
### Security
|
|
66
|
+
|
|
67
|
+
- Covers 13 CWEs: 208, 295, 321, 323, 326, 327, 328, 329, 330, 331, 338, 916, 1104
|
|
68
|
+
- Detects 3 specific CVEs: CVE-2023-46809, CVE-2020-36732, CVE-2023-46233
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ofri Peretz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# eslint-plugin-crypto
|
|
2
|
+
|
|
3
|
+
> Security-focused ESLint plugin with **24 AI-parseable rules** for cryptographic best practices.
|
|
4
|
+
|
|
5
|
+
Detects weak algorithms, insecure key handling, deprecated crypto patterns, CVE vulnerabilities, and guides you to modern, secure alternatives.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🔐 **24 Rules** covering crypto best practices
|
|
10
|
+
- 🎯 **CVE Detection** (CVE-2023-46809, CVE-2020-36732, CVE-2023-46233)
|
|
11
|
+
- 🤖 **AI-Optimized** messages with CWE references
|
|
12
|
+
- ⚡ **Auto-Fix** suggestions where safe
|
|
13
|
+
- 📦 **Package Support** for crypto-hash, crypto-random-string, crypto-js
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install eslint-plugin-crypto --save-dev
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
### ESLint Flat Config (eslint.config.js)
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
import crypto from 'eslint-plugin-crypto';
|
|
27
|
+
|
|
28
|
+
export default [crypto.configs.recommended];
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Presets
|
|
32
|
+
|
|
33
|
+
| Preset | Description |
|
|
34
|
+
| -------------------- | -------------------------------------------- |
|
|
35
|
+
| `recommended` | Balanced security defaults for most projects |
|
|
36
|
+
| `strict` | All 24 rules as errors for maximum security |
|
|
37
|
+
| `cryptojs-migration` | For teams migrating from crypto-js |
|
|
38
|
+
| `nodejs-only` | Only Node.js crypto rules |
|
|
39
|
+
| `cve-focused` | Rules targeting specific CVEs |
|
|
40
|
+
|
|
41
|
+
## Rule Categories
|
|
42
|
+
|
|
43
|
+
### Core Node.js Crypto (8 rules)
|
|
44
|
+
|
|
45
|
+
| Rule | Description | CWE |
|
|
46
|
+
| ----------------------------- | ------------------------------- | ------- |
|
|
47
|
+
| `no-weak-hash-algorithm` | Disallow MD5, SHA1, MD4 | CWE-327 |
|
|
48
|
+
| `no-weak-cipher-algorithm` | Disallow DES, 3DES, RC4 | CWE-327 |
|
|
49
|
+
| `no-deprecated-cipher-method` | Disallow createCipher() | CWE-327 |
|
|
50
|
+
| `no-static-iv` | Disallow hardcoded IVs | CWE-329 |
|
|
51
|
+
| `no-ecb-mode` | Disallow ECB encryption | CWE-327 |
|
|
52
|
+
| `no-insecure-key-derivation` | Require PBKDF2 ≥100k iterations | CWE-916 |
|
|
53
|
+
| `no-hardcoded-crypto-key` | Disallow hardcoded keys | CWE-321 |
|
|
54
|
+
| `require-random-iv` | Require IV from randomBytes() | CWE-329 |
|
|
55
|
+
|
|
56
|
+
### CVE-Specific Rules (3 rules)
|
|
57
|
+
|
|
58
|
+
| Rule | CVE | Description |
|
|
59
|
+
| ------------------------------ | -------------- | ------------------------------- |
|
|
60
|
+
| `no-insecure-rsa-padding` | CVE-2023-46809 | Marvin Attack (RSA PKCS#1 v1.5) |
|
|
61
|
+
| `no-cryptojs-weak-random` | CVE-2020-36732 | Weak PRNG in crypto-js < 3.2.1 |
|
|
62
|
+
| `require-secure-pbkdf2-digest` | CVE-2023-46233 | Weak PBKDF2 defaults (SHA1) |
|
|
63
|
+
|
|
64
|
+
### Advanced Security (7 rules)
|
|
65
|
+
|
|
66
|
+
| Rule | Description | CWE |
|
|
67
|
+
| ---------------------------------- | ---------------------------------- | ------- |
|
|
68
|
+
| `no-math-random-crypto` | Disallow Math.random() for crypto | CWE-338 |
|
|
69
|
+
| `no-predictable-salt` | Disallow empty/hardcoded salts | CWE-331 |
|
|
70
|
+
| `require-authenticated-encryption` | Require GCM instead of CBC | CWE-327 |
|
|
71
|
+
| `no-key-reuse` | Warn on key reuse | CWE-323 |
|
|
72
|
+
| `no-self-signed-certs` | Disallow rejectUnauthorized: false | CWE-295 |
|
|
73
|
+
| `no-timing-unsafe-compare` | Require timingSafeEqual() | CWE-208 |
|
|
74
|
+
| `require-key-length` | Require AES-256 | CWE-326 |
|
|
75
|
+
| `no-web-crypto-export` | Warn on key export | CWE-321 |
|
|
76
|
+
|
|
77
|
+
### Package-Specific Rules (6 rules)
|
|
78
|
+
|
|
79
|
+
| Package | Rule | Description |
|
|
80
|
+
| -------------------- | --------------------------- | ---------------------- |
|
|
81
|
+
| crypto-hash | `no-sha1-hash` | Disallow sha1() |
|
|
82
|
+
| crypto-random-string | `require-sufficient-length` | Require min 32 chars |
|
|
83
|
+
| crypto-random-string | `no-numeric-only-tokens` | Warn on numeric-only |
|
|
84
|
+
| crypto-js | `no-cryptojs` | Warn on deprecated lib |
|
|
85
|
+
| crypto-js | `no-cryptojs-weak-random` | CVE-2020-36732 |
|
|
86
|
+
| Various | `prefer-native-crypto` | Prefer native crypto |
|
|
87
|
+
|
|
88
|
+
## Examples
|
|
89
|
+
|
|
90
|
+
### ❌ Bad
|
|
91
|
+
|
|
92
|
+
```javascript
|
|
93
|
+
// CVE-2023-46809: Marvin Attack
|
|
94
|
+
crypto.privateDecrypt({ key, padding: crypto.constants.RSA_PKCS1_PADDING }, buffer);
|
|
95
|
+
|
|
96
|
+
// CWE-338: Weak random
|
|
97
|
+
const token = Math.random().toString(36);
|
|
98
|
+
|
|
99
|
+
// CWE-327: ECB mode leaks patterns
|
|
100
|
+
crypto.createCipheriv('aes-256-ecb', key, iv);
|
|
101
|
+
|
|
102
|
+
// CWE-208: Timing attack
|
|
103
|
+
if (userToken === storedToken) { ... }
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### ✅ Good
|
|
107
|
+
|
|
108
|
+
```javascript
|
|
109
|
+
// Use OAEP padding
|
|
110
|
+
crypto.privateDecrypt({ key, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING }, buffer);
|
|
111
|
+
|
|
112
|
+
// Secure random
|
|
113
|
+
const token = crypto.randomBytes(32).toString('hex');
|
|
114
|
+
|
|
115
|
+
// GCM provides authentication
|
|
116
|
+
crypto.createCipheriv('aes-256-gcm', key, iv);
|
|
117
|
+
|
|
118
|
+
// Constant-time comparison
|
|
119
|
+
if (crypto.timingSafeEqual(Buffer.from(userToken), Buffer.from(storedToken))) { ... }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Peer Dependencies (Optional)
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"crypto-hash": ">=3.0.0",
|
|
127
|
+
"crypto-random-string": ">=4.0.0",
|
|
128
|
+
"crypto-js": ">=4.0.0"
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## AI-Optimized Messages
|
|
133
|
+
|
|
134
|
+
All rules include LLM-optimized error messages with:
|
|
135
|
+
|
|
136
|
+
- CWE references for vulnerability classification
|
|
137
|
+
- CVE references for known vulnerabilities
|
|
138
|
+
- Severity levels (CRITICAL, HIGH, MEDIUM, LOW)
|
|
139
|
+
- Direct fix suggestions with code examples
|
|
140
|
+
- Documentation links
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
MIT © [Ofri Peretz](https://github.com/ofri-peretz)
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "eslint-plugin-crypto",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Security-focused ESLint plugin with 24 AI-parseable rules for cryptographic best practices. Detects weak algorithms, insecure key handling, CVE-specific vulnerabilities, and deprecated crypto patterns.",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"main": "./src/index.js",
|
|
7
|
+
"types": "./src/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./src/index.d.ts",
|
|
11
|
+
"default": "./src/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./types": {
|
|
14
|
+
"types": "./src/types/index.d.ts",
|
|
15
|
+
"default": "./src/types/index.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"author": "Ofri Peretz <ofriperetzdev@gmail.com>",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"homepage": "https://github.com/ofri-peretz/eslint/blob/main/packages/eslint-plugin-crypto/README.md",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/ofri-peretz/eslint.git",
|
|
24
|
+
"directory": "packages/eslint-plugin-crypto"
|
|
25
|
+
},
|
|
26
|
+
"bugs": {
|
|
27
|
+
"url": "https://github.com/ofri-peretz/eslint/issues"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"src/",
|
|
34
|
+
"dist/",
|
|
35
|
+
"docs/",
|
|
36
|
+
"README.md",
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"CHANGELOG.md",
|
|
39
|
+
"AGENTS.md"
|
|
40
|
+
],
|
|
41
|
+
"keywords": [
|
|
42
|
+
"eslint",
|
|
43
|
+
"eslint-plugin",
|
|
44
|
+
"eslintplugin",
|
|
45
|
+
"security",
|
|
46
|
+
"crypto",
|
|
47
|
+
"cryptography",
|
|
48
|
+
"encryption",
|
|
49
|
+
"hashing",
|
|
50
|
+
"nodejs-crypto",
|
|
51
|
+
"cve",
|
|
52
|
+
"cwe",
|
|
53
|
+
"owasp",
|
|
54
|
+
"vulnerability",
|
|
55
|
+
"llm-optimized",
|
|
56
|
+
"ai-assistant",
|
|
57
|
+
"auto-fix",
|
|
58
|
+
"typescript",
|
|
59
|
+
"marvin-attack",
|
|
60
|
+
"timing-attack"
|
|
61
|
+
],
|
|
62
|
+
"engines": {
|
|
63
|
+
"node": ">=18.0.0"
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"@interlace/eslint-devkit": "^1.2.1",
|
|
67
|
+
"tslib": "^2.3.0"
|
|
68
|
+
},
|
|
69
|
+
"devDependencies": {
|
|
70
|
+
"@typescript-eslint/parser": "^8.46.2",
|
|
71
|
+
"@typescript-eslint/rule-tester": "^8.46.2",
|
|
72
|
+
"@vitest/coverage-v8": "^4.0.6",
|
|
73
|
+
"vitest": "^4.0.6"
|
|
74
|
+
},
|
|
75
|
+
"scripts": {
|
|
76
|
+
"test": "vitest run",
|
|
77
|
+
"test:watch": "vitest watch",
|
|
78
|
+
"test:coverage": "vitest run --coverage"
|
|
79
|
+
}
|
|
80
|
+
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* eslint-plugin-crypto
|
|
3
|
+
*
|
|
4
|
+
* Security-focused ESLint plugin with 24 rules for cryptographic best practices.
|
|
5
|
+
* Covers Node.js crypto, crypto-hash, crypto-random-string, cryptojs, and Web Crypto.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - LLM-optimized error messages with CWE references
|
|
9
|
+
* - Auto-fix suggestions where safe
|
|
10
|
+
* - OWASP-aligned recommendations
|
|
11
|
+
* - CVE-specific detection (CVE-2023-46809, CVE-2020-36732, CVE-2023-46233)
|
|
12
|
+
*
|
|
13
|
+
* @see https://github.com/ofri-peretz/eslint/tree/main/packages/eslint-plugin-crypto
|
|
14
|
+
*/
|
|
15
|
+
import type { TSESLint } from '@interlace/eslint-devkit';
|
|
16
|
+
/**
|
|
17
|
+
* Collection of all crypto security rules (24 total)
|
|
18
|
+
*/
|
|
19
|
+
export declare const rules: Record<string, TSESLint.RuleModule<string, readonly unknown[]>>;
|
|
20
|
+
/**
|
|
21
|
+
* ESLint Plugin object
|
|
22
|
+
*/
|
|
23
|
+
export declare const plugin: TSESLint.FlatConfig.Plugin;
|
|
24
|
+
/**
|
|
25
|
+
* Preset configurations
|
|
26
|
+
*/
|
|
27
|
+
export declare const configs: Record<string, TSESLint.FlatConfig.Config>;
|
|
28
|
+
/**
|
|
29
|
+
* Default export for ESLint plugin
|
|
30
|
+
*/
|
|
31
|
+
export default plugin;
|
|
32
|
+
/**
|
|
33
|
+
* Re-export all types
|
|
34
|
+
*/
|
|
35
|
+
export * from './types/index';
|
package/src/index.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* eslint-plugin-crypto
|
|
4
|
+
*
|
|
5
|
+
* Security-focused ESLint plugin with 24 rules for cryptographic best practices.
|
|
6
|
+
* Covers Node.js crypto, crypto-hash, crypto-random-string, cryptojs, and Web Crypto.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - LLM-optimized error messages with CWE references
|
|
10
|
+
* - Auto-fix suggestions where safe
|
|
11
|
+
* - OWASP-aligned recommendations
|
|
12
|
+
* - CVE-specific detection (CVE-2023-46809, CVE-2020-36732, CVE-2023-46233)
|
|
13
|
+
*
|
|
14
|
+
* @see https://github.com/ofri-peretz/eslint/tree/main/packages/eslint-plugin-crypto
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.configs = exports.plugin = exports.rules = void 0;
|
|
18
|
+
const tslib_1 = require("tslib");
|
|
19
|
+
// Core Node.js crypto rules
|
|
20
|
+
const no_weak_hash_algorithm_1 = require("./rules/no-weak-hash-algorithm");
|
|
21
|
+
const no_weak_cipher_algorithm_1 = require("./rules/no-weak-cipher-algorithm");
|
|
22
|
+
const no_deprecated_cipher_method_1 = require("./rules/no-deprecated-cipher-method");
|
|
23
|
+
const no_static_iv_1 = require("./rules/no-static-iv");
|
|
24
|
+
const no_ecb_mode_1 = require("./rules/no-ecb-mode");
|
|
25
|
+
const no_insecure_key_derivation_1 = require("./rules/no-insecure-key-derivation");
|
|
26
|
+
const no_hardcoded_crypto_key_1 = require("./rules/no-hardcoded-crypto-key");
|
|
27
|
+
const require_random_iv_1 = require("./rules/require-random-iv");
|
|
28
|
+
// crypto-hash package rules
|
|
29
|
+
const no_sha1_hash_1 = require("./rules/no-sha1-hash");
|
|
30
|
+
// crypto-random-string package rules
|
|
31
|
+
const require_sufficient_length_1 = require("./rules/require-sufficient-length");
|
|
32
|
+
const no_numeric_only_tokens_1 = require("./rules/no-numeric-only-tokens");
|
|
33
|
+
// cryptojs package rules
|
|
34
|
+
const no_cryptojs_1 = require("./rules/no-cryptojs");
|
|
35
|
+
const no_cryptojs_weak_random_1 = require("./rules/no-cryptojs-weak-random");
|
|
36
|
+
const prefer_native_crypto_1 = require("./rules/prefer-native-crypto");
|
|
37
|
+
// NEW: CVE and advanced security rules
|
|
38
|
+
const no_math_random_crypto_1 = require("./rules/no-math-random-crypto");
|
|
39
|
+
const no_insecure_rsa_padding_1 = require("./rules/no-insecure-rsa-padding");
|
|
40
|
+
const require_secure_pbkdf2_digest_1 = require("./rules/require-secure-pbkdf2-digest");
|
|
41
|
+
const no_predictable_salt_1 = require("./rules/no-predictable-salt");
|
|
42
|
+
const require_authenticated_encryption_1 = require("./rules/require-authenticated-encryption");
|
|
43
|
+
const no_key_reuse_1 = require("./rules/no-key-reuse");
|
|
44
|
+
const no_self_signed_certs_1 = require("./rules/no-self-signed-certs");
|
|
45
|
+
const no_timing_unsafe_compare_1 = require("./rules/no-timing-unsafe-compare");
|
|
46
|
+
const require_key_length_1 = require("./rules/require-key-length");
|
|
47
|
+
const no_web_crypto_export_1 = require("./rules/no-web-crypto-export");
|
|
48
|
+
/**
|
|
49
|
+
* Collection of all crypto security rules (24 total)
|
|
50
|
+
*/
|
|
51
|
+
exports.rules = {
|
|
52
|
+
// Core Node.js crypto rules (8)
|
|
53
|
+
'no-weak-hash-algorithm': no_weak_hash_algorithm_1.noWeakHashAlgorithm,
|
|
54
|
+
'no-weak-cipher-algorithm': no_weak_cipher_algorithm_1.noWeakCipherAlgorithm,
|
|
55
|
+
'no-deprecated-cipher-method': no_deprecated_cipher_method_1.noDeprecatedCipherMethod,
|
|
56
|
+
'no-static-iv': no_static_iv_1.noStaticIv,
|
|
57
|
+
'no-ecb-mode': no_ecb_mode_1.noEcbMode,
|
|
58
|
+
'no-insecure-key-derivation': no_insecure_key_derivation_1.noInsecureKeyDerivation,
|
|
59
|
+
'no-hardcoded-crypto-key': no_hardcoded_crypto_key_1.noHardcodedCryptoKey,
|
|
60
|
+
'require-random-iv': require_random_iv_1.requireRandomIv,
|
|
61
|
+
// crypto-hash package rules (1)
|
|
62
|
+
'no-sha1-hash': no_sha1_hash_1.noSha1Hash,
|
|
63
|
+
// crypto-random-string package rules (2)
|
|
64
|
+
'require-sufficient-length': require_sufficient_length_1.requireSufficientLength,
|
|
65
|
+
'no-numeric-only-tokens': no_numeric_only_tokens_1.noNumericOnlyTokens,
|
|
66
|
+
// cryptojs package rules (3)
|
|
67
|
+
'no-cryptojs': no_cryptojs_1.noCryptojs,
|
|
68
|
+
'no-cryptojs-weak-random': no_cryptojs_weak_random_1.noCryptojsWeakRandom,
|
|
69
|
+
'prefer-native-crypto': prefer_native_crypto_1.preferNativeCrypto,
|
|
70
|
+
// Advanced security rules (10)
|
|
71
|
+
'no-math-random-crypto': no_math_random_crypto_1.noMathRandomCrypto,
|
|
72
|
+
'no-insecure-rsa-padding': no_insecure_rsa_padding_1.noInsecureRsaPadding,
|
|
73
|
+
'require-secure-pbkdf2-digest': require_secure_pbkdf2_digest_1.requireSecurePbkdf2Digest,
|
|
74
|
+
'no-predictable-salt': no_predictable_salt_1.noPredictableSalt,
|
|
75
|
+
'require-authenticated-encryption': require_authenticated_encryption_1.requireAuthenticatedEncryption,
|
|
76
|
+
'no-key-reuse': no_key_reuse_1.noKeyReuse,
|
|
77
|
+
'no-self-signed-certs': no_self_signed_certs_1.noSelfSignedCerts,
|
|
78
|
+
'no-timing-unsafe-compare': no_timing_unsafe_compare_1.noTimingUnsafeCompare,
|
|
79
|
+
'require-key-length': require_key_length_1.requireKeyLength,
|
|
80
|
+
'no-web-crypto-export': no_web_crypto_export_1.noWebCryptoExport,
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* ESLint Plugin object
|
|
84
|
+
*/
|
|
85
|
+
exports.plugin = {
|
|
86
|
+
meta: {
|
|
87
|
+
name: 'eslint-plugin-crypto',
|
|
88
|
+
version: '1.0.0',
|
|
89
|
+
},
|
|
90
|
+
rules: exports.rules,
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Recommended rules - balanced between security and practicality
|
|
94
|
+
*/
|
|
95
|
+
const recommendedRules = {
|
|
96
|
+
// Critical - Always error
|
|
97
|
+
'crypto/no-weak-hash-algorithm': 'error',
|
|
98
|
+
'crypto/no-weak-cipher-algorithm': 'error',
|
|
99
|
+
'crypto/no-deprecated-cipher-method': 'error',
|
|
100
|
+
'crypto/no-hardcoded-crypto-key': 'error',
|
|
101
|
+
'crypto/no-ecb-mode': 'error',
|
|
102
|
+
'crypto/no-cryptojs-weak-random': 'error',
|
|
103
|
+
'crypto/no-math-random-crypto': 'error',
|
|
104
|
+
'crypto/no-insecure-rsa-padding': 'error',
|
|
105
|
+
'crypto/no-self-signed-certs': 'error',
|
|
106
|
+
// High - Error for most projects
|
|
107
|
+
'crypto/no-static-iv': 'error',
|
|
108
|
+
'crypto/no-insecure-key-derivation': 'error',
|
|
109
|
+
'crypto/require-random-iv': 'warn',
|
|
110
|
+
'crypto/no-sha1-hash': 'error',
|
|
111
|
+
'crypto/require-secure-pbkdf2-digest': 'error',
|
|
112
|
+
'crypto/no-predictable-salt': 'error',
|
|
113
|
+
'crypto/no-timing-unsafe-compare': 'warn',
|
|
114
|
+
// Medium - Warnings
|
|
115
|
+
'crypto/require-sufficient-length': 'warn',
|
|
116
|
+
'crypto/no-numeric-only-tokens': 'warn',
|
|
117
|
+
'crypto/no-cryptojs': 'warn',
|
|
118
|
+
'crypto/prefer-native-crypto': 'warn',
|
|
119
|
+
'crypto/require-authenticated-encryption': 'warn',
|
|
120
|
+
'crypto/no-key-reuse': 'warn',
|
|
121
|
+
'crypto/require-key-length': 'warn',
|
|
122
|
+
'crypto/no-web-crypto-export': 'warn',
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Preset configurations
|
|
126
|
+
*/
|
|
127
|
+
exports.configs = {
|
|
128
|
+
/**
|
|
129
|
+
* Recommended configuration - sensible defaults
|
|
130
|
+
*/
|
|
131
|
+
recommended: {
|
|
132
|
+
plugins: {
|
|
133
|
+
crypto: exports.plugin,
|
|
134
|
+
},
|
|
135
|
+
rules: recommendedRules,
|
|
136
|
+
},
|
|
137
|
+
/**
|
|
138
|
+
* Strict configuration - all rules as errors
|
|
139
|
+
*/
|
|
140
|
+
strict: {
|
|
141
|
+
plugins: {
|
|
142
|
+
crypto: exports.plugin,
|
|
143
|
+
},
|
|
144
|
+
rules: Object.fromEntries(Object.keys(exports.rules).map(ruleName => [`crypto/${ruleName}`, 'error'])),
|
|
145
|
+
},
|
|
146
|
+
/**
|
|
147
|
+
* CryptoJS migration configuration
|
|
148
|
+
* For teams migrating from crypto-js to native crypto
|
|
149
|
+
*/
|
|
150
|
+
'cryptojs-migration': {
|
|
151
|
+
plugins: {
|
|
152
|
+
crypto: exports.plugin,
|
|
153
|
+
},
|
|
154
|
+
rules: {
|
|
155
|
+
'crypto/no-cryptojs': 'error',
|
|
156
|
+
'crypto/no-cryptojs-weak-random': 'error',
|
|
157
|
+
'crypto/prefer-native-crypto': 'error',
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
/**
|
|
161
|
+
* Node.js-only configuration
|
|
162
|
+
* Only Node.js crypto rules, no package-specific rules
|
|
163
|
+
*/
|
|
164
|
+
'nodejs-only': {
|
|
165
|
+
plugins: {
|
|
166
|
+
crypto: exports.plugin,
|
|
167
|
+
},
|
|
168
|
+
rules: {
|
|
169
|
+
'crypto/no-weak-hash-algorithm': 'error',
|
|
170
|
+
'crypto/no-weak-cipher-algorithm': 'error',
|
|
171
|
+
'crypto/no-deprecated-cipher-method': 'error',
|
|
172
|
+
'crypto/no-static-iv': 'error',
|
|
173
|
+
'crypto/no-ecb-mode': 'error',
|
|
174
|
+
'crypto/no-insecure-key-derivation': 'error',
|
|
175
|
+
'crypto/no-hardcoded-crypto-key': 'error',
|
|
176
|
+
'crypto/require-random-iv': 'warn',
|
|
177
|
+
'crypto/no-math-random-crypto': 'error',
|
|
178
|
+
'crypto/no-insecure-rsa-padding': 'error',
|
|
179
|
+
'crypto/require-secure-pbkdf2-digest': 'error',
|
|
180
|
+
'crypto/no-predictable-salt': 'error',
|
|
181
|
+
'crypto/require-authenticated-encryption': 'warn',
|
|
182
|
+
'crypto/no-key-reuse': 'warn',
|
|
183
|
+
'crypto/no-self-signed-certs': 'error',
|
|
184
|
+
'crypto/no-timing-unsafe-compare': 'warn',
|
|
185
|
+
'crypto/require-key-length': 'warn',
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
/**
|
|
189
|
+
* CVE-focused configuration
|
|
190
|
+
* Rules specifically targeting known CVEs
|
|
191
|
+
*/
|
|
192
|
+
'cve-focused': {
|
|
193
|
+
plugins: {
|
|
194
|
+
crypto: exports.plugin,
|
|
195
|
+
},
|
|
196
|
+
rules: {
|
|
197
|
+
'crypto/no-insecure-rsa-padding': 'error', // CVE-2023-46809 (Marvin Attack)
|
|
198
|
+
'crypto/no-cryptojs-weak-random': 'error', // CVE-2020-36732
|
|
199
|
+
'crypto/require-secure-pbkdf2-digest': 'error', // CVE-2023-46233
|
|
200
|
+
'crypto/no-weak-hash-algorithm': 'error', // Various CVEs
|
|
201
|
+
'crypto/no-weak-cipher-algorithm': 'error', // Various CVEs
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
};
|
|
205
|
+
/**
|
|
206
|
+
* Default export for ESLint plugin
|
|
207
|
+
*/
|
|
208
|
+
exports.default = exports.plugin;
|
|
209
|
+
/**
|
|
210
|
+
* Re-export all types
|
|
211
|
+
*/
|
|
212
|
+
tslib_1.__exportStar(require("./types/index"), exports);
|
|
213
|
+
//# sourceMappingURL=index.js.map
|
package/src/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/eslint-plugin-crypto/src/index.ts"],"names":[],"mappings":"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"}
|