@npm-breach/check 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/README.md +117 -0
- package/affected-packages.json +232 -0
- package/lib/affected-packages.json +232 -0
- package/lib/commands/check.js +68 -0
- package/lib/commands/checkPackage.js +22 -0
- package/lib/commands/help.js +36 -0
- package/lib/commands/list.js +26 -0
- package/lib/core/packageChecker.js +58 -0
- package/lib/core/packageLoader.js +17 -0
- package/lib/index.js +50 -0
- package/lib/utils/colors.js +15 -0
- package/lib/utils/output.js +37 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# NPM Breach Check
|
|
2
|
+
|
|
3
|
+
🔐 **Security-focused CLI tool to detect potentially vulnerable packages in your Node.js applications**
|
|
4
|
+
|
|
5
|
+
A lightweight command-line scanner that checks for known vulnerable packages in your dependency tree. Help protect your applications by identifying packages that may pose security risks.
|
|
6
|
+
|
|
7
|
+
## 🚀 Quick Start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Install globally
|
|
11
|
+
npm install -g @npm-breach/check
|
|
12
|
+
|
|
13
|
+
# Check your project for vulnerable packages
|
|
14
|
+
npm-breach-check
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 📋 Usage
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Scan all packages in your project (default)
|
|
21
|
+
npm-breach-check
|
|
22
|
+
|
|
23
|
+
# List all monitored packages
|
|
24
|
+
npm-breach-check list
|
|
25
|
+
|
|
26
|
+
# Show help
|
|
27
|
+
npm-breach-check help
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## 📊 Example Output
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
Summary:
|
|
34
|
+
Total checked: 60
|
|
35
|
+
Found: 12
|
|
36
|
+
Affected versions: 1
|
|
37
|
+
Used but not affected: 11
|
|
38
|
+
Not used in the project: 48
|
|
39
|
+
|
|
40
|
+
Affected versions:
|
|
41
|
+
==================
|
|
42
|
+
✓ ansi-styles@2.2.1 (affected: 2.2.1)
|
|
43
|
+
|
|
44
|
+
Used but not affected:
|
|
45
|
+
======================
|
|
46
|
+
⚠ debug@2.6.9 (affected: 4.4.2)
|
|
47
|
+
⚠ chalk@1.1.3 (affected: 5.6.1)
|
|
48
|
+
⚠ supports-color@3.2.3 (affected: 10.2.1)
|
|
49
|
+
⚠ strip-ansi@3.0.1 (affected: 7.1.1)
|
|
50
|
+
⚠ ansi-regex@2.1.1 (affected: 6.2.1)
|
|
51
|
+
⚠ wrap-ansi@2.1.0 (affected: 9.0.1)
|
|
52
|
+
⚠ color-convert@1.9.3 (affected: 3.1.1)
|
|
53
|
+
⚠ color-name@1.1.4 (affected: 2.0.1)
|
|
54
|
+
⚠ is-arrayish@0.2.1 (affected: 0.3.3)
|
|
55
|
+
⚠ has-ansi@2.0.0 (affected: 6.0.1)
|
|
56
|
+
⚠ error-ex@1.3.4 (affected: 1.3.3)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- 🔴 **Affected versions** - Vulnerable packages found (need immediate attention)
|
|
60
|
+
- 🟡 **Used but not affected** - Packages installed but in safe versions
|
|
61
|
+
- 🟢 **Not used in project** - Packages not installed (you're safe)
|
|
62
|
+
|
|
63
|
+
## ⚡ Features
|
|
64
|
+
|
|
65
|
+
- **Zero Configuration** - Works out of the box
|
|
66
|
+
- **Lightweight** - Only one dependency (`semver`)
|
|
67
|
+
- **Fast Scanning** - Native Node.js performance
|
|
68
|
+
- **Semantic Versioning** - Supports version ranges (`^`, `~`, `>=`, etc.)
|
|
69
|
+
- **Dependency Tree Analysis** - Deep scanning with `npm ls`
|
|
70
|
+
|
|
71
|
+
## 🛡️ What It Checks
|
|
72
|
+
|
|
73
|
+
This tool monitors a curated list of packages known to have security considerations, including:
|
|
74
|
+
|
|
75
|
+
- Color manipulation packages (chalk, ansi-styles)
|
|
76
|
+
- Angular/React form utilities
|
|
77
|
+
- File processing libraries
|
|
78
|
+
- Template engines
|
|
79
|
+
- And many more...
|
|
80
|
+
|
|
81
|
+
Run `npm-breach-check list` to see the complete monitored package list.
|
|
82
|
+
|
|
83
|
+
## 🤝 Contributing
|
|
84
|
+
|
|
85
|
+
We welcome contributions to improve package security monitoring!
|
|
86
|
+
|
|
87
|
+
### Adding New Packages
|
|
88
|
+
|
|
89
|
+
To add a potentially vulnerable package to the monitoring list:
|
|
90
|
+
|
|
91
|
+
1. Fork this repository
|
|
92
|
+
2. Edit `affected-packages.json`
|
|
93
|
+
3. Add your package with version constraints:
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"name": "package-name",
|
|
97
|
+
"versions": ["^1.0.0", ">=2.1.0"]
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
4. Submit a pull request with details about the security concern
|
|
101
|
+
|
|
102
|
+
### Development Setup
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
git clone https://github.com/your-username/npm-breach-check.git
|
|
106
|
+
cd npm-breach-check
|
|
107
|
+
npm install
|
|
108
|
+
npm link
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 📄 License
|
|
112
|
+
|
|
113
|
+
MIT © Contributors
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
**Help keep the Node.js ecosystem secure - contribute to the monitored package list!**
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
{
|
|
2
|
+
"packages": [
|
|
3
|
+
{
|
|
4
|
+
"name": "angulartics2",
|
|
5
|
+
"versions": ["14.1.2"]
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "@ctrl/deluge",
|
|
9
|
+
"versions": ["7.2.2"]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "@ctrl/golang-template",
|
|
13
|
+
"versions": ["1.4.3"]
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "@ctrl/magnet-link",
|
|
17
|
+
"versions": ["4.0.4"]
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "@ctrl/ngx-codemirror",
|
|
21
|
+
"versions": ["7.0.2"]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "@ctrl/ngx-csv",
|
|
25
|
+
"versions": ["6.0.2"]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "@ctrl/ngx-emoji-mart",
|
|
29
|
+
"versions": ["9.2.2"]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "@ctrl/ngx-rightclick",
|
|
33
|
+
"versions": ["4.0.2"]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "@ctrl/qbittorrent",
|
|
37
|
+
"versions": ["9.7.2"]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "@ctrl/react-adsense",
|
|
41
|
+
"versions": ["2.0.2"]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "@ctrl/shared-torrent",
|
|
45
|
+
"versions": ["6.3.2"]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "@ctrl/tinycolor",
|
|
49
|
+
"versions": ["4.1.1", "4.1.2"]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "@ctrl/torrent-file",
|
|
53
|
+
"versions": ["4.1.2"]
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "@ctrl/transmission",
|
|
57
|
+
"versions": ["7.3.1"]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "@ctrl/ts-base32",
|
|
61
|
+
"versions": ["4.0.2"]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "encounter-playground",
|
|
65
|
+
"versions": ["0.0.5"]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "json-rules-engine-simplified",
|
|
69
|
+
"versions": ["0.2.4", "0.2.1"]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "koa2-swagger-ui",
|
|
73
|
+
"versions": ["5.11.2", "5.11.1"]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "@nativescript-community/gesturehandler",
|
|
77
|
+
"versions": ["2.0.35"]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "@nativescript-community/sentry",
|
|
81
|
+
"versions": ["4.6.43"]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "@nativescript-community/text",
|
|
85
|
+
"versions": ["1.6.13"]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"name": "@nativescript-community/ui-collectionview",
|
|
89
|
+
"versions": ["6.0.6"]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "@nativescript-community/ui-drawer",
|
|
93
|
+
"versions": ["0.1.30"]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "@nativescript-community/ui-image",
|
|
97
|
+
"versions": ["4.5.6"]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "@nativescript-community/ui-material-bottomsheet",
|
|
101
|
+
"versions": ["7.2.72"]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "@nativescript-community/ui-material-core",
|
|
105
|
+
"versions": ["7.2.76"]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "@nativescript-community/ui-material-core-tabs",
|
|
109
|
+
"versions": ["7.2.76"]
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"name": "ngx-color",
|
|
113
|
+
"versions": ["10.0.2"]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name": "ngx-toastr",
|
|
117
|
+
"versions": ["19.0.2"]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"name": "ngx-trend",
|
|
121
|
+
"versions": ["8.0.1"]
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "react-complaint-image",
|
|
125
|
+
"versions": ["0.0.35"]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"name": "react-jsonschema-form-conditionals",
|
|
129
|
+
"versions": ["0.3.21"]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"name": "react-jsonschema-form-extras",
|
|
133
|
+
"versions": ["1.0.4"]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "rxnt-authentication",
|
|
137
|
+
"versions": ["0.0.6"]
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"name": "rxnt-healthchecks-nestjs",
|
|
141
|
+
"versions": ["1.0.5"]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"name": "rxnt-kue",
|
|
145
|
+
"versions": ["1.0.7"]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"name": "swc-plugin-component-annotate",
|
|
149
|
+
"versions": ["1.9.2"]
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "ts-gaussian",
|
|
153
|
+
"versions": ["3.0.6"]
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"name": "ansi-styles",
|
|
157
|
+
"versions": ["2.2.1"]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"name": "debug",
|
|
161
|
+
"versions": ["4.4.2"]
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "chalk",
|
|
165
|
+
"versions": ["5.6.1"]
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"name": "supports-color",
|
|
169
|
+
"versions": ["10.2.1"]
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"name": "strip-ansi",
|
|
173
|
+
"versions": ["7.1.1"]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"name": "ansi-regex",
|
|
177
|
+
"versions": ["6.2.1"]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"name": "wrap-ansi",
|
|
181
|
+
"versions": ["9.0.1"]
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"name": "color-convert",
|
|
185
|
+
"versions": ["3.1.1"]
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"name": "color-name",
|
|
189
|
+
"versions": ["2.0.1"]
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"name": "is-arrayish",
|
|
193
|
+
"versions": ["0.3.3"]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"name": "slice-ansi",
|
|
197
|
+
"versions": ["7.1.1"]
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"name": "color",
|
|
201
|
+
"versions": ["5.0.1"]
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "color-string",
|
|
205
|
+
"versions": ["2.1.1"]
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"name": "simple-swizzle",
|
|
209
|
+
"versions": ["0.2.3"]
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"name": "supports-hyperlinks",
|
|
213
|
+
"versions": ["4.1.1"]
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"name": "has-ansi",
|
|
217
|
+
"versions": ["6.0.1"]
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"name": "chalk-template",
|
|
221
|
+
"versions": ["1.1.1"]
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"name": "backslash",
|
|
225
|
+
"versions": ["0.2.1"]
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"name": "error-ex",
|
|
229
|
+
"versions": ["1.3.3"]
|
|
230
|
+
}
|
|
231
|
+
]
|
|
232
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
{
|
|
2
|
+
"packages": [
|
|
3
|
+
{
|
|
4
|
+
"name": "angulartics2",
|
|
5
|
+
"versions": ["14.1.2"]
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"name": "@ctrl/deluge",
|
|
9
|
+
"versions": ["7.2.2"]
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"name": "@ctrl/golang-template",
|
|
13
|
+
"versions": ["1.4.3"]
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"name": "@ctrl/magnet-link",
|
|
17
|
+
"versions": ["4.0.4"]
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"name": "@ctrl/ngx-codemirror",
|
|
21
|
+
"versions": ["7.0.2"]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "@ctrl/ngx-csv",
|
|
25
|
+
"versions": ["6.0.2"]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"name": "@ctrl/ngx-emoji-mart",
|
|
29
|
+
"versions": ["9.2.2"]
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "@ctrl/ngx-rightclick",
|
|
33
|
+
"versions": ["4.0.2"]
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"name": "@ctrl/qbittorrent",
|
|
37
|
+
"versions": ["9.7.2"]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"name": "@ctrl/react-adsense",
|
|
41
|
+
"versions": ["2.0.2"]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "@ctrl/shared-torrent",
|
|
45
|
+
"versions": ["6.3.2"]
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "@ctrl/tinycolor",
|
|
49
|
+
"versions": ["4.1.1", "4.1.2"]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"name": "@ctrl/torrent-file",
|
|
53
|
+
"versions": ["4.1.2"]
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "@ctrl/transmission",
|
|
57
|
+
"versions": ["7.3.1"]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "@ctrl/ts-base32",
|
|
61
|
+
"versions": ["4.0.2"]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "encounter-playground",
|
|
65
|
+
"versions": ["0.0.5"]
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
"name": "json-rules-engine-simplified",
|
|
69
|
+
"versions": ["0.2.4", "0.2.1"]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "koa2-swagger-ui",
|
|
73
|
+
"versions": ["5.11.2", "5.11.1"]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "@nativescript-community/gesturehandler",
|
|
77
|
+
"versions": ["2.0.35"]
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "@nativescript-community/sentry",
|
|
81
|
+
"versions": ["4.6.43"]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"name": "@nativescript-community/text",
|
|
85
|
+
"versions": ["1.6.13"]
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"name": "@nativescript-community/ui-collectionview",
|
|
89
|
+
"versions": ["6.0.6"]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "@nativescript-community/ui-drawer",
|
|
93
|
+
"versions": ["0.1.30"]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"name": "@nativescript-community/ui-image",
|
|
97
|
+
"versions": ["4.5.6"]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"name": "@nativescript-community/ui-material-bottomsheet",
|
|
101
|
+
"versions": ["7.2.72"]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "@nativescript-community/ui-material-core",
|
|
105
|
+
"versions": ["7.2.76"]
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"name": "@nativescript-community/ui-material-core-tabs",
|
|
109
|
+
"versions": ["7.2.76"]
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"name": "ngx-color",
|
|
113
|
+
"versions": ["10.0.2"]
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name": "ngx-toastr",
|
|
117
|
+
"versions": ["19.0.2"]
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"name": "ngx-trend",
|
|
121
|
+
"versions": ["8.0.1"]
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"name": "react-complaint-image",
|
|
125
|
+
"versions": ["0.0.35"]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"name": "react-jsonschema-form-conditionals",
|
|
129
|
+
"versions": ["0.3.21"]
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"name": "react-jsonschema-form-extras",
|
|
133
|
+
"versions": ["1.0.4"]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "rxnt-authentication",
|
|
137
|
+
"versions": ["0.0.6"]
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"name": "rxnt-healthchecks-nestjs",
|
|
141
|
+
"versions": ["1.0.5"]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"name": "rxnt-kue",
|
|
145
|
+
"versions": ["1.0.7"]
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"name": "swc-plugin-component-annotate",
|
|
149
|
+
"versions": ["1.9.2"]
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "ts-gaussian",
|
|
153
|
+
"versions": ["3.0.6"]
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"name": "ansi-styles",
|
|
157
|
+
"versions": ["6.2.2"]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
"name": "debug",
|
|
161
|
+
"versions": ["4.4.2"]
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "chalk",
|
|
165
|
+
"versions": ["5.6.1"]
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
"name": "supports-color",
|
|
169
|
+
"versions": ["10.2.1"]
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"name": "strip-ansi",
|
|
173
|
+
"versions": ["7.1.1"]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"name": "ansi-regex",
|
|
177
|
+
"versions": ["6.2.1"]
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"name": "wrap-ansi",
|
|
181
|
+
"versions": ["9.0.1"]
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"name": "color-convert",
|
|
185
|
+
"versions": ["3.1.1"]
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"name": "color-name",
|
|
189
|
+
"versions": ["2.0.1"]
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"name": "is-arrayish",
|
|
193
|
+
"versions": ["0.3.3"]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"name": "slice-ansi",
|
|
197
|
+
"versions": ["7.1.1"]
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"name": "color",
|
|
201
|
+
"versions": ["5.0.1"]
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "color-string",
|
|
205
|
+
"versions": ["2.1.1"]
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"name": "simple-swizzle",
|
|
209
|
+
"versions": ["0.2.3"]
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
"name": "supports-hyperlinks",
|
|
213
|
+
"versions": ["4.1.1"]
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"name": "has-ansi",
|
|
217
|
+
"versions": ["6.0.1"]
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"name": "chalk-template",
|
|
221
|
+
"versions": ["1.1.1"]
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"name": "backslash",
|
|
225
|
+
"versions": ["0.2.1"]
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"name": "error-ex",
|
|
229
|
+
"versions": ["1.3.3"]
|
|
230
|
+
}
|
|
231
|
+
]
|
|
232
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const { loadAffectedPackages } = require('../core/packageLoader');
|
|
2
|
+
const { checkPackageWithSemver } = require('../core/packageChecker');
|
|
3
|
+
const { printHeader, printSummary, printSatisfiedPackages, printAffectedPackages } = require('../utils/output');
|
|
4
|
+
const { colorize } = require('../utils/colors');
|
|
5
|
+
|
|
6
|
+
function checkAllAffectedPackages() {
|
|
7
|
+
const affectedPackages = loadAffectedPackages();
|
|
8
|
+
|
|
9
|
+
if (affectedPackages.length === 0) {
|
|
10
|
+
console.log(colorize("No packages loaded from affected-packages.json", 'red'));
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
printHeader();
|
|
15
|
+
|
|
16
|
+
let totalChecked = 0;
|
|
17
|
+
let foundCount = 0;
|
|
18
|
+
let satisfiedCount = 0;
|
|
19
|
+
const wrongVersionPackages = [];
|
|
20
|
+
const satisfiedPackages = [];
|
|
21
|
+
|
|
22
|
+
for (const packageInfo of affectedPackages) {
|
|
23
|
+
for (const versionRange of packageInfo.versions) {
|
|
24
|
+
totalChecked++;
|
|
25
|
+
console.log(colorize(`Checking: ${packageInfo.name} (${versionRange})`, 'yellow'));
|
|
26
|
+
|
|
27
|
+
const result = checkPackageWithSemver(packageInfo.name, versionRange);
|
|
28
|
+
|
|
29
|
+
if (result.found) {
|
|
30
|
+
foundCount++;
|
|
31
|
+
if (result.satisfies) {
|
|
32
|
+
satisfiedCount++;
|
|
33
|
+
console.log(colorize("✓ Affected", 'red'));
|
|
34
|
+
const satisfiedInfo = `${packageInfo.name}@${result.installedVersion} (affected: ${versionRange})`;
|
|
35
|
+
if (!satisfiedPackages.includes(satisfiedInfo)) {
|
|
36
|
+
satisfiedPackages.push(satisfiedInfo);
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
console.log(colorize("⚠ Found but version not affected", 'yellow'));
|
|
40
|
+
const wrongVersionInfo = `${packageInfo.name}@${result.installedVersion} (affected: ${versionRange})`;
|
|
41
|
+
if (!wrongVersionPackages.includes(wrongVersionInfo)) {
|
|
42
|
+
wrongVersionPackages.push(wrongVersionInfo);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
console.log(colorize(` Installed: ${result.installedVersion}`, 'gray'));
|
|
46
|
+
console.log(colorize(` Affected: ${versionRange}`, 'gray'));
|
|
47
|
+
} else {
|
|
48
|
+
console.log(colorize(` ${result.output}`, 'gray'));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
console.log(colorize("─".repeat(60), 'blue'));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const summary = {
|
|
56
|
+
totalChecked,
|
|
57
|
+
foundCount,
|
|
58
|
+
satisfiedCount,
|
|
59
|
+
satisfiedPackages,
|
|
60
|
+
wrongVersionPackages
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
printSummary(summary);
|
|
64
|
+
printSatisfiedPackages(satisfiedPackages);
|
|
65
|
+
printAffectedPackages(wrongVersionPackages);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = { checkAllAffectedPackages };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const { checkPackageWithSemver } = require('../core/packageChecker');
|
|
2
|
+
const { colorize } = require('../utils/colors');
|
|
3
|
+
|
|
4
|
+
function checkSpecificPackage(packageName, versionRange) {
|
|
5
|
+
console.log(colorize(`Checking package: ${packageName} (${versionRange})`, 'yellow'));
|
|
6
|
+
const result = checkPackageWithSemver(packageName, versionRange);
|
|
7
|
+
|
|
8
|
+
if (result.found) {
|
|
9
|
+
if (result.satisfies) {
|
|
10
|
+
console.log(colorize("✓ Affected", 'red'));
|
|
11
|
+
} else {
|
|
12
|
+
console.log(colorize("⚠ Found but version not affected", 'yellow'));
|
|
13
|
+
}
|
|
14
|
+
console.log(colorize(` Installed: ${result.installedVersion}`, 'gray'));
|
|
15
|
+
console.log(colorize(` Affected: ${versionRange}`, 'gray'));
|
|
16
|
+
} else {
|
|
17
|
+
console.log(colorize("✗ Not Affected", 'green'));
|
|
18
|
+
console.log(colorize(` ${result.output}`, 'gray'));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = { checkSpecificPackage };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const { colorize } = require('../utils/colors');
|
|
2
|
+
|
|
3
|
+
function showHelp() {
|
|
4
|
+
console.log(colorize('NPM Package Checker v1.0.0', 'blue'));
|
|
5
|
+
console.log(colorize("Check npm packages and semantic version ranges in dependency trees", 'gray'));
|
|
6
|
+
console.log();
|
|
7
|
+
console.log(colorize("Usage:", 'yellow'));
|
|
8
|
+
console.log(' npm-breach-check [command] [options]');
|
|
9
|
+
console.log();
|
|
10
|
+
console.log(colorize("Commands:", 'yellow'));
|
|
11
|
+
console.log(" check Check all affected packages (default)");
|
|
12
|
+
console.log(" check-package <name> <version-range> Check a specific package and version range");
|
|
13
|
+
console.log(" list List all affected packages");
|
|
14
|
+
console.log(" help, --help, -h Show this help message");
|
|
15
|
+
console.log(" version, --version, -v Show version number");
|
|
16
|
+
console.log();
|
|
17
|
+
console.log(colorize("Semantic Version Examples:", 'yellow'));
|
|
18
|
+
console.log(" ^1.2.3 Compatible with version 1.2.3 or higher (^1.2.3 ≤ version < 2.0.0)");
|
|
19
|
+
console.log(" ~1.2.3 Approximately equivalent to version 1.2.3 (~1.2.3 ≤ version < 1.3.0)");
|
|
20
|
+
console.log(" >=1.2.3 Greater than or equal to version 1.2.3");
|
|
21
|
+
console.log(" 1.2.3 Exact version 1.2.3");
|
|
22
|
+
console.log(" 1.2.x Any version in the 1.2.x range");
|
|
23
|
+
console.log();
|
|
24
|
+
console.log(colorize("Examples:", 'yellow'));
|
|
25
|
+
console.log(' npm-breach-check');
|
|
26
|
+
console.log(' npm-breach-check check');
|
|
27
|
+
console.log(" npm-breach-check check-package jwt-decode '^2.2.0'");
|
|
28
|
+
console.log(" npm-breach-check check-package react '>=16.0.0'");
|
|
29
|
+
console.log(' npm-breach-check list');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function showVersion() {
|
|
33
|
+
console.log('1.0.0');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = { showHelp, showVersion };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const { loadAffectedPackages } = require('../core/packageLoader');
|
|
2
|
+
const { colorize } = require('../utils/colors');
|
|
3
|
+
|
|
4
|
+
function listPackages() {
|
|
5
|
+
const affectedPackages = loadAffectedPackages();
|
|
6
|
+
|
|
7
|
+
if (affectedPackages.length === 0) {
|
|
8
|
+
console.log(colorize("No packages loaded from affected-packages.json", 'red'));
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
console.log(colorize("Affected packages:", 'blue'));
|
|
13
|
+
console.log(colorize("=================", 'blue'));
|
|
14
|
+
|
|
15
|
+
for (const packageInfo of affectedPackages) {
|
|
16
|
+
console.log(colorize(`${packageInfo.name}`, 'green'));
|
|
17
|
+
for (const version of packageInfo.versions) {
|
|
18
|
+
console.log(colorize(` └─ ${version}`, 'gray'));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const totalVersions = affectedPackages.reduce((acc, pkg) => acc + pkg.versions.length, 0);
|
|
23
|
+
console.log(colorize(`\nTotal: ${affectedPackages.length} packages with ${totalVersions} versions`, 'cyan'));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = { listPackages };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const { execSync } = require('child_process');
|
|
2
|
+
const semver = require('semver');
|
|
3
|
+
|
|
4
|
+
function getInstalledPackageInfo(packageName) {
|
|
5
|
+
try {
|
|
6
|
+
const output = execSync(`npm ls ${packageName} --json`, {
|
|
7
|
+
encoding: 'utf8',
|
|
8
|
+
stdio: 'pipe'
|
|
9
|
+
});
|
|
10
|
+
const data = JSON.parse(output);
|
|
11
|
+
|
|
12
|
+
// Navigate through the dependency tree to find the package
|
|
13
|
+
function findPackage(deps, name) {
|
|
14
|
+
if (!deps) return null;
|
|
15
|
+
|
|
16
|
+
if (deps[name]) {
|
|
17
|
+
return {
|
|
18
|
+
version: deps[name].version,
|
|
19
|
+
path: deps[name].path || ''
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Search in nested dependencies
|
|
24
|
+
for (const depName in deps) {
|
|
25
|
+
const found = findPackage(deps[depName].dependencies, name);
|
|
26
|
+
if (found) return found;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return findPackage(data.dependencies, packageName);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function checkPackageWithSemver(packageName, versionRange) {
|
|
39
|
+
const installedPkg = getInstalledPackageInfo(packageName);
|
|
40
|
+
|
|
41
|
+
if (!installedPkg) {
|
|
42
|
+
return {
|
|
43
|
+
found: false,
|
|
44
|
+
output: `Package ${packageName} not found in dependency tree`
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const satisfies = semver.satisfies(installedPkg.version, versionRange);
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
found: true,
|
|
52
|
+
installedVersion: installedPkg.version,
|
|
53
|
+
satisfies,
|
|
54
|
+
output: `Found ${packageName}@${installedPkg.version} ${satisfies ? '✓' : '✗'} (${satisfies ? 'satisfies' : 'does not satisfy'} ${versionRange})`
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
module.exports = { getInstalledPackageInfo, checkPackageWithSemver };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { colorize } = require('../utils/colors');
|
|
4
|
+
|
|
5
|
+
function loadAffectedPackages() {
|
|
6
|
+
try {
|
|
7
|
+
const jsonPath = path.join(__dirname, '..', '..', 'affected-packages.json');
|
|
8
|
+
const jsonContent = fs.readFileSync(jsonPath, 'utf8');
|
|
9
|
+
const config = JSON.parse(jsonContent);
|
|
10
|
+
return config.packages;
|
|
11
|
+
} catch (error) {
|
|
12
|
+
console.error(colorize('Error loading affected-packages.json:', 'red'), error);
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { loadAffectedPackages };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { checkAllAffectedPackages } = require('./commands/check');
|
|
4
|
+
const { checkSpecificPackage } = require('./commands/checkPackage');
|
|
5
|
+
const { listPackages } = require('./commands/list');
|
|
6
|
+
const { showHelp, showVersion } = require('./commands/help');
|
|
7
|
+
const { colorize } = require('./utils/colors');
|
|
8
|
+
|
|
9
|
+
// Parse command line arguments
|
|
10
|
+
const args = process.argv.slice(2);
|
|
11
|
+
const command = args[0] || 'check';
|
|
12
|
+
|
|
13
|
+
switch (command) {
|
|
14
|
+
case 'check':
|
|
15
|
+
checkAllAffectedPackages();
|
|
16
|
+
break;
|
|
17
|
+
|
|
18
|
+
case 'check-package':
|
|
19
|
+
if (args.length < 3) {
|
|
20
|
+
console.error(colorize("Error: check-package requires package name and version range", 'red'));
|
|
21
|
+
console.log("Usage: npm-breach-check check-package <package> <version-range>");
|
|
22
|
+
console.log("Examples:");
|
|
23
|
+
console.log(" npm-breach-check check-package jwt-decode '^2.2.0'");
|
|
24
|
+
console.log(" npm-breach-check check-package react '>=16.0.0'");
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
checkSpecificPackage(args[1], args[2]);
|
|
28
|
+
break;
|
|
29
|
+
|
|
30
|
+
case 'list':
|
|
31
|
+
listPackages();
|
|
32
|
+
break;
|
|
33
|
+
|
|
34
|
+
case 'help':
|
|
35
|
+
case '--help':
|
|
36
|
+
case '-h':
|
|
37
|
+
showHelp();
|
|
38
|
+
break;
|
|
39
|
+
|
|
40
|
+
case 'version':
|
|
41
|
+
case '--version':
|
|
42
|
+
case '-v':
|
|
43
|
+
showVersion();
|
|
44
|
+
break;
|
|
45
|
+
|
|
46
|
+
default:
|
|
47
|
+
console.error(colorize(`Error: Unknown command '${command}'`, 'red'));
|
|
48
|
+
console.log("Run 'npm-breach-check help' for usage information");
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const colors = {
|
|
2
|
+
reset: '\x1b[0m',
|
|
3
|
+
red: '\x1b[31m',
|
|
4
|
+
green: '\x1b[32m',
|
|
5
|
+
yellow: '\x1b[33m',
|
|
6
|
+
blue: '\x1b[34m',
|
|
7
|
+
cyan: '\x1b[36m',
|
|
8
|
+
gray: '\x1b[90m'
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function colorize(text, color) {
|
|
12
|
+
return `${colors[color]}${text}${colors.reset}`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
module.exports = { colors, colorize };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const { colorize } = require('./colors');
|
|
2
|
+
|
|
3
|
+
function printHeader() {
|
|
4
|
+
console.log(colorize("Checking affected npm packages:", 'blue'));
|
|
5
|
+
console.log(colorize("===============================================================", 'blue'));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function printSummary(summary) {
|
|
9
|
+
console.log(colorize(`\nSummary:`, 'cyan'));
|
|
10
|
+
console.log(colorize(` Total checked: ${summary.totalChecked}`, 'cyan'));
|
|
11
|
+
console.log(colorize(` Found: ${summary.foundCount}`, 'cyan'));
|
|
12
|
+
console.log(colorize(` Affected versions: ${summary.satisfiedCount}`, 'red'));
|
|
13
|
+
console.log(colorize(` Used but not affected: ${summary.foundCount - summary.satisfiedCount}`, 'gray'));
|
|
14
|
+
// console.log(colorize(` Not used in the project: ${summary.totalChecked - summary.foundCount}`, 'green'));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function printSatisfiedPackages(packages) {
|
|
18
|
+
if (packages.length > 0) {
|
|
19
|
+
console.log(colorize(`\nAffected versions:`, 'red'));
|
|
20
|
+
console.log(colorize("==================", 'red'));
|
|
21
|
+
for (const pkg of packages) {
|
|
22
|
+
console.log(colorize(` ✓ ${pkg}`, 'red'));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function printAffectedPackages(packages) {
|
|
28
|
+
if (packages.length > 0) {
|
|
29
|
+
console.log(colorize(`\nUsed but not affected:`, 'gray'));
|
|
30
|
+
console.log(colorize("======================", 'gray'));
|
|
31
|
+
for (const pkg of packages) {
|
|
32
|
+
console.log(colorize(` ⚠ ${pkg}`, 'gray'));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = { printHeader, printSummary, printSatisfiedPackages, printAffectedPackages };
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@npm-breach/check",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Security-focused CLI tool to detect potentially vulnerable packages in your Node.js applications",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"npm-breach-check": "./lib/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node lib/index.js",
|
|
11
|
+
"test": "echo \"No tests configured for plain JavaScript version\" && exit 0"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"security",
|
|
15
|
+
"vulnerability",
|
|
16
|
+
"scanner",
|
|
17
|
+
"cli",
|
|
18
|
+
"npm",
|
|
19
|
+
"package-checker",
|
|
20
|
+
"dependency-tree",
|
|
21
|
+
"breach",
|
|
22
|
+
"audit"
|
|
23
|
+
],
|
|
24
|
+
"author": "Your Name",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "https://github.com/labidiaymen/npm-breach.git"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/labidiaymen/npm-breach#readme",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/labidiaymen/npm-breach/issues"
|
|
33
|
+
},
|
|
34
|
+
"preferGlobal": true,
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"semver": "^7.5.0"
|
|
37
|
+
}
|
|
38
|
+
}
|