logshield-cli 0.1.0 → 0.2.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/dist/android-chrome-192x192.png +0 -0
- package/dist/android-chrome-512x512.png +0 -0
- package/dist/apple-touch-icon.png +0 -0
- package/dist/assets/index-B3qxIuiz.css +1 -0
- package/dist/assets/index-DDJ1Wxio.js +29 -0
- package/dist/cli/index.cjs +402 -0
- package/dist/favicon-16x16.png +0 -0
- package/dist/favicon-32x32.png +0 -0
- package/dist/favicon.ico +0 -0
- package/dist/features.jsx +462 -0
- package/dist/index.html +16 -0
- package/dist/privacy.html +217 -0
- package/dist/refund.html +221 -0
- package/dist/robots.txt +4 -0
- package/dist/site.webmanifest +20 -0
- package/dist/terms.html +140 -0
- package/dist/utils/luhn.js +16 -0
- package/dist/vite.svg +1 -0
- package/package.json +7 -11
- package/dist/cli/cli/index.cjs +0 -54
- package/dist/cli/cli/index.js +0 -57
- package/dist/cli/cli/readInput.js +0 -27
- package/dist/cli/cli/summary.js +0 -13
- package/dist/cli/cli/writeOutput.js +0 -11
- package/dist/cli/index.js +0 -52
- package/dist/cli/package.json +0 -3
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
"use strict";
|
|
4
|
+
var __create = Object.create;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
8
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
9
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
10
|
+
var __esm = (fn, res) => function __init() {
|
|
11
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
|
+
};
|
|
13
|
+
var __export = (target, all) => {
|
|
14
|
+
for (var name in all)
|
|
15
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
|
+
};
|
|
17
|
+
var __copyProps = (to, from, except, desc) => {
|
|
18
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
19
|
+
for (let key of __getOwnPropNames(from))
|
|
20
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
21
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
22
|
+
}
|
|
23
|
+
return to;
|
|
24
|
+
};
|
|
25
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
26
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
27
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
28
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
29
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
30
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
31
|
+
mod
|
|
32
|
+
));
|
|
33
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
34
|
+
|
|
35
|
+
// src/cli/readInput.ts
|
|
36
|
+
var readInput_exports = {};
|
|
37
|
+
__export(readInput_exports, {
|
|
38
|
+
readInput: () => readInput
|
|
39
|
+
});
|
|
40
|
+
async function readInput(file) {
|
|
41
|
+
if (file) {
|
|
42
|
+
if (!import_node_fs.default.existsSync(file)) {
|
|
43
|
+
throw new Error(`File not found: ${file}`);
|
|
44
|
+
}
|
|
45
|
+
return import_node_fs.default.readFileSync(file, "utf8");
|
|
46
|
+
}
|
|
47
|
+
if (!process.stdin.isTTY) {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
let data = "";
|
|
50
|
+
process.stdin.setEncoding("utf8");
|
|
51
|
+
process.stdin.on("data", (chunk) => {
|
|
52
|
+
data += chunk;
|
|
53
|
+
});
|
|
54
|
+
process.stdin.on("end", () => resolve(data));
|
|
55
|
+
process.stdin.on("error", reject);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
throw new Error("No input provided");
|
|
59
|
+
}
|
|
60
|
+
var import_node_fs;
|
|
61
|
+
var init_readInput = __esm({
|
|
62
|
+
"src/cli/readInput.ts"() {
|
|
63
|
+
"use strict";
|
|
64
|
+
import_node_fs = __toESM(require("node:fs"));
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// src/cli/writeOutput.ts
|
|
69
|
+
var writeOutput_exports = {};
|
|
70
|
+
__export(writeOutput_exports, {
|
|
71
|
+
writeOutput: () => writeOutput
|
|
72
|
+
});
|
|
73
|
+
function writeOutput(result, opts) {
|
|
74
|
+
if (opts.json) {
|
|
75
|
+
process.stdout.write(JSON.stringify(result));
|
|
76
|
+
} else {
|
|
77
|
+
process.stdout.write(result.output);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
var init_writeOutput = __esm({
|
|
81
|
+
"src/cli/writeOutput.ts"() {
|
|
82
|
+
"use strict";
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// src/cli/summary.ts
|
|
87
|
+
var summary_exports = {};
|
|
88
|
+
__export(summary_exports, {
|
|
89
|
+
printSummary: () => printSummary
|
|
90
|
+
});
|
|
91
|
+
function printSummary(matches) {
|
|
92
|
+
const counter = {};
|
|
93
|
+
for (const m of matches) {
|
|
94
|
+
counter[m.rule] = (counter[m.rule] || 0) + 1;
|
|
95
|
+
}
|
|
96
|
+
process.stderr.write("LogShield Summary\n");
|
|
97
|
+
for (const [rule, count] of Object.entries(counter)) {
|
|
98
|
+
process.stderr.write(`${rule}: ${count}
|
|
99
|
+
`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
var init_summary = __esm({
|
|
103
|
+
"src/cli/summary.ts"() {
|
|
104
|
+
"use strict";
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// src/engine/applyRules.ts
|
|
109
|
+
function applyRules(input, rules, ctx, matches) {
|
|
110
|
+
let output = input;
|
|
111
|
+
for (const rule of rules) {
|
|
112
|
+
output = output.replace(rule.pattern, (...args2) => {
|
|
113
|
+
const match = args2[0];
|
|
114
|
+
const groups = args2.slice(1, -2);
|
|
115
|
+
const replaced = rule.replace(match, ctx, groups);
|
|
116
|
+
if (replaced !== match) {
|
|
117
|
+
matches.push({
|
|
118
|
+
rule: rule.name,
|
|
119
|
+
value: match
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return replaced;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
return output;
|
|
126
|
+
}
|
|
127
|
+
var init_applyRules = __esm({
|
|
128
|
+
"src/engine/applyRules.ts"() {
|
|
129
|
+
"use strict";
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// src/engine/guard.ts
|
|
134
|
+
function guardInput(input) {
|
|
135
|
+
if (!input) return "";
|
|
136
|
+
if (input.length > MAX_SIZE) {
|
|
137
|
+
throw new Error("Log size exceeds 200KB limit");
|
|
138
|
+
}
|
|
139
|
+
return input;
|
|
140
|
+
}
|
|
141
|
+
var MAX_SIZE;
|
|
142
|
+
var init_guard = __esm({
|
|
143
|
+
"src/engine/guard.ts"() {
|
|
144
|
+
"use strict";
|
|
145
|
+
MAX_SIZE = 200 * 1024;
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// src/rules/tokens.ts
|
|
150
|
+
var tokenRules;
|
|
151
|
+
var init_tokens = __esm({
|
|
152
|
+
"src/rules/tokens.ts"() {
|
|
153
|
+
"use strict";
|
|
154
|
+
tokenRules = [
|
|
155
|
+
{
|
|
156
|
+
name: "JWT",
|
|
157
|
+
pattern: /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\b/g,
|
|
158
|
+
replace: () => "<REDACTED_JWT>"
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: "AUTH_BEARER",
|
|
162
|
+
pattern: /\bBearer\s+[A-Za-z0-9._-]+\b/g,
|
|
163
|
+
replace: () => "Bearer <REDACTED_TOKEN>"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: "EMAIL",
|
|
167
|
+
pattern: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi,
|
|
168
|
+
replace: () => "<REDACTED_EMAIL>"
|
|
169
|
+
}
|
|
170
|
+
];
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// src/rules/credentials.ts
|
|
175
|
+
var credentialRules;
|
|
176
|
+
var init_credentials = __esm({
|
|
177
|
+
"src/rules/credentials.ts"() {
|
|
178
|
+
"use strict";
|
|
179
|
+
credentialRules = [
|
|
180
|
+
{
|
|
181
|
+
name: "PASSWORD",
|
|
182
|
+
pattern: /\bpassword=([^\s]+)/gi,
|
|
183
|
+
replace: (_match, _value, _ctx) => "password=<REDACTED_PASSWORD>"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
name: "API_KEY",
|
|
187
|
+
pattern: /\bapiKey=([A-Za-z0-9_\-]{16,})\b/g,
|
|
188
|
+
replace: () => "<REDACTED_API_KEY>"
|
|
189
|
+
}
|
|
190
|
+
];
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// src/rules/cloud.ts
|
|
195
|
+
var cloudRules;
|
|
196
|
+
var init_cloud = __esm({
|
|
197
|
+
"src/rules/cloud.ts"() {
|
|
198
|
+
"use strict";
|
|
199
|
+
cloudRules = [
|
|
200
|
+
{
|
|
201
|
+
name: "AWS_ACCESS_KEY",
|
|
202
|
+
pattern: /\bAKIA[0-9A-Z]{16,20}\b/g,
|
|
203
|
+
replace: (match, { strict }) => strict ? "<REDACTED_AWS_KEY>" : match
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
name: "STRIPE_SECRET_KEY",
|
|
207
|
+
pattern: /\b(?:LS_STRIPE_(?:TEST|LIVE)_KEY_[A-Z0-9_]{10,}|sk_(?:test|live)_[A-Za-z0-9]{16,})\b/g,
|
|
208
|
+
replace: (match, ctx) => ctx.strict ? "<REDACTED_STRIPE_KEY>" : match
|
|
209
|
+
}
|
|
210
|
+
];
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// src/utils/luhn.ts
|
|
215
|
+
function isValidLuhn(input) {
|
|
216
|
+
const digits = input.replace(/\D/g, "");
|
|
217
|
+
let sum = 0;
|
|
218
|
+
let alt = false;
|
|
219
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
220
|
+
let n = parseInt(digits[i], 10);
|
|
221
|
+
if (alt) {
|
|
222
|
+
n *= 2;
|
|
223
|
+
if (n > 9) n -= 9;
|
|
224
|
+
}
|
|
225
|
+
sum += n;
|
|
226
|
+
alt = !alt;
|
|
227
|
+
}
|
|
228
|
+
return sum % 10 === 0;
|
|
229
|
+
}
|
|
230
|
+
var init_luhn = __esm({
|
|
231
|
+
"src/utils/luhn.ts"() {
|
|
232
|
+
"use strict";
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// src/rules/creditCard.ts
|
|
237
|
+
var creditCardRules;
|
|
238
|
+
var init_creditCard = __esm({
|
|
239
|
+
"src/rules/creditCard.ts"() {
|
|
240
|
+
"use strict";
|
|
241
|
+
init_luhn();
|
|
242
|
+
creditCardRules = [
|
|
243
|
+
{
|
|
244
|
+
name: "CREDIT_CARD",
|
|
245
|
+
pattern: /\b(?:\d[ -]*?){13,19}\b/g,
|
|
246
|
+
replace: (match, { strict }) => {
|
|
247
|
+
if (!strict) return match;
|
|
248
|
+
return isValidLuhn(match) ? "<REDACTED_CC>" : match;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
];
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// src/rules/urls.ts
|
|
256
|
+
var urlRules;
|
|
257
|
+
var init_urls = __esm({
|
|
258
|
+
"src/rules/urls.ts"() {
|
|
259
|
+
"use strict";
|
|
260
|
+
urlRules = [
|
|
261
|
+
{
|
|
262
|
+
name: "URL",
|
|
263
|
+
pattern: /\bhttps?:\/\/[^\s/$.?#].[^\s]*\b/gi,
|
|
264
|
+
replace: () => "<REDACTED_URL>"
|
|
265
|
+
}
|
|
266
|
+
];
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// src/rules/custom.ts
|
|
271
|
+
var customRules;
|
|
272
|
+
var init_custom = __esm({
|
|
273
|
+
"src/rules/custom.ts"() {
|
|
274
|
+
"use strict";
|
|
275
|
+
customRules = [
|
|
276
|
+
{
|
|
277
|
+
name: "GENERIC_SECRET_KV",
|
|
278
|
+
pattern: /"(\w+)":"([^"]{12,})"/g,
|
|
279
|
+
replace: (match, ctx, groups) => {
|
|
280
|
+
if (!ctx.strict) return match;
|
|
281
|
+
const key = groups[0] ?? "token";
|
|
282
|
+
return `"${key}":"<REDACTED_SECRET>"`;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
];
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// src/rules/index.ts
|
|
290
|
+
function normalize(rules) {
|
|
291
|
+
return rules.map((rule) => {
|
|
292
|
+
if (typeof rule.replace === "function") {
|
|
293
|
+
return rule;
|
|
294
|
+
}
|
|
295
|
+
const value = rule.replace;
|
|
296
|
+
return {
|
|
297
|
+
...rule,
|
|
298
|
+
replace: () => value
|
|
299
|
+
};
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
var allRules;
|
|
303
|
+
var init_rules = __esm({
|
|
304
|
+
"src/rules/index.ts"() {
|
|
305
|
+
"use strict";
|
|
306
|
+
init_tokens();
|
|
307
|
+
init_credentials();
|
|
308
|
+
init_cloud();
|
|
309
|
+
init_creditCard();
|
|
310
|
+
init_urls();
|
|
311
|
+
init_custom();
|
|
312
|
+
allRules = normalize([
|
|
313
|
+
...tokenRules,
|
|
314
|
+
...credentialRules,
|
|
315
|
+
...cloudRules,
|
|
316
|
+
...creditCardRules,
|
|
317
|
+
...urlRules,
|
|
318
|
+
...customRules
|
|
319
|
+
]);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// src/engine/sanitizeLog.ts
|
|
324
|
+
var sanitizeLog_exports = {};
|
|
325
|
+
__export(sanitizeLog_exports, {
|
|
326
|
+
sanitizeLog: () => sanitizeLog
|
|
327
|
+
});
|
|
328
|
+
function sanitizeLog(input, options) {
|
|
329
|
+
guardInput(input);
|
|
330
|
+
if (!input) {
|
|
331
|
+
return { output: "", matches: [] };
|
|
332
|
+
}
|
|
333
|
+
const ctx = {
|
|
334
|
+
strict: Boolean(options?.strict)
|
|
335
|
+
};
|
|
336
|
+
const matches = [];
|
|
337
|
+
const output = applyRules(input, allRules, ctx, matches);
|
|
338
|
+
return { output, matches };
|
|
339
|
+
}
|
|
340
|
+
var init_sanitizeLog = __esm({
|
|
341
|
+
"src/engine/sanitizeLog.ts"() {
|
|
342
|
+
"use strict";
|
|
343
|
+
init_applyRules();
|
|
344
|
+
init_guard();
|
|
345
|
+
init_rules();
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
// src/cli/index.ts
|
|
350
|
+
var { readInput: readInput2 } = (init_readInput(), __toCommonJS(readInput_exports));
|
|
351
|
+
var { writeOutput: writeOutput2 } = (init_writeOutput(), __toCommonJS(writeOutput_exports));
|
|
352
|
+
var { printSummary: printSummary2 } = (init_summary(), __toCommonJS(summary_exports));
|
|
353
|
+
var { sanitizeLog: sanitizeLog2 } = (init_sanitizeLog(), __toCommonJS(sanitizeLog_exports));
|
|
354
|
+
var args = process.argv.slice(2);
|
|
355
|
+
function hasFlag(flag) {
|
|
356
|
+
return args.includes(flag);
|
|
357
|
+
}
|
|
358
|
+
function getFileArg() {
|
|
359
|
+
const file = args[1];
|
|
360
|
+
if (!file || file.startsWith("--")) return void 0;
|
|
361
|
+
return file;
|
|
362
|
+
}
|
|
363
|
+
async function main() {
|
|
364
|
+
if (hasFlag("--help") || args.length === 0) {
|
|
365
|
+
process.stdout.write(`Usage: logshield scan [file]
|
|
366
|
+
|
|
367
|
+
Options:
|
|
368
|
+
--strict
|
|
369
|
+
--json
|
|
370
|
+
--summary
|
|
371
|
+
--version
|
|
372
|
+
--help
|
|
373
|
+
`);
|
|
374
|
+
process.exit(0);
|
|
375
|
+
}
|
|
376
|
+
if (hasFlag("--version")) {
|
|
377
|
+
process.stdout.write("logshield v0.2.0\n");
|
|
378
|
+
process.exit(0);
|
|
379
|
+
}
|
|
380
|
+
const command = args[0];
|
|
381
|
+
if (command !== "scan") {
|
|
382
|
+
process.stderr.write("Unknown command\n");
|
|
383
|
+
process.exit(1);
|
|
384
|
+
}
|
|
385
|
+
const strict = hasFlag("--strict");
|
|
386
|
+
const json = hasFlag("--json");
|
|
387
|
+
const summary = hasFlag("--summary");
|
|
388
|
+
const file = getFileArg();
|
|
389
|
+
try {
|
|
390
|
+
const input = await readInput2(file);
|
|
391
|
+
const result = sanitizeLog2(input, { strict });
|
|
392
|
+
writeOutput2(result, { json });
|
|
393
|
+
if (summary) {
|
|
394
|
+
printSummary2(result.matches);
|
|
395
|
+
}
|
|
396
|
+
} catch (err) {
|
|
397
|
+
process.stderr.write(err && err.message || "Unexpected error");
|
|
398
|
+
process.stderr.write("\n");
|
|
399
|
+
process.exit(2);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
main();
|
|
Binary file
|
|
Binary file
|
package/dist/favicon.ico
ADDED
|
Binary file
|