@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 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
+ }