code-secret-handler 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/LICENSE +79 -0
- package/README.md +221 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +121 -0
- package/dist/cli.js.map +1 -0
- package/dist/env/envWriter.d.ts +9 -0
- package/dist/env/envWriter.d.ts.map +1 -0
- package/dist/env/envWriter.js +76 -0
- package/dist/env/envWriter.js.map +1 -0
- package/dist/env/keyNamer.d.ts +13 -0
- package/dist/env/keyNamer.d.ts.map +1 -0
- package/dist/env/keyNamer.js +33 -0
- package/dist/env/keyNamer.js.map +1 -0
- package/dist/interactive/confirm.d.ts +16 -0
- package/dist/interactive/confirm.d.ts.map +1 -0
- package/dist/interactive/confirm.js +72 -0
- package/dist/interactive/confirm.js.map +1 -0
- package/dist/license/gitContext.d.ts +16 -0
- package/dist/license/gitContext.d.ts.map +1 -0
- package/dist/license/gitContext.js +117 -0
- package/dist/license/gitContext.js.map +1 -0
- package/dist/license/licenseCheck.d.ts +22 -0
- package/dist/license/licenseCheck.d.ts.map +1 -0
- package/dist/license/licenseCheck.js +119 -0
- package/dist/license/licenseCheck.js.map +1 -0
- package/dist/license/telemetry.d.ts +17 -0
- package/dist/license/telemetry.d.ts.map +1 -0
- package/dist/license/telemetry.js +87 -0
- package/dist/license/telemetry.js.map +1 -0
- package/dist/reporter/console.d.ts +3 -0
- package/dist/reporter/console.d.ts.map +1 -0
- package/dist/reporter/console.js +96 -0
- package/dist/reporter/console.js.map +1 -0
- package/dist/reporter/csv.d.ts +6 -0
- package/dist/reporter/csv.d.ts.map +1 -0
- package/dist/reporter/csv.js +56 -0
- package/dist/reporter/csv.js.map +1 -0
- package/dist/reporter/index.d.ts +13 -0
- package/dist/reporter/index.d.ts.map +1 -0
- package/dist/reporter/index.js +52 -0
- package/dist/reporter/index.js.map +1 -0
- package/dist/reporter/json.d.ts +7 -0
- package/dist/reporter/json.d.ts.map +1 -0
- package/dist/reporter/json.js +39 -0
- package/dist/reporter/json.js.map +1 -0
- package/dist/reporter/markdown.d.ts +6 -0
- package/dist/reporter/markdown.d.ts.map +1 -0
- package/dist/reporter/markdown.js +106 -0
- package/dist/reporter/markdown.js.map +1 -0
- package/dist/rewriter/index.d.ts +9 -0
- package/dist/rewriter/index.d.ts.map +1 -0
- package/dist/rewriter/index.js +95 -0
- package/dist/rewriter/index.js.map +1 -0
- package/dist/rewriter/langDetector.d.ts +7 -0
- package/dist/rewriter/langDetector.d.ts.map +1 -0
- package/dist/rewriter/langDetector.js +96 -0
- package/dist/rewriter/langDetector.js.map +1 -0
- package/dist/rewriter/templates/csharp.d.ts +8 -0
- package/dist/rewriter/templates/csharp.d.ts.map +1 -0
- package/dist/rewriter/templates/csharp.js +36 -0
- package/dist/rewriter/templates/csharp.js.map +1 -0
- package/dist/rewriter/templates/generic.d.ts +7 -0
- package/dist/rewriter/templates/generic.d.ts.map +1 -0
- package/dist/rewriter/templates/generic.js +40 -0
- package/dist/rewriter/templates/generic.js.map +1 -0
- package/dist/rewriter/templates/go.d.ts +8 -0
- package/dist/rewriter/templates/go.d.ts.map +1 -0
- package/dist/rewriter/templates/go.js +56 -0
- package/dist/rewriter/templates/go.js.map +1 -0
- package/dist/rewriter/templates/java.d.ts +7 -0
- package/dist/rewriter/templates/java.d.ts.map +1 -0
- package/dist/rewriter/templates/java.js +31 -0
- package/dist/rewriter/templates/java.js.map +1 -0
- package/dist/rewriter/templates/javascript.d.ts +10 -0
- package/dist/rewriter/templates/javascript.d.ts.map +1 -0
- package/dist/rewriter/templates/javascript.js +54 -0
- package/dist/rewriter/templates/javascript.js.map +1 -0
- package/dist/rewriter/templates/php.d.ts +8 -0
- package/dist/rewriter/templates/php.d.ts.map +1 -0
- package/dist/rewriter/templates/php.js +41 -0
- package/dist/rewriter/templates/php.js.map +1 -0
- package/dist/rewriter/templates/properties.d.ts +9 -0
- package/dist/rewriter/templates/properties.d.ts.map +1 -0
- package/dist/rewriter/templates/properties.js +39 -0
- package/dist/rewriter/templates/properties.js.map +1 -0
- package/dist/rewriter/templates/python.d.ts +8 -0
- package/dist/rewriter/templates/python.d.ts.map +1 -0
- package/dist/rewriter/templates/python.js +48 -0
- package/dist/rewriter/templates/python.js.map +1 -0
- package/dist/rewriter/templates/ruby.d.ts +8 -0
- package/dist/rewriter/templates/ruby.d.ts.map +1 -0
- package/dist/rewriter/templates/ruby.js +40 -0
- package/dist/rewriter/templates/ruby.js.map +1 -0
- package/dist/rewriter/templates/rust.d.ts +7 -0
- package/dist/rewriter/templates/rust.d.ts.map +1 -0
- package/dist/rewriter/templates/rust.js +27 -0
- package/dist/rewriter/templates/rust.js.map +1 -0
- package/dist/rewriter/templates/shell.d.ts +7 -0
- package/dist/rewriter/templates/shell.d.ts.map +1 -0
- package/dist/rewriter/templates/shell.js +42 -0
- package/dist/rewriter/templates/shell.js.map +1 -0
- package/dist/rewriter/templates/toml.d.ts +9 -0
- package/dist/rewriter/templates/toml.d.ts.map +1 -0
- package/dist/rewriter/templates/toml.js +34 -0
- package/dist/rewriter/templates/toml.js.map +1 -0
- package/dist/rewriter/templates/yaml.d.ts +8 -0
- package/dist/rewriter/templates/yaml.d.ts.map +1 -0
- package/dist/rewriter/templates/yaml.js +37 -0
- package/dist/rewriter/templates/yaml.js.map +1 -0
- package/dist/scanner/detector.d.ts +18 -0
- package/dist/scanner/detector.d.ts.map +1 -0
- package/dist/scanner/detector.js +156 -0
- package/dist/scanner/detector.js.map +1 -0
- package/dist/scanner/fileWalker.d.ts +6 -0
- package/dist/scanner/fileWalker.d.ts.map +1 -0
- package/dist/scanner/fileWalker.js +146 -0
- package/dist/scanner/fileWalker.js.map +1 -0
- package/dist/scanner/index.d.ts +8 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +74 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/scanner/rules/aws.d.ts +6 -0
- package/dist/scanner/rules/aws.d.ts.map +1 -0
- package/dist/scanner/rules/aws.js +90 -0
- package/dist/scanner/rules/aws.js.map +1 -0
- package/dist/scanner/rules/azure.d.ts +6 -0
- package/dist/scanner/rules/azure.d.ts.map +1 -0
- package/dist/scanner/rules/azure.js +86 -0
- package/dist/scanner/rules/azure.js.map +1 -0
- package/dist/scanner/rules/cloud.d.ts +11 -0
- package/dist/scanner/rules/cloud.d.ts.map +1 -0
- package/dist/scanner/rules/cloud.js +1066 -0
- package/dist/scanner/rules/cloud.js.map +1 -0
- package/dist/scanner/rules/database.d.ts +6 -0
- package/dist/scanner/rules/database.d.ts.map +1 -0
- package/dist/scanner/rules/database.js +283 -0
- package/dist/scanner/rules/database.js.map +1 -0
- package/dist/scanner/rules/gcp.d.ts +6 -0
- package/dist/scanner/rules/gcp.d.ts.map +1 -0
- package/dist/scanner/rules/gcp.js +108 -0
- package/dist/scanner/rules/gcp.js.map +1 -0
- package/dist/scanner/rules/generic.d.ts +13 -0
- package/dist/scanner/rules/generic.d.ts.map +1 -0
- package/dist/scanner/rules/generic.js +305 -0
- package/dist/scanner/rules/generic.js.map +1 -0
- package/dist/scanner/rules/index.d.ts +18 -0
- package/dist/scanner/rules/index.d.ts.map +1 -0
- package/dist/scanner/rules/index.js +40 -0
- package/dist/scanner/rules/index.js.map +1 -0
- package/dist/scanner/rules/jwt.d.ts +6 -0
- package/dist/scanner/rules/jwt.d.ts.map +1 -0
- package/dist/scanner/rules/jwt.js +97 -0
- package/dist/scanner/rules/jwt.js.map +1 -0
- package/dist/scanner/rules/network.d.ts +7 -0
- package/dist/scanner/rules/network.d.ts.map +1 -0
- package/dist/scanner/rules/network.js +166 -0
- package/dist/scanner/rules/network.js.map +1 -0
- package/dist/scanner/rules/privateKey.d.ts +6 -0
- package/dist/scanner/rules/privateKey.d.ts.map +1 -0
- package/dist/scanner/rules/privateKey.js +60 -0
- package/dist/scanner/rules/privateKey.js.map +1 -0
- package/dist/scanner/rules/ssh.d.ts +6 -0
- package/dist/scanner/rules/ssh.d.ts.map +1 -0
- package/dist/scanner/rules/ssh.js +49 -0
- package/dist/scanner/rules/ssh.js.map +1 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rewriteToml = rewriteToml;
|
|
4
|
+
/**
|
|
5
|
+
* Rewrites TOML files:
|
|
6
|
+
* - Replaces literal secret with a reference comment and env var placeholder.
|
|
7
|
+
* - TOML does not support env var interpolation natively, so we replace
|
|
8
|
+
* the value with "${KEY}" and add a guidance comment.
|
|
9
|
+
*/
|
|
10
|
+
function rewriteToml(ctx) {
|
|
11
|
+
const { finding, fileContent } = ctx;
|
|
12
|
+
const { rawValue, envKey } = finding;
|
|
13
|
+
let rewrittenContent = fileContent;
|
|
14
|
+
let replacements = 0;
|
|
15
|
+
const quoteStyles = ['"', "'"];
|
|
16
|
+
for (const q of quoteStyles) {
|
|
17
|
+
const escaped = rawValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
18
|
+
const re = new RegExp(`${q}${escaped}${q}`, 'g');
|
|
19
|
+
if (re.test(rewrittenContent)) {
|
|
20
|
+
// Replace with env var reference as a string — note: not all TOML loaders support this
|
|
21
|
+
rewrittenContent = rewrittenContent.replace(re, `"$\{${envKey}}" # Set ${envKey} in environment`);
|
|
22
|
+
replacements++;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
filePath: finding.file,
|
|
28
|
+
originalContent: fileContent,
|
|
29
|
+
rewrittenContent,
|
|
30
|
+
replacements,
|
|
31
|
+
dotenvInjected: false,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=toml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toml.js","sourceRoot":"","sources":["../../../src/rewriter/templates/toml.ts"],"names":[],"mappings":";;;AAEA;;;;;GAKG;AACH,qBAA4B,GAAmB;IAC7C,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC;IACrC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAErC,IAAI,gBAAgB,GAAG,WAAW,CAAC;IACnC,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QAChE,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACjD,IAAI,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC9B,uFAAuF;YACvF,gBAAgB,GAAG,gBAAgB,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,MAAM,aAAa,MAAM,iBAAiB,CAAC,CAAC;YACnG,YAAY,EAAE,CAAC;YACf,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,IAAI;QACtB,eAAe,EAAE,WAAW;QAC5B,gBAAgB;QAChB,YAAY;QACZ,cAAc,EAAE,KAAK;KACtB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { RewriteContext, RewriteResult } from '../../types';
|
|
2
|
+
/**
|
|
3
|
+
* Rewrites YAML files:
|
|
4
|
+
* - Replaces literal secret with `${KEY}` (shell-style substitution)
|
|
5
|
+
* - Adds a comment suggesting the use of an env-var substitution tool.
|
|
6
|
+
*/
|
|
7
|
+
export declare function rewriteYaml(ctx: RewriteContext): RewriteResult;
|
|
8
|
+
//# sourceMappingURL=yaml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml.d.ts","sourceRoot":"","sources":["../../../src/rewriter/templates/yaml.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5D;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,aAAa,CA+B9D"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rewriteYaml = rewriteYaml;
|
|
4
|
+
/**
|
|
5
|
+
* Rewrites YAML files:
|
|
6
|
+
* - Replaces literal secret with `${KEY}` (shell-style substitution)
|
|
7
|
+
* - Adds a comment suggesting the use of an env-var substitution tool.
|
|
8
|
+
*/
|
|
9
|
+
function rewriteYaml(ctx) {
|
|
10
|
+
const { finding, fileContent } = ctx;
|
|
11
|
+
const { rawValue, envKey } = finding;
|
|
12
|
+
let rewrittenContent = fileContent;
|
|
13
|
+
let replacements = 0;
|
|
14
|
+
const quoteStyles = ["'", '"', ''];
|
|
15
|
+
for (const q of quoteStyles) {
|
|
16
|
+
const escaped = rawValue.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
17
|
+
const re = new RegExp(`${q}${escaped}${q}`, 'g');
|
|
18
|
+
if (re.test(rewrittenContent)) {
|
|
19
|
+
rewrittenContent = rewrittenContent.replace(re, `\${${envKey}}`);
|
|
20
|
+
replacements++;
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (replacements > 0 && !/# env-var substitution/i.test(rewrittenContent)) {
|
|
25
|
+
rewrittenContent =
|
|
26
|
+
`# Note: Use envsubst, docker-compose, or a similar tool to substitute \${...} env vars.\n` +
|
|
27
|
+
rewrittenContent;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
filePath: finding.file,
|
|
31
|
+
originalContent: fileContent,
|
|
32
|
+
rewrittenContent,
|
|
33
|
+
replacements,
|
|
34
|
+
dotenvInjected: false,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=yaml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yaml.js","sourceRoot":"","sources":["../../../src/rewriter/templates/yaml.ts"],"names":[],"mappings":";;;AAEA;;;;GAIG;AACH,qBAA4B,GAAmB;IAC7C,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,GAAG,CAAC;IACrC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAErC,IAAI,gBAAgB,GAAG,WAAW,CAAC;IACnC,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACnC,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;QAChE,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QACjD,IAAI,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC9B,gBAAgB,GAAG,gBAAgB,CAAC,OAAO,CAAC,EAAE,EAAE,MAAM,MAAM,GAAG,CAAC,CAAC;YACjE,YAAY,EAAE,CAAC;YACf,MAAM;QACR,CAAC;IACH,CAAC;IAED,IAAI,YAAY,GAAG,CAAC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAC1E,gBAAgB;YACd,2FAA2F;gBAC3F,gBAAgB,CAAC;IACrB,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,IAAI;QACtB,eAAe,EAAE,WAAW;QAC5B,gBAAgB;QAChB,YAAY;QACZ,cAAc,EAAE,KAAK;KACtB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Finding, Rule } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Generates the env variable name for a finding using context from the line.
|
|
4
|
+
* Falls back to the rule's envKeyPrefix.
|
|
5
|
+
*/
|
|
6
|
+
export declare function generateEnvKeyBase(rule: Rule, lineContent: string, filePath: string): string;
|
|
7
|
+
/**
|
|
8
|
+
* Scans a single file for secrets using all rules.
|
|
9
|
+
* Returns a list of raw findings (envKey not yet deduplicated).
|
|
10
|
+
*/
|
|
11
|
+
export declare function scanFile(filePath: string): Finding[];
|
|
12
|
+
/**
|
|
13
|
+
* Deduplicates env keys across all findings.
|
|
14
|
+
* If two findings would share the same key, appends _2, _3, etc.
|
|
15
|
+
* Also accepts existing .env keys to avoid collisions with them.
|
|
16
|
+
*/
|
|
17
|
+
export declare function deduplicateEnvKeys(findings: Finding[], existingKeys: Set<string>): Finding[];
|
|
18
|
+
//# sourceMappingURL=detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector.d.ts","sourceRoot":"","sources":["../../src/scanner/detector.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAsDzC;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAoB5F;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CA4DpD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,EAAE,CAa5F"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateEnvKeyBase = generateEnvKeyBase;
|
|
7
|
+
exports.scanFile = scanFile;
|
|
8
|
+
exports.deduplicateEnvKeys = deduplicateEnvKeys;
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
const rules_1 = require("./rules");
|
|
12
|
+
/**
|
|
13
|
+
* Values that are commonly used as placeholder/example values — skip these.
|
|
14
|
+
*/
|
|
15
|
+
const PLACEHOLDER_PATTERNS = [
|
|
16
|
+
/^your[_-]/i,
|
|
17
|
+
/^xxx+$/i,
|
|
18
|
+
/^<.+>$/, // <YOUR_KEY>
|
|
19
|
+
/^\$\{.+\}$/, // ${MY_VAR}
|
|
20
|
+
/^\$[A-Z_]+$/, // $MY_VAR
|
|
21
|
+
/^process\.env\./,
|
|
22
|
+
/^os\.environ/,
|
|
23
|
+
/^ENV\[/,
|
|
24
|
+
/^System\.getenv/,
|
|
25
|
+
/^getenv\(/,
|
|
26
|
+
/^placeholder$/i,
|
|
27
|
+
/^changeme$/i,
|
|
28
|
+
/^change_me$/i,
|
|
29
|
+
/^replace_?me$/i,
|
|
30
|
+
/^todo$/i,
|
|
31
|
+
/^fixme$/i,
|
|
32
|
+
/^insert[_-]?here$/i,
|
|
33
|
+
/^example$/i,
|
|
34
|
+
/^test$/i,
|
|
35
|
+
/^dummy$/i,
|
|
36
|
+
/^fake$/i,
|
|
37
|
+
/^mock$/i,
|
|
38
|
+
/^secret$/i, // bare word "secret" — likely a placeholder
|
|
39
|
+
/^password$/i, // bare word "password"
|
|
40
|
+
/^12345+$/,
|
|
41
|
+
/^0{8,}$/,
|
|
42
|
+
/^1{8,}$/,
|
|
43
|
+
/^null$/i,
|
|
44
|
+
/^undefined$/i,
|
|
45
|
+
/^none$/i,
|
|
46
|
+
/^empty$/i,
|
|
47
|
+
/^n\/a$/i,
|
|
48
|
+
];
|
|
49
|
+
/**
|
|
50
|
+
* Minimum lengths for secret values to avoid false positives.
|
|
51
|
+
*/
|
|
52
|
+
const MIN_SECRET_LENGTH = 4;
|
|
53
|
+
/**
|
|
54
|
+
* Returns true if the value looks like a placeholder/template value.
|
|
55
|
+
*/
|
|
56
|
+
function isPlaceholder(value) {
|
|
57
|
+
if (value.length < MIN_SECRET_LENGTH)
|
|
58
|
+
return true;
|
|
59
|
+
return PLACEHOLDER_PATTERNS.some(p => p.test(value));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Generates the env variable name for a finding using context from the line.
|
|
63
|
+
* Falls back to the rule's envKeyPrefix.
|
|
64
|
+
*/
|
|
65
|
+
function generateEnvKeyBase(rule, lineContent, filePath) {
|
|
66
|
+
// Try to infer a more specific name from the variable name on the line
|
|
67
|
+
const assignmentMatch = lineContent.match(/(?:const|let|var|val|final|private|public|protected|static)?\s*([A-Za-z_][A-Za-z0-9_]*)\s*(?:[:=])/);
|
|
68
|
+
if (assignmentMatch) {
|
|
69
|
+
const varName = assignmentMatch[1]
|
|
70
|
+
.replace(/([a-z])([A-Z])/g, '$1_$2') // camelCase → snake_case
|
|
71
|
+
.toUpperCase();
|
|
72
|
+
// Only use var name if it looks meaningful and is not too generic
|
|
73
|
+
const genericNames = new Set(['VALUE', 'VAL', 'V', 'S', 'K', 'KEY', 'DATA', 'RESULT', 'RES', 'X', 'Y']);
|
|
74
|
+
if (!genericNames.has(varName) && varName.length > 2) {
|
|
75
|
+
return varName;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Fall back to the rule's prefix
|
|
79
|
+
return rule.envKeyPrefix;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Scans a single file for secrets using all rules.
|
|
83
|
+
* Returns a list of raw findings (envKey not yet deduplicated).
|
|
84
|
+
*/
|
|
85
|
+
function scanFile(filePath) {
|
|
86
|
+
let content;
|
|
87
|
+
try {
|
|
88
|
+
content = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// Binary or unreadable — skip
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
// Skip files larger than 5 MB
|
|
95
|
+
const stats = fs_1.default.statSync(filePath);
|
|
96
|
+
if (stats.size > 5 * 1024 * 1024)
|
|
97
|
+
return [];
|
|
98
|
+
const findings = [];
|
|
99
|
+
const lines = content.split('\n');
|
|
100
|
+
for (let lineIdx = 0; lineIdx < lines.length; lineIdx++) {
|
|
101
|
+
const lineContent = lines[lineIdx];
|
|
102
|
+
// Skip comment-only lines (best-effort)
|
|
103
|
+
const trimmed = lineContent.trim();
|
|
104
|
+
if (trimmed.startsWith('//') ||
|
|
105
|
+
trimmed.startsWith('#') ||
|
|
106
|
+
trimmed.startsWith('*') ||
|
|
107
|
+
trimmed.startsWith('/*') ||
|
|
108
|
+
trimmed.startsWith('<!--')) {
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
for (const rule of rules_1.ALL_RULES) {
|
|
112
|
+
// Reset lastIndex for global regexes
|
|
113
|
+
rule.pattern.lastIndex = 0;
|
|
114
|
+
const match = rule.pattern.exec(lineContent);
|
|
115
|
+
if (!match)
|
|
116
|
+
continue;
|
|
117
|
+
const rawValue = match[rule.valueGroup] ?? match[0];
|
|
118
|
+
if (!rawValue || isPlaceholder(rawValue))
|
|
119
|
+
continue;
|
|
120
|
+
const column = lineContent.indexOf(rawValue) + 1;
|
|
121
|
+
const envKey = generateEnvKeyBase(rule, lineContent, filePath);
|
|
122
|
+
findings.push({
|
|
123
|
+
file: path_1.default.resolve(filePath),
|
|
124
|
+
line: lineIdx + 1,
|
|
125
|
+
column,
|
|
126
|
+
rule,
|
|
127
|
+
rawValue,
|
|
128
|
+
lineContent,
|
|
129
|
+
envKey,
|
|
130
|
+
});
|
|
131
|
+
// Only match first rule per line to avoid duplicates
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return findings;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Deduplicates env keys across all findings.
|
|
139
|
+
* If two findings would share the same key, appends _2, _3, etc.
|
|
140
|
+
* Also accepts existing .env keys to avoid collisions with them.
|
|
141
|
+
*/
|
|
142
|
+
function deduplicateEnvKeys(findings, existingKeys) {
|
|
143
|
+
const usedKeys = new Set(existingKeys);
|
|
144
|
+
return findings.map(finding => {
|
|
145
|
+
let candidate = finding.envKey;
|
|
146
|
+
if (usedKeys.has(candidate)) {
|
|
147
|
+
let suffix = 2;
|
|
148
|
+
while (usedKeys.has(`${candidate}_${suffix}`))
|
|
149
|
+
suffix++;
|
|
150
|
+
candidate = `${candidate}_${suffix}`;
|
|
151
|
+
}
|
|
152
|
+
usedKeys.add(candidate);
|
|
153
|
+
return { ...finding, envKey: candidate };
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detector.js","sourceRoot":"","sources":["../../src/scanner/detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileWalker.d.ts","sourceRoot":"","sources":["../../src/scanner/fileWalker.ts"],"names":[],"mappings":"AAuHA;;;GAGG;AACH,wBAAsB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAqBpE"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.walkFiles = walkFiles;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const ignore_1 = __importDefault(require("ignore"));
|
|
10
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
11
|
+
/**
|
|
12
|
+
* File extensions we will attempt to scan for secrets.
|
|
13
|
+
* Binary and compiled files are excluded.
|
|
14
|
+
*/
|
|
15
|
+
const SCANNABLE_EXTENSIONS = new Set([
|
|
16
|
+
// Web / JS ecosystem
|
|
17
|
+
'.js', '.jsx', '.ts', '.tsx', '.mjs', '.cjs', '.vue', '.svelte',
|
|
18
|
+
// Config / env
|
|
19
|
+
'.env', '.env.local', '.env.development', '.env.staging', '.env.production',
|
|
20
|
+
'.json', '.jsonc', '.json5',
|
|
21
|
+
'.yaml', '.yml',
|
|
22
|
+
'.toml',
|
|
23
|
+
'.ini',
|
|
24
|
+
'.properties',
|
|
25
|
+
'.conf', '.config',
|
|
26
|
+
'.xml',
|
|
27
|
+
// Backend languages
|
|
28
|
+
'.py', '.rb', '.php', '.java', '.kt', '.kts', '.scala',
|
|
29
|
+
'.go', '.rs', '.cs', '.vb', '.fs', '.fsx',
|
|
30
|
+
'.cpp', '.c', '.h', '.hpp', '.cc',
|
|
31
|
+
'.swift', '.m', '.mm',
|
|
32
|
+
'.dart',
|
|
33
|
+
'.ex', '.exs', // Elixir
|
|
34
|
+
'.erl', '.hrl', // Erlang
|
|
35
|
+
'.clj', '.cljs', // Clojure
|
|
36
|
+
'.hs', '.lhs', // Haskell
|
|
37
|
+
'.lua',
|
|
38
|
+
'.pl', '.pm', // Perl
|
|
39
|
+
'.r', '.R', // R
|
|
40
|
+
// Shell / scripting
|
|
41
|
+
'.sh', '.bash', '.zsh', '.fish', '.ps1', '.psm1', '.bat', '.cmd',
|
|
42
|
+
// Infrastructure as code
|
|
43
|
+
'.tf', '.tfvars', // Terraform
|
|
44
|
+
'.hcl',
|
|
45
|
+
'.dockerfile',
|
|
46
|
+
// Misc
|
|
47
|
+
'.gradle', '.groovy',
|
|
48
|
+
'.sql',
|
|
49
|
+
'.graphql', '.gql',
|
|
50
|
+
'.proto',
|
|
51
|
+
'.md', '.mdx', '.txt', '.log',
|
|
52
|
+
]);
|
|
53
|
+
/**
|
|
54
|
+
* File names (without extension, or exact names) that should always be scanned.
|
|
55
|
+
*/
|
|
56
|
+
const SCANNABLE_FILENAMES = new Set([
|
|
57
|
+
'Dockerfile', 'docker-compose', 'docker-compose.yml', 'docker-compose.yaml',
|
|
58
|
+
'.env', '.envrc', 'Makefile', 'Procfile', 'Gemfile', 'Rakefile',
|
|
59
|
+
'.npmrc', '.yarnrc', '.pypirc', '.netrc', '.htpasswd',
|
|
60
|
+
]);
|
|
61
|
+
/**
|
|
62
|
+
* Patterns for paths that should always be excluded regardless of .gitignore.
|
|
63
|
+
*/
|
|
64
|
+
const ALWAYS_IGNORE_GLOBS = [
|
|
65
|
+
'**/node_modules/**',
|
|
66
|
+
'**/.git/**',
|
|
67
|
+
'**/dist/**',
|
|
68
|
+
'**/build/**',
|
|
69
|
+
'**/out/**',
|
|
70
|
+
'**/__pycache__/**',
|
|
71
|
+
'**/*.pyc',
|
|
72
|
+
'**/*.pyo',
|
|
73
|
+
'**/vendor/**',
|
|
74
|
+
'**/.yarn/**',
|
|
75
|
+
'**/.pnp.*',
|
|
76
|
+
'**/coverage/**',
|
|
77
|
+
'**/.nyc_output/**',
|
|
78
|
+
'**/*.min.js',
|
|
79
|
+
'**/*.min.css',
|
|
80
|
+
'**/*.map',
|
|
81
|
+
'**/*.lock', // package-lock.json, yarn.lock, etc.
|
|
82
|
+
'**/Cargo.lock',
|
|
83
|
+
'**/*.png', '**/*.jpg', '**/*.jpeg', '**/*.gif', '**/*.ico',
|
|
84
|
+
'**/*.svg', '**/*.webp', '**/*.avif',
|
|
85
|
+
'**/*.woff', '**/*.woff2', '**/*.ttf', '**/*.eot',
|
|
86
|
+
'**/*.pdf', '**/*.zip', '**/*.tar', '**/*.gz', '**/*.tgz',
|
|
87
|
+
'**/*.exe', '**/*.dll', '**/*.so', '**/*.dylib',
|
|
88
|
+
'**/*.jar', '**/*.war', '**/*.ear', '**/*.class',
|
|
89
|
+
'**/*.DS_Store',
|
|
90
|
+
];
|
|
91
|
+
/**
|
|
92
|
+
* Loads a .gitignore file from the given directory and returns an `ignore` instance.
|
|
93
|
+
*/
|
|
94
|
+
function loadGitIgnore(dir) {
|
|
95
|
+
const ig = (0, ignore_1.default)();
|
|
96
|
+
const gitignorePath = path_1.default.join(dir, '.gitignore');
|
|
97
|
+
if (fs_1.default.existsSync(gitignorePath)) {
|
|
98
|
+
const content = fs_1.default.readFileSync(gitignorePath, 'utf-8');
|
|
99
|
+
ig.add(content);
|
|
100
|
+
}
|
|
101
|
+
// Also check nested .gitignore files by adding the built-in always-ignore patterns
|
|
102
|
+
ig.add(ALWAYS_IGNORE_GLOBS.map(g => g.replace(/\*\*\//g, '')));
|
|
103
|
+
return ig;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Determines whether a file is scannable based on its extension or filename.
|
|
107
|
+
*/
|
|
108
|
+
function isScannableFile(filePath) {
|
|
109
|
+
const basename = path_1.default.basename(filePath);
|
|
110
|
+
const ext = path_1.default.extname(filePath).toLowerCase();
|
|
111
|
+
if (SCANNABLE_FILENAMES.has(basename))
|
|
112
|
+
return true;
|
|
113
|
+
if (ext && SCANNABLE_EXTENSIONS.has(ext))
|
|
114
|
+
return true;
|
|
115
|
+
// Files with no extension that look like config files
|
|
116
|
+
if (!ext && basename.startsWith('.'))
|
|
117
|
+
return true;
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Recursively walks `targetDir` and returns the absolute paths of all
|
|
122
|
+
* scannable files, respecting the nearest .gitignore.
|
|
123
|
+
*/
|
|
124
|
+
async function walkFiles(targetDir) {
|
|
125
|
+
const absoluteDir = path_1.default.resolve(targetDir);
|
|
126
|
+
const ig = loadGitIgnore(absoluteDir);
|
|
127
|
+
const allFiles = await (0, fast_glob_1.default)('**/*', {
|
|
128
|
+
cwd: absoluteDir,
|
|
129
|
+
absolute: true,
|
|
130
|
+
onlyFiles: true,
|
|
131
|
+
dot: true,
|
|
132
|
+
ignore: ALWAYS_IGNORE_GLOBS,
|
|
133
|
+
followSymbolicLinks: false,
|
|
134
|
+
});
|
|
135
|
+
return allFiles.filter(filePath => {
|
|
136
|
+
const relative = path_1.default.relative(absoluteDir, filePath);
|
|
137
|
+
// Apply gitignore rules
|
|
138
|
+
if (ig.ignores(relative))
|
|
139
|
+
return false;
|
|
140
|
+
// Apply extension/filename filter
|
|
141
|
+
if (!isScannableFile(filePath))
|
|
142
|
+
return false;
|
|
143
|
+
return true;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=fileWalker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileWalker.js","sourceRoot":"","sources":["../../src/scanner/fileWalker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ScanSummary } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Main scanner orchestrator.
|
|
4
|
+
* Walks the target directory, scans every file, deduplicates env keys,
|
|
5
|
+
* and returns a full ScanSummary.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runScanner(targetDir: string, envFilePath: string): Promise<ScanSummary>;
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAW,WAAW,EAAE,MAAM,UAAU,CAAC;AAqBhD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA8C7F"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.runScanner = runScanner;
|
|
7
|
+
const ora_1 = __importDefault(require("ora"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const fileWalker_1 = require("./fileWalker");
|
|
11
|
+
const detector_1 = require("./detector");
|
|
12
|
+
/**
|
|
13
|
+
* Reads existing keys from a .env file to seed the deduplication set.
|
|
14
|
+
*/
|
|
15
|
+
function readExistingEnvKeys(envFilePath) {
|
|
16
|
+
const keys = new Set();
|
|
17
|
+
if (!fs_1.default.existsSync(envFilePath))
|
|
18
|
+
return keys;
|
|
19
|
+
const content = fs_1.default.readFileSync(envFilePath, 'utf-8');
|
|
20
|
+
for (const line of content.split('\n')) {
|
|
21
|
+
const trimmed = line.trim();
|
|
22
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
23
|
+
continue;
|
|
24
|
+
const eqIdx = trimmed.indexOf('=');
|
|
25
|
+
if (eqIdx > 0)
|
|
26
|
+
keys.add(trimmed.slice(0, eqIdx).trim());
|
|
27
|
+
}
|
|
28
|
+
return keys;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Main scanner orchestrator.
|
|
32
|
+
* Walks the target directory, scans every file, deduplicates env keys,
|
|
33
|
+
* and returns a full ScanSummary.
|
|
34
|
+
*/
|
|
35
|
+
async function runScanner(targetDir, envFilePath) {
|
|
36
|
+
const spinner = (0, ora_1.default)({
|
|
37
|
+
text: `Discovering files in ${path_1.default.resolve(targetDir)} …`,
|
|
38
|
+
color: 'cyan',
|
|
39
|
+
}).start();
|
|
40
|
+
let files;
|
|
41
|
+
try {
|
|
42
|
+
files = await (0, fileWalker_1.walkFiles)(targetDir);
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
spinner.fail('Failed to walk directory');
|
|
46
|
+
throw err;
|
|
47
|
+
}
|
|
48
|
+
spinner.text = `Scanning ${files.length} files for secrets …`;
|
|
49
|
+
const allFindings = [];
|
|
50
|
+
const filesWithSecrets = new Set();
|
|
51
|
+
for (const filePath of files) {
|
|
52
|
+
const fileFindings = (0, detector_1.scanFile)(filePath);
|
|
53
|
+
if (fileFindings.length > 0) {
|
|
54
|
+
allFindings.push(...fileFindings);
|
|
55
|
+
filesWithSecrets.add(filePath);
|
|
56
|
+
}
|
|
57
|
+
spinner.text = `Scanned ${files.indexOf(filePath) + 1}/${files.length} files — ${allFindings.length} secret(s) found so far …`;
|
|
58
|
+
}
|
|
59
|
+
spinner.succeed(`Scan complete: ${files.length} files scanned, ${allFindings.length} secret(s) found in ${filesWithSecrets.size} file(s).`);
|
|
60
|
+
// Deduplicate env keys, considering what's already in .env
|
|
61
|
+
const existingKeys = readExistingEnvKeys(envFilePath);
|
|
62
|
+
const deduplicated = (0, detector_1.deduplicateEnvKeys)(allFindings, existingKeys);
|
|
63
|
+
return {
|
|
64
|
+
targetDir: path_1.default.resolve(targetDir),
|
|
65
|
+
filesScanned: files.length,
|
|
66
|
+
filesWithSecrets: filesWithSecrets.size,
|
|
67
|
+
totalFindings: deduplicated.length,
|
|
68
|
+
findings: deduplicated,
|
|
69
|
+
envFile: path_1.default.resolve(envFilePath),
|
|
70
|
+
dryRun: false, // set by caller
|
|
71
|
+
scannedAt: new Date().toISOString(),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scanner/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws.d.ts","sourceRoot":"","sources":["../../../src/scanner/rules/aws.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC;;GAEG;AACH,eAAO,MAAM,QAAQ,EAAE,IAAI,EAkF1B,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.awsRules = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* AWS credential patterns.
|
|
6
|
+
*/
|
|
7
|
+
exports.awsRules = [
|
|
8
|
+
{
|
|
9
|
+
id: 'aws-access-key-id',
|
|
10
|
+
description: 'AWS Access Key ID',
|
|
11
|
+
// AWS access key IDs start with AKIA, ABIA, ACCA, or ASIA
|
|
12
|
+
pattern: /(?:aws[_-]?access[_-]?key[_-]?id|aws[_-]?access[_-]?key)\s*[:=]\s*['"\`]?((?:AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16})['"\`]?/i,
|
|
13
|
+
valueGroup: 1,
|
|
14
|
+
envKeyPrefix: 'AWS_ACCESS_KEY_ID',
|
|
15
|
+
severity: 'critical',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'aws-access-key-id-bare',
|
|
19
|
+
description: 'Bare AWS Access Key ID (without variable name context)',
|
|
20
|
+
pattern: /['"\`]((?:AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16})['"\`]/,
|
|
21
|
+
valueGroup: 1,
|
|
22
|
+
envKeyPrefix: 'AWS_ACCESS_KEY_ID',
|
|
23
|
+
severity: 'critical',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
id: 'aws-secret-access-key',
|
|
27
|
+
description: 'AWS Secret Access Key',
|
|
28
|
+
pattern: /(?:aws[_-]?secret[_-]?access[_-]?key|aws[_-]?secret[_-]?key)\s*[:=]\s*['"\`]([A-Za-z0-9+/]{40})['"\`]/i,
|
|
29
|
+
valueGroup: 1,
|
|
30
|
+
envKeyPrefix: 'AWS_SECRET_ACCESS_KEY',
|
|
31
|
+
severity: 'critical',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'aws-session-token',
|
|
35
|
+
description: 'AWS Session Token',
|
|
36
|
+
pattern: /(?:aws[_-]?session[_-]?token|aws[_-]?security[_-]?token)\s*[:=]\s*['"\`]([A-Za-z0-9+/=]{100,})['"\`]/i,
|
|
37
|
+
valueGroup: 1,
|
|
38
|
+
envKeyPrefix: 'AWS_SESSION_TOKEN',
|
|
39
|
+
severity: 'critical',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'aws-account-id',
|
|
43
|
+
description: 'AWS Account ID',
|
|
44
|
+
pattern: /(?:aws[_-]?account[_-]?id|aws[_-]?account)\s*[:=]\s*['"\`]?(\d{12})['"\`]?/i,
|
|
45
|
+
valueGroup: 1,
|
|
46
|
+
envKeyPrefix: 'AWS_ACCOUNT_ID',
|
|
47
|
+
severity: 'high',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: 'aws-mws-key',
|
|
51
|
+
description: 'AWS MWS (Marketplace Web Service) Key',
|
|
52
|
+
pattern: /amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i,
|
|
53
|
+
valueGroup: 0,
|
|
54
|
+
envKeyPrefix: 'AWS_MWS_KEY',
|
|
55
|
+
severity: 'critical',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: 'aws-region',
|
|
59
|
+
description: 'AWS Region hardcoded assignment',
|
|
60
|
+
pattern: /(?:aws[_-]?region)\s*[:=]\s*['"\`](us-east-[12]|us-west-[12]|eu-west-[123]|eu-central-1|ap-southeast-[12]|ap-northeast-[123]|sa-east-1|ca-central-1|ap-south-1|ap-east-1|me-south-1|af-south-1)['"\`]/i,
|
|
61
|
+
valueGroup: 1,
|
|
62
|
+
envKeyPrefix: 'AWS_REGION',
|
|
63
|
+
severity: 'low',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: 'aws-arn',
|
|
67
|
+
description: 'Hardcoded AWS ARN (resource identifier)',
|
|
68
|
+
pattern: /(?:arn[_-]?value|resource[_-]?arn|target[_-]?arn|(?:sns|sqs|lambda|iam|s3)[_-]?arn)\s*[:=]\s*['"\`](arn:aws:[a-z0-9\-]+:[a-z0-9\-]*:\d{12}:[^'"\`\s]+)['"\`]/i,
|
|
69
|
+
valueGroup: 1,
|
|
70
|
+
envKeyPrefix: 'AWS_ARN',
|
|
71
|
+
severity: 'medium',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
id: 'aws-s3-bucket',
|
|
75
|
+
description: 'AWS S3 bucket name hardcoded assignment',
|
|
76
|
+
pattern: /(?:s3[_-]?bucket(?:[_-]?name)?|bucket[_-]?name|AWS_S3_BUCKET)\s*[:=]\s*['"\`]([a-z0-9][a-z0-9\-\.]{1,61}[a-z0-9])['"\`]/i,
|
|
77
|
+
valueGroup: 1,
|
|
78
|
+
envKeyPrefix: 'AWS_S3_BUCKET',
|
|
79
|
+
severity: 'medium',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: 'aws-cloudfront-key-pair-id',
|
|
83
|
+
description: 'AWS CloudFront Key Pair ID',
|
|
84
|
+
pattern: /(?:cloudfront[_-]?key[_-]?pair[_-]?id|CLOUDFRONT_KEY_PAIR_ID)\s*[:=]\s*['"\`]([A-Z0-9]{14,20})['"\`]/i,
|
|
85
|
+
valueGroup: 1,
|
|
86
|
+
envKeyPrefix: 'CLOUDFRONT_KEY_PAIR_ID',
|
|
87
|
+
severity: 'high',
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
//# sourceMappingURL=aws.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aws.js","sourceRoot":"","sources":["../../../src/scanner/rules/aws.ts"],"names":[],"mappings":";;;AAEA;;GAEG;AACU,QAAA,QAAQ,GAAW;IAC9B;QACE,EAAE,EAAE,mBAAmB;QACvB,WAAW,EAAE,mBAAmB;QAChC,0DAA0D;QAC1D,OAAO,EAAE,wHAAwH;QACjI,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,mBAAmB;QACjC,QAAQ,EAAE,UAAU;KACrB;IACD;QACE,EAAE,EAAE,wBAAwB;QAC5B,WAAW,EAAE,wDAAwD;QACrE,OAAO,EAAE,mDAAmD;QAC5D,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,mBAAmB;QACjC,QAAQ,EAAE,UAAU;KACrB;IACD;QACE,EAAE,EAAE,uBAAuB;QAC3B,WAAW,EAAE,uBAAuB;QACpC,OAAO,EAAE,wGAAwG;QACjH,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,uBAAuB;QACrC,QAAQ,EAAE,UAAU;KACrB;IACD;QACE,EAAE,EAAE,mBAAmB;QACvB,WAAW,EAAE,mBAAmB;QAChC,OAAO,EAAE,uGAAuG;QAChH,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,mBAAmB;QACjC,QAAQ,EAAE,UAAU;KACrB;IACD;QACE,EAAE,EAAE,gBAAgB;QACpB,WAAW,EAAE,gBAAgB;QAC7B,OAAO,EAAE,6EAA6E;QACtF,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,gBAAgB;QAC9B,QAAQ,EAAE,MAAM;KACjB;IACD;QACE,EAAE,EAAE,aAAa;QACjB,WAAW,EAAE,uCAAuC;QACpD,OAAO,EAAE,0EAA0E;QACnF,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,aAAa;QAC3B,QAAQ,EAAE,UAAU;KACrB;IACD;QACE,EAAE,EAAE,YAAY;QAChB,WAAW,EAAE,iCAAiC;QAC9C,OAAO,EAAE,wMAAwM;QACjN,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,YAAY;QAC1B,QAAQ,EAAE,KAAK;KAChB;IACD;QACE,EAAE,EAAE,SAAS;QACb,WAAW,EAAE,yCAAyC;QACtD,OAAO,EAAE,+JAA+J;QACxK,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,SAAS;QACvB,QAAQ,EAAE,QAAQ;KACnB;IACD;QACE,EAAE,EAAE,eAAe;QACnB,WAAW,EAAE,yCAAyC;QACtD,OAAO,EAAE,0HAA0H;QACnI,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,eAAe;QAC7B,QAAQ,EAAE,QAAQ;KACnB;IACD;QACE,EAAE,EAAE,4BAA4B;QAChC,WAAW,EAAE,4BAA4B;QACzC,OAAO,EAAE,uGAAuG;QAChH,UAAU,EAAE,CAAC;QACb,YAAY,EAAE,wBAAwB;QACtC,QAAQ,EAAE,MAAM;KACjB;CACF,CAAC"}
|