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 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
 
@@ -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=([^\s]+)/gi,
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
- // apiKey=...
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: /\bapiKey=([A-Za-z0-9_\-]{16,})\b/g,
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:\s*[A-Za-z0-9_\-]{16,}\b/gi,
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.0" : "unknown";
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
- ` ${rule.padEnd(maxLen)} x${count}
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.0",
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
  }