logshield-cli 0.4.0 → 0.4.1
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/CHANGELOG.md +18 -2
- package/dist/cli/index.cjs +39 -13
- package/package.json +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.4.1
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Prevented secret leakage in `--json` output by removing raw match values from the public result shape
|
|
8
|
+
- Forwarded `--dry-run` into the engine to ensure consistent, future-proof behavior
|
|
9
|
+
|
|
10
|
+
### Improved
|
|
11
|
+
|
|
12
|
+
- Expanded credential detection for common API key variants (`api_key`, `api-key`, `apikey`) and `Authorization: Bearer ...`
|
|
13
|
+
- Hardened AWS secret key strict detection to reduce false positives while keeping strict mode safe
|
|
14
|
+
|
|
15
|
+
### Notes
|
|
16
|
+
|
|
17
|
+
- No breaking changes
|
|
18
|
+
- No new features
|
|
19
|
+
- Stability and safety hardening release
|
|
20
|
+
|
|
3
21
|
## v0.4.0
|
|
4
22
|
|
|
5
23
|
### Changed
|
|
@@ -21,8 +39,6 @@
|
|
|
21
39
|
### Improved
|
|
22
40
|
|
|
23
41
|
- CLI documentation clarity
|
|
24
|
-
- Blog and docs structure consistency
|
|
25
|
-
- Shared `styles.css` and `main.js` across site pages
|
|
26
42
|
|
|
27
43
|
### Notes
|
|
28
44
|
|
package/dist/cli/index.cjs
CHANGED
|
@@ -126,8 +126,7 @@ function applyRules(input, rules, ctx, matches) {
|
|
|
126
126
|
const replaced = rule.replace(match, ctx, groups);
|
|
127
127
|
if (replaced !== match) {
|
|
128
128
|
matches.push({
|
|
129
|
-
rule: rule.name
|
|
130
|
-
value: match
|
|
129
|
+
rule: rule.name
|
|
131
130
|
});
|
|
132
131
|
}
|
|
133
132
|
if (ctx.dryRun) {
|
|
@@ -197,9 +196,10 @@ var credentialRules;
|
|
|
197
196
|
var init_credentials = __esm({
|
|
198
197
|
"src/rules/credentials.ts"() {
|
|
199
198
|
credentialRules = [
|
|
199
|
+
// password=... or password: ...
|
|
200
200
|
{
|
|
201
201
|
name: "PASSWORD",
|
|
202
|
-
pattern: /\bpassword
|
|
202
|
+
pattern: /\bpassword\s*[:=]\s*([^\s]+)/gi,
|
|
203
203
|
replace: () => "password=<REDACTED_PASSWORD>"
|
|
204
204
|
},
|
|
205
205
|
// DB URL credential: postgres://user:pass@host
|
|
@@ -208,17 +208,30 @@ var init_credentials = __esm({
|
|
|
208
208
|
pattern: /\b(postgres|mysql|mongodb):\/\/([^:\s]+):([^@\s]+)@/gi,
|
|
209
209
|
replace: (_match, _ctx, groups) => `${groups[0]}://${groups[1]}:<REDACTED_PASSWORD>@`
|
|
210
210
|
},
|
|
211
|
-
|
|
211
|
+
/**
|
|
212
|
+
* API key (common variants):
|
|
213
|
+
* - apiKey=...
|
|
214
|
+
* - api_key=...
|
|
215
|
+
* - api-key: ...
|
|
216
|
+
* - apikey=...
|
|
217
|
+
* Supports '=' or ':' and optional quotes/spaces.
|
|
218
|
+
*/
|
|
212
219
|
{
|
|
213
220
|
name: "API_KEY",
|
|
214
|
-
pattern: /\
|
|
221
|
+
pattern: /\bapi(?:[_-]?key)\s*[:=]\s*["']?([A-Za-z0-9_\-]{16,})["']?\b/gi,
|
|
215
222
|
replace: () => "<REDACTED_API_KEY>"
|
|
216
223
|
},
|
|
217
224
|
// x-api-key: ....
|
|
218
225
|
{
|
|
219
226
|
name: "API_KEY_HEADER",
|
|
220
|
-
pattern: /\bx-api-key
|
|
227
|
+
pattern: /\bx-api-key\s*:\s*["']?[A-Za-z0-9_\-]{16,}["']?\b/gi,
|
|
221
228
|
replace: () => "x-api-key: <REDACTED_API_KEY>"
|
|
229
|
+
},
|
|
230
|
+
// authorization: Bearer ...
|
|
231
|
+
{
|
|
232
|
+
name: "AUTHORIZATION_BEARER",
|
|
233
|
+
pattern: /\bauthorization\s*:\s*bearer\s+([A-Za-z0-9._\-]{16,})\b/gi,
|
|
234
|
+
replace: () => "authorization: Bearer <REDACTED_TOKEN>"
|
|
222
235
|
}
|
|
223
236
|
];
|
|
224
237
|
}
|
|
@@ -234,9 +247,24 @@ var init_cloud = __esm({
|
|
|
234
247
|
pattern: /\bAKIA[0-9A-Z]{16,20}\b/g,
|
|
235
248
|
replace: (match, { strict }) => strict ? "<REDACTED_AWS_KEY>" : match
|
|
236
249
|
},
|
|
250
|
+
/**
|
|
251
|
+
* Prefer contextual AWS secret key detection first:
|
|
252
|
+
* - AWS_SECRET_ACCESS_KEY=...
|
|
253
|
+
* - aws_secret_access_key: ...
|
|
254
|
+
* - secretAccessKey=...
|
|
255
|
+
*/
|
|
256
|
+
{
|
|
257
|
+
name: "AWS_SECRET_ACCESS_KEY",
|
|
258
|
+
pattern: /\b(?:AWS_SECRET_ACCESS_KEY|aws_secret_access_key|secretAccessKey|awsSecretAccessKey)\s*[:=]\s*["']?([A-Za-z0-9\/+=]{40})["']?\b/g,
|
|
259
|
+
replace: (_match, { strict }, groups) => strict ? "<REDACTED_AWS_SECRET>" : _match.replace(groups[0], "<REDACTED_AWS_SECRET>")
|
|
260
|
+
},
|
|
261
|
+
/**
|
|
262
|
+
* Strict-only broad fallback, but require at least one of / + = inside the 40 chars
|
|
263
|
+
* to reduce false positives on purely alphanumeric 40-char strings.
|
|
264
|
+
*/
|
|
237
265
|
{
|
|
238
266
|
name: "AWS_SECRET_KEY",
|
|
239
|
-
pattern: /\b[A-Za-z0-9\/+=]{40}\b/g,
|
|
267
|
+
pattern: /\b(?=[A-Za-z0-9\/+=]{40}\b)(?=[A-Za-z0-9\/+=]*[\/+=])[A-Za-z0-9\/+=]{40}\b/g,
|
|
240
268
|
replace: (match, { strict }) => strict ? "<REDACTED_AWS_SECRET>" : match
|
|
241
269
|
},
|
|
242
270
|
{
|
|
@@ -389,7 +417,7 @@ var { printSummary: printSummary2 } = (init_summary(), __toCommonJS(summary_expo
|
|
|
389
417
|
var { sanitizeLog: sanitizeLog2 } = (init_sanitizeLog(), __toCommonJS(sanitizeLog_exports));
|
|
390
418
|
var rawArgs = process.argv.slice(2).map((arg) => arg === "-h" ? "--help" : arg);
|
|
391
419
|
function getVersion() {
|
|
392
|
-
return true ? "0.4.
|
|
420
|
+
return true ? "0.4.1" : "unknown";
|
|
393
421
|
}
|
|
394
422
|
function printHelp() {
|
|
395
423
|
process.stdout.write(`Usage: logshield scan [file]
|
|
@@ -447,10 +475,8 @@ function renderDryRunReport(matches) {
|
|
|
447
475
|
process.stdout.write(`Detected ${total} ${label}:
|
|
448
476
|
`);
|
|
449
477
|
for (const { rule, count } of entries) {
|
|
450
|
-
process.stdout.write(
|
|
451
|
-
|
|
452
|
-
`
|
|
453
|
-
);
|
|
478
|
+
process.stdout.write(` ${rule.padEnd(maxLen)} x${count}
|
|
479
|
+
`);
|
|
454
480
|
}
|
|
455
481
|
process.stdout.write("\n");
|
|
456
482
|
process.stdout.write("No output was modified.\n");
|
|
@@ -495,7 +521,7 @@ async function main() {
|
|
|
495
521
|
}
|
|
496
522
|
try {
|
|
497
523
|
const input = await readInput2(useStdin ? void 0 : file);
|
|
498
|
-
const result = sanitizeLog2(input, { strict });
|
|
524
|
+
const result = sanitizeLog2(input, { strict, dryRun });
|
|
499
525
|
if (dryRun) {
|
|
500
526
|
renderDryRunReport(result.matches);
|
|
501
527
|
if (failOnDetect && result.matches.length > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "logshield-cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"build:web": "vite build --outDir dist-web",
|
|
18
18
|
"build:blog": "node scripts/build-blog.js",
|
|
19
19
|
"dev:web": "vite",
|
|
20
|
+
"typecheck": "tsc -p tsconfig.core.json && tsc -p tsconfig.cli.json --noEmit",
|
|
20
21
|
"pretest": "npm run build",
|
|
21
22
|
"test": "vitest",
|
|
22
23
|
"prepublishOnly": "npm run build"
|
|
@@ -27,6 +28,7 @@
|
|
|
27
28
|
"esbuild": "^0.25.0",
|
|
28
29
|
"postcss": "^8.5.6",
|
|
29
30
|
"tailwindcss": "^3.4.19",
|
|
31
|
+
"typescript": "^5.9.3",
|
|
30
32
|
"vitest": "^4.0.0"
|
|
31
33
|
}
|
|
32
34
|
}
|