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.
Files changed (171) hide show
  1. package/LICENSE +79 -0
  2. package/README.md +221 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +121 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/env/envWriter.d.ts +9 -0
  8. package/dist/env/envWriter.d.ts.map +1 -0
  9. package/dist/env/envWriter.js +76 -0
  10. package/dist/env/envWriter.js.map +1 -0
  11. package/dist/env/keyNamer.d.ts +13 -0
  12. package/dist/env/keyNamer.d.ts.map +1 -0
  13. package/dist/env/keyNamer.js +33 -0
  14. package/dist/env/keyNamer.js.map +1 -0
  15. package/dist/interactive/confirm.d.ts +16 -0
  16. package/dist/interactive/confirm.d.ts.map +1 -0
  17. package/dist/interactive/confirm.js +72 -0
  18. package/dist/interactive/confirm.js.map +1 -0
  19. package/dist/license/gitContext.d.ts +16 -0
  20. package/dist/license/gitContext.d.ts.map +1 -0
  21. package/dist/license/gitContext.js +117 -0
  22. package/dist/license/gitContext.js.map +1 -0
  23. package/dist/license/licenseCheck.d.ts +22 -0
  24. package/dist/license/licenseCheck.d.ts.map +1 -0
  25. package/dist/license/licenseCheck.js +119 -0
  26. package/dist/license/licenseCheck.js.map +1 -0
  27. package/dist/license/telemetry.d.ts +17 -0
  28. package/dist/license/telemetry.d.ts.map +1 -0
  29. package/dist/license/telemetry.js +87 -0
  30. package/dist/license/telemetry.js.map +1 -0
  31. package/dist/reporter/console.d.ts +3 -0
  32. package/dist/reporter/console.d.ts.map +1 -0
  33. package/dist/reporter/console.js +96 -0
  34. package/dist/reporter/console.js.map +1 -0
  35. package/dist/reporter/csv.d.ts +6 -0
  36. package/dist/reporter/csv.d.ts.map +1 -0
  37. package/dist/reporter/csv.js +56 -0
  38. package/dist/reporter/csv.js.map +1 -0
  39. package/dist/reporter/index.d.ts +13 -0
  40. package/dist/reporter/index.d.ts.map +1 -0
  41. package/dist/reporter/index.js +52 -0
  42. package/dist/reporter/index.js.map +1 -0
  43. package/dist/reporter/json.d.ts +7 -0
  44. package/dist/reporter/json.d.ts.map +1 -0
  45. package/dist/reporter/json.js +39 -0
  46. package/dist/reporter/json.js.map +1 -0
  47. package/dist/reporter/markdown.d.ts +6 -0
  48. package/dist/reporter/markdown.d.ts.map +1 -0
  49. package/dist/reporter/markdown.js +106 -0
  50. package/dist/reporter/markdown.js.map +1 -0
  51. package/dist/rewriter/index.d.ts +9 -0
  52. package/dist/rewriter/index.d.ts.map +1 -0
  53. package/dist/rewriter/index.js +95 -0
  54. package/dist/rewriter/index.js.map +1 -0
  55. package/dist/rewriter/langDetector.d.ts +7 -0
  56. package/dist/rewriter/langDetector.d.ts.map +1 -0
  57. package/dist/rewriter/langDetector.js +96 -0
  58. package/dist/rewriter/langDetector.js.map +1 -0
  59. package/dist/rewriter/templates/csharp.d.ts +8 -0
  60. package/dist/rewriter/templates/csharp.d.ts.map +1 -0
  61. package/dist/rewriter/templates/csharp.js +36 -0
  62. package/dist/rewriter/templates/csharp.js.map +1 -0
  63. package/dist/rewriter/templates/generic.d.ts +7 -0
  64. package/dist/rewriter/templates/generic.d.ts.map +1 -0
  65. package/dist/rewriter/templates/generic.js +40 -0
  66. package/dist/rewriter/templates/generic.js.map +1 -0
  67. package/dist/rewriter/templates/go.d.ts +8 -0
  68. package/dist/rewriter/templates/go.d.ts.map +1 -0
  69. package/dist/rewriter/templates/go.js +56 -0
  70. package/dist/rewriter/templates/go.js.map +1 -0
  71. package/dist/rewriter/templates/java.d.ts +7 -0
  72. package/dist/rewriter/templates/java.d.ts.map +1 -0
  73. package/dist/rewriter/templates/java.js +31 -0
  74. package/dist/rewriter/templates/java.js.map +1 -0
  75. package/dist/rewriter/templates/javascript.d.ts +10 -0
  76. package/dist/rewriter/templates/javascript.d.ts.map +1 -0
  77. package/dist/rewriter/templates/javascript.js +54 -0
  78. package/dist/rewriter/templates/javascript.js.map +1 -0
  79. package/dist/rewriter/templates/php.d.ts +8 -0
  80. package/dist/rewriter/templates/php.d.ts.map +1 -0
  81. package/dist/rewriter/templates/php.js +41 -0
  82. package/dist/rewriter/templates/php.js.map +1 -0
  83. package/dist/rewriter/templates/properties.d.ts +9 -0
  84. package/dist/rewriter/templates/properties.d.ts.map +1 -0
  85. package/dist/rewriter/templates/properties.js +39 -0
  86. package/dist/rewriter/templates/properties.js.map +1 -0
  87. package/dist/rewriter/templates/python.d.ts +8 -0
  88. package/dist/rewriter/templates/python.d.ts.map +1 -0
  89. package/dist/rewriter/templates/python.js +48 -0
  90. package/dist/rewriter/templates/python.js.map +1 -0
  91. package/dist/rewriter/templates/ruby.d.ts +8 -0
  92. package/dist/rewriter/templates/ruby.d.ts.map +1 -0
  93. package/dist/rewriter/templates/ruby.js +40 -0
  94. package/dist/rewriter/templates/ruby.js.map +1 -0
  95. package/dist/rewriter/templates/rust.d.ts +7 -0
  96. package/dist/rewriter/templates/rust.d.ts.map +1 -0
  97. package/dist/rewriter/templates/rust.js +27 -0
  98. package/dist/rewriter/templates/rust.js.map +1 -0
  99. package/dist/rewriter/templates/shell.d.ts +7 -0
  100. package/dist/rewriter/templates/shell.d.ts.map +1 -0
  101. package/dist/rewriter/templates/shell.js +42 -0
  102. package/dist/rewriter/templates/shell.js.map +1 -0
  103. package/dist/rewriter/templates/toml.d.ts +9 -0
  104. package/dist/rewriter/templates/toml.d.ts.map +1 -0
  105. package/dist/rewriter/templates/toml.js +34 -0
  106. package/dist/rewriter/templates/toml.js.map +1 -0
  107. package/dist/rewriter/templates/yaml.d.ts +8 -0
  108. package/dist/rewriter/templates/yaml.d.ts.map +1 -0
  109. package/dist/rewriter/templates/yaml.js +37 -0
  110. package/dist/rewriter/templates/yaml.js.map +1 -0
  111. package/dist/scanner/detector.d.ts +18 -0
  112. package/dist/scanner/detector.d.ts.map +1 -0
  113. package/dist/scanner/detector.js +156 -0
  114. package/dist/scanner/detector.js.map +1 -0
  115. package/dist/scanner/fileWalker.d.ts +6 -0
  116. package/dist/scanner/fileWalker.d.ts.map +1 -0
  117. package/dist/scanner/fileWalker.js +146 -0
  118. package/dist/scanner/fileWalker.js.map +1 -0
  119. package/dist/scanner/index.d.ts +8 -0
  120. package/dist/scanner/index.d.ts.map +1 -0
  121. package/dist/scanner/index.js +74 -0
  122. package/dist/scanner/index.js.map +1 -0
  123. package/dist/scanner/rules/aws.d.ts +6 -0
  124. package/dist/scanner/rules/aws.d.ts.map +1 -0
  125. package/dist/scanner/rules/aws.js +90 -0
  126. package/dist/scanner/rules/aws.js.map +1 -0
  127. package/dist/scanner/rules/azure.d.ts +6 -0
  128. package/dist/scanner/rules/azure.d.ts.map +1 -0
  129. package/dist/scanner/rules/azure.js +86 -0
  130. package/dist/scanner/rules/azure.js.map +1 -0
  131. package/dist/scanner/rules/cloud.d.ts +11 -0
  132. package/dist/scanner/rules/cloud.d.ts.map +1 -0
  133. package/dist/scanner/rules/cloud.js +1066 -0
  134. package/dist/scanner/rules/cloud.js.map +1 -0
  135. package/dist/scanner/rules/database.d.ts +6 -0
  136. package/dist/scanner/rules/database.d.ts.map +1 -0
  137. package/dist/scanner/rules/database.js +283 -0
  138. package/dist/scanner/rules/database.js.map +1 -0
  139. package/dist/scanner/rules/gcp.d.ts +6 -0
  140. package/dist/scanner/rules/gcp.d.ts.map +1 -0
  141. package/dist/scanner/rules/gcp.js +108 -0
  142. package/dist/scanner/rules/gcp.js.map +1 -0
  143. package/dist/scanner/rules/generic.d.ts +13 -0
  144. package/dist/scanner/rules/generic.d.ts.map +1 -0
  145. package/dist/scanner/rules/generic.js +305 -0
  146. package/dist/scanner/rules/generic.js.map +1 -0
  147. package/dist/scanner/rules/index.d.ts +18 -0
  148. package/dist/scanner/rules/index.d.ts.map +1 -0
  149. package/dist/scanner/rules/index.js +40 -0
  150. package/dist/scanner/rules/index.js.map +1 -0
  151. package/dist/scanner/rules/jwt.d.ts +6 -0
  152. package/dist/scanner/rules/jwt.d.ts.map +1 -0
  153. package/dist/scanner/rules/jwt.js +97 -0
  154. package/dist/scanner/rules/jwt.js.map +1 -0
  155. package/dist/scanner/rules/network.d.ts +7 -0
  156. package/dist/scanner/rules/network.d.ts.map +1 -0
  157. package/dist/scanner/rules/network.js +166 -0
  158. package/dist/scanner/rules/network.js.map +1 -0
  159. package/dist/scanner/rules/privateKey.d.ts +6 -0
  160. package/dist/scanner/rules/privateKey.d.ts.map +1 -0
  161. package/dist/scanner/rules/privateKey.js +60 -0
  162. package/dist/scanner/rules/privateKey.js.map +1 -0
  163. package/dist/scanner/rules/ssh.d.ts +6 -0
  164. package/dist/scanner/rules/ssh.d.ts.map +1 -0
  165. package/dist/scanner/rules/ssh.js +49 -0
  166. package/dist/scanner/rules/ssh.js.map +1 -0
  167. package/dist/types.d.ts +78 -0
  168. package/dist/types.d.ts.map +1 -0
  169. package/dist/types.js +3 -0
  170. package/dist/types.js.map +1 -0
  171. package/package.json +54 -0
@@ -0,0 +1,72 @@
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.confirmChanges = confirmChanges;
7
+ exports.askBackupPreference = askBackupPreference;
8
+ exports.askEnvFilePath = askEnvFilePath;
9
+ const prompts_1 = require("@inquirer/prompts");
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ const path_1 = __importDefault(require("path"));
12
+ /**
13
+ * Shows a summary of planned changes and asks the user to confirm before proceeding.
14
+ * Returns true if the user approves, false if they decline.
15
+ */
16
+ async function confirmChanges(summary, noRewrite) {
17
+ if (summary.totalFindings === 0)
18
+ return false;
19
+ console.log('\n' + chalk_1.default.bold.yellow('📋 Planned Changes:'));
20
+ console.log(chalk_1.default.gray('─'.repeat(60)));
21
+ // Group by file
22
+ const byFile = new Map();
23
+ for (const f of summary.findings) {
24
+ if (!byFile.has(f.file))
25
+ byFile.set(f.file, []);
26
+ byFile.get(f.file).push(f);
27
+ }
28
+ // Print .env changes
29
+ console.log(chalk_1.default.bold(`\n 1. Write to ${chalk_1.default.underline(summary.envFile)}:`));
30
+ for (const f of summary.findings) {
31
+ console.log(chalk_1.default.green(` + ${f.envKey}="***"`));
32
+ }
33
+ if (!noRewrite) {
34
+ console.log(chalk_1.default.bold(`\n 2. Rewrite ${byFile.size} source file(s):`));
35
+ for (const [filePath, fileFindings] of byFile) {
36
+ const relPath = path_1.default.relative(summary.targetDir, filePath);
37
+ console.log(chalk_1.default.cyan(` 📄 ${relPath} (${fileFindings.length} change(s))`));
38
+ }
39
+ }
40
+ console.log(chalk_1.default.gray('\n─'.repeat(60)));
41
+ const answer = await (0, prompts_1.confirm)({
42
+ message: `Apply ${summary.totalFindings} change(s) to .env${noRewrite ? '' : ' and source files'}?`,
43
+ default: true,
44
+ });
45
+ return answer;
46
+ }
47
+ /**
48
+ * Asks the user to confirm backup before proceeding.
49
+ * Returns 'backup', 'skip', or 'abort'.
50
+ */
51
+ async function askBackupPreference() {
52
+ const choice = await (0, prompts_1.select)({
53
+ message: 'Source files will be modified. How would you like to handle backups?',
54
+ choices: [
55
+ { name: 'Create .bak backup of each modified file', value: 'backup' },
56
+ { name: 'Skip backup (rely on Git)', value: 'skip' },
57
+ { name: 'Abort — do not make any changes', value: 'abort' },
58
+ ],
59
+ });
60
+ return choice;
61
+ }
62
+ /**
63
+ * Prompts for a custom .env file path override.
64
+ */
65
+ async function askEnvFilePath(defaultPath) {
66
+ const answer = await (0, prompts_1.input)({
67
+ message: 'Path for the .env file:',
68
+ default: defaultPath,
69
+ });
70
+ return answer;
71
+ }
72
+ //# sourceMappingURL=confirm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirm.js","sourceRoot":"","sources":["../../src/interactive/confirm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export type GitPlatform = 'github' | 'gitlab' | 'bitbucket' | 'other';
2
+ export type AccountType = 'Organization' | 'User' | 'unknown';
3
+ export interface GitContext {
4
+ repoUrl: string;
5
+ owner: string;
6
+ repoName: string;
7
+ platform: GitPlatform;
8
+ accountType: AccountType;
9
+ }
10
+ /**
11
+ * Reads the git remote origin URL from the target directory, parses it,
12
+ * and (for GitHub repos) checks whether the owner is an Org or personal User.
13
+ * Returns null if the directory has no git remote or is not a git repo.
14
+ */
15
+ export declare function getGitContext(targetDir: string): Promise<GitContext | null>;
16
+ //# sourceMappingURL=gitContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitContext.d.ts","sourceRoot":"","sources":["../../src/license/gitContext.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,GAAG,OAAO,CAAC;AACtE,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,MAAM,GAAG,SAAS,CAAC;AAE9D,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,WAAW,CAAC;IACtB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAkFD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA2BjF"}
@@ -0,0 +1,117 @@
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.getGitContext = getGitContext;
7
+ const child_process_1 = require("child_process");
8
+ const https_1 = __importDefault(require("https"));
9
+ // ─── Parse remote URL ─────────────────────────────────────────────────────────
10
+ /**
11
+ * Parses a git remote URL (SSH or HTTPS) into owner, repo, and platform.
12
+ * Supports:
13
+ * git@github.com:owner/repo.git
14
+ * https://github.com/owner/repo.git
15
+ * git@gitlab.com:owner/repo.git
16
+ * https://bitbucket.org/owner/repo.git
17
+ */
18
+ function parseRemoteUrl(remoteUrl) {
19
+ // SSH format: git@<host>:<owner>/<repo>.git
20
+ const sshMatch = remoteUrl.match(/git@([^:]+):([^/]+)\/(.+?)(?:\.git)?$/);
21
+ if (sshMatch) {
22
+ const host = sshMatch[1].toLowerCase();
23
+ const owner = sshMatch[2];
24
+ const repoName = sshMatch[3];
25
+ return { owner, repoName, platform: detectPlatform(host) };
26
+ }
27
+ // HTTPS format: https://<host>/<owner>/<repo>.git
28
+ const httpsMatch = remoteUrl.match(/https?:\/\/([^/]+)\/([^/]+)\/(.+?)(?:\.git)?$/);
29
+ if (httpsMatch) {
30
+ const host = httpsMatch[1].toLowerCase();
31
+ const owner = httpsMatch[2];
32
+ const repoName = httpsMatch[3];
33
+ return { owner, repoName, platform: detectPlatform(host) };
34
+ }
35
+ return null;
36
+ }
37
+ function detectPlatform(host) {
38
+ if (host.includes('github'))
39
+ return 'github';
40
+ if (host.includes('gitlab'))
41
+ return 'gitlab';
42
+ if (host.includes('bitbucket'))
43
+ return 'bitbucket';
44
+ return 'other';
45
+ }
46
+ // ─── GitHub API: org vs user ──────────────────────────────────────────────────
47
+ /**
48
+ * Calls the public unauthenticated GitHub API to determine whether an owner
49
+ * is a personal User or an Organization. Returns 'unknown' on any failure.
50
+ */
51
+ function fetchGitHubAccountType(owner) {
52
+ return new Promise((resolve) => {
53
+ const options = {
54
+ hostname: 'api.github.com',
55
+ path: `/users/${encodeURIComponent(owner)}`,
56
+ method: 'GET',
57
+ headers: {
58
+ 'User-Agent': 'code-secret-handler',
59
+ 'Accept': 'application/vnd.github+json',
60
+ },
61
+ };
62
+ const req = https_1.default.request(options, (res) => {
63
+ let data = '';
64
+ res.on('data', (chunk) => { data += chunk; });
65
+ res.on('end', () => {
66
+ try {
67
+ const json = JSON.parse(data);
68
+ if (json.type === 'Organization')
69
+ resolve('Organization');
70
+ else if (json.type === 'User')
71
+ resolve('User');
72
+ else
73
+ resolve('unknown');
74
+ }
75
+ catch {
76
+ resolve('unknown');
77
+ }
78
+ });
79
+ });
80
+ req.on('error', () => resolve('unknown'));
81
+ req.setTimeout(4000, () => { req.destroy(); resolve('unknown'); });
82
+ req.end();
83
+ });
84
+ }
85
+ // ─── Main export ──────────────────────────────────────────────────────────────
86
+ /**
87
+ * Reads the git remote origin URL from the target directory, parses it,
88
+ * and (for GitHub repos) checks whether the owner is an Org or personal User.
89
+ * Returns null if the directory has no git remote or is not a git repo.
90
+ */
91
+ async function getGitContext(targetDir) {
92
+ try {
93
+ const rawUrl = (0, child_process_1.execSync)(`git -C "${targetDir}" config --get remote.origin.url`, {
94
+ stdio: ['ignore', 'pipe', 'ignore'],
95
+ timeout: 4000,
96
+ })
97
+ .toString()
98
+ .trim();
99
+ if (!rawUrl)
100
+ return null;
101
+ const parsed = parseRemoteUrl(rawUrl);
102
+ if (!parsed)
103
+ return null;
104
+ const { owner, repoName, platform } = parsed;
105
+ // Only query GitHub API for GitHub repos (GitLab/Bitbucket have different APIs)
106
+ let accountType = 'unknown';
107
+ if (platform === 'github') {
108
+ accountType = await fetchGitHubAccountType(owner);
109
+ }
110
+ return { repoUrl: rawUrl, owner, repoName, platform, accountType };
111
+ }
112
+ catch {
113
+ // Not a git repo, no remote, or git not installed — silently ignore
114
+ return null;
115
+ }
116
+ }
117
+ //# sourceMappingURL=gitContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gitContext.js","sourceRoot":"","sources":["../../src/license/gitContext.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { GitContext } from './gitContext';
2
+ export interface LicenseCheckResult {
3
+ /** Whether execution is allowed to continue */
4
+ allowed: boolean;
5
+ /** Whether a valid commercial license key was provided */
6
+ licenseKeyProvided: boolean;
7
+ }
8
+ /**
9
+ * Performs the full license check:
10
+ *
11
+ * 1. If CSH_LICENSE_KEY is set → validate it online against Supabase.
12
+ * - Valid → allow (commercial user with a valid key)
13
+ * - Invalid → treat as unlicensed org and block
14
+ *
15
+ * 2. If no key and the owner is a GitHub Organization → hard-block with banner.
16
+ *
17
+ * 3. All other cases (personal user, unknown, no git remote) → allow freely.
18
+ *
19
+ * Hard-blocks call process.exit(1).
20
+ */
21
+ export declare function checkLicense(gitCtx: GitContext | null): Promise<LicenseCheckResult>;
22
+ //# sourceMappingURL=licenseCheck.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"licenseCheck.d.ts","sourceRoot":"","sources":["../../src/license/licenseCheck.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA2F1C,MAAM,WAAW,kBAAkB;IACjC,+CAA+C;IAC/C,OAAO,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA2BzF"}
@@ -0,0 +1,119 @@
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.checkLicense = checkLicense;
7
+ const https_1 = __importDefault(require("https"));
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ // ─── Config ───────────────────────────────────────────────────────────────────
10
+ const SUPABASE_URL = 'https://onzfespujyixmzcrsrmc.supabase.co';
11
+ const SUPABASE_ANON_KEY = 'sb_publishable_wmKRmr4EANLYfpJyllpxRQ_IZUCOn9o';
12
+ const CONTACT_EMAIL = 'vic.grambo@gmail.com';
13
+ // ─── Supabase license key validator ──────────────────────────────────────────
14
+ /**
15
+ * Checks the `license_keys` table in Supabase for a matching active key.
16
+ * Returns true if the key is valid and active.
17
+ */
18
+ function validateKeyOnline(licenseKey) {
19
+ return new Promise((resolve) => {
20
+ const encodedKey = encodeURIComponent(licenseKey);
21
+ const url = new URL(`/rest/v1/license_keys?key=eq.${encodedKey}&is_active=eq.true&select=key`, SUPABASE_URL);
22
+ const options = {
23
+ hostname: url.hostname,
24
+ path: url.pathname + url.search,
25
+ method: 'GET',
26
+ headers: {
27
+ 'apikey': SUPABASE_ANON_KEY,
28
+ 'Authorization': `Bearer ${SUPABASE_ANON_KEY}`,
29
+ 'Accept': 'application/json',
30
+ },
31
+ };
32
+ const req = https_1.default.request(options, (res) => {
33
+ let data = '';
34
+ res.on('data', (chunk) => { data += chunk; });
35
+ res.on('end', () => {
36
+ try {
37
+ const rows = JSON.parse(data);
38
+ resolve(Array.isArray(rows) && rows.length > 0);
39
+ }
40
+ catch {
41
+ resolve(false);
42
+ }
43
+ });
44
+ });
45
+ req.on('error', () => resolve(false));
46
+ req.setTimeout(6000, () => { req.destroy(); resolve(false); });
47
+ req.end();
48
+ });
49
+ }
50
+ // ─── Hard-block banner ────────────────────────────────────────────────────────
51
+ function printBlockBanner(gitCtx) {
52
+ const owner = gitCtx?.owner ?? 'Unknown';
53
+ const repo = gitCtx ? `${gitCtx.owner}/${gitCtx.repoName}` : 'Unknown';
54
+ const type = gitCtx?.accountType === 'Organization' ? 'GitHub Organization' : 'Organization / Company';
55
+ const w = 65;
56
+ const line = '─'.repeat(w);
57
+ console.log('\n' + chalk_1.default.red('┌' + line + '┐'));
58
+ const title = ' đŸšĢ COMMERCIAL USE DETECTED — LICENSE REQUIRED';
59
+ console.log(chalk_1.default.red('│') + chalk_1.default.bold.red(title.padEnd(w)) + chalk_1.default.red('│'));
60
+ console.log(chalk_1.default.red('│' + ' '.repeat(w) + '│'));
61
+ const rows = [
62
+ ` This tool is free for personal use only.`,
63
+ ` The scanned repo appears to belong to an organization:`,
64
+ ``,
65
+ ` Owner : ${owner} (${type})`,
66
+ ` Repo : ${repo}`,
67
+ ``,
68
+ ` To use code-secret-handler commercially or within an`,
69
+ ` organization, you must obtain a commercial license.`,
70
+ ``,
71
+ ` Contact : ${CONTACT_EMAIL}`,
72
+ ` Set : CSH_LICENSE_KEY=<your-key> to proceed`,
73
+ ``,
74
+ ` To opt out of telemetry: CSH_TELEMETRY=0`,
75
+ ];
76
+ for (const row of rows) {
77
+ console.log(chalk_1.default.red('│') + chalk_1.default.yellow(row.padEnd(w)) + chalk_1.default.red('│'));
78
+ }
79
+ console.log(chalk_1.default.red('└' + line + '┘') + '\n');
80
+ }
81
+ /**
82
+ * Performs the full license check:
83
+ *
84
+ * 1. If CSH_LICENSE_KEY is set → validate it online against Supabase.
85
+ * - Valid → allow (commercial user with a valid key)
86
+ * - Invalid → treat as unlicensed org and block
87
+ *
88
+ * 2. If no key and the owner is a GitHub Organization → hard-block with banner.
89
+ *
90
+ * 3. All other cases (personal user, unknown, no git remote) → allow freely.
91
+ *
92
+ * Hard-blocks call process.exit(1).
93
+ */
94
+ async function checkLicense(gitCtx) {
95
+ const licenseKey = process.env['CSH_LICENSE_KEY']?.trim();
96
+ // ── Step 1: License key provided → validate online ──────────────────────────
97
+ if (licenseKey) {
98
+ console.log(chalk_1.default.gray(' 🔑 Validating commercial license keyâ€Ļ'));
99
+ const valid = await validateKeyOnline(licenseKey);
100
+ if (valid) {
101
+ console.log(chalk_1.default.green(' ✅ Commercial license verified. Thank you!\n'));
102
+ return { allowed: true, licenseKeyProvided: true };
103
+ }
104
+ else {
105
+ // Invalid key — treat as unlicensed org
106
+ console.log(chalk_1.default.red(' ❌ License key is invalid or expired.\n'));
107
+ printBlockBanner(gitCtx);
108
+ process.exit(1);
109
+ }
110
+ }
111
+ // ── Step 2: No key → check if this is an org repo ───────────────────────────
112
+ if (gitCtx?.accountType === 'Organization') {
113
+ printBlockBanner(gitCtx);
114
+ process.exit(1);
115
+ }
116
+ // ── Step 3: Personal user, unknown, or no git context → allow freely ────────
117
+ return { allowed: true, licenseKeyProvided: false };
118
+ }
119
+ //# sourceMappingURL=licenseCheck.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"licenseCheck.js","sourceRoot":"","sources":["../../src/license/licenseCheck.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { GitContext } from './gitContext';
2
+ /**
3
+ * Sends a non-blocking, fire-and-forget telemetry ping to Supabase.
4
+ *
5
+ * Opt-out: set CSH_TELEMETRY=0 in the environment.
6
+ *
7
+ * What is collected:
8
+ * - Tool version, OS, Node.js version
9
+ * - Git remote URL, owner, repo name, platform (github/gitlab/etc.)
10
+ * - Whether the owner is an Org or personal User (via public GitHub API)
11
+ * - Whether a commercial license key was provided
12
+ * - Timestamp
13
+ *
14
+ * Nothing sensitive is ever collected (no secrets, no file contents, no code).
15
+ */
16
+ export declare function sendTelemetry(gitCtx: GitContext | null, licenseKeyProvided: boolean): void;
17
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/license/telemetry.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AA+D1C;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,EAAE,kBAAkB,EAAE,OAAO,GAAG,IAAI,CAwB1F"}
@@ -0,0 +1,87 @@
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.sendTelemetry = sendTelemetry;
7
+ const https_1 = __importDefault(require("https"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const path_1 = __importDefault(require("path"));
10
+ // ─── Config (baked in at publish time) ───────────────────────────────────────
11
+ const SUPABASE_URL = 'https://onzfespujyixmzcrsrmc.supabase.co';
12
+ const SUPABASE_ANON_KEY = 'sb_publishable_wmKRmr4EANLYfpJyllpxRQ_IZUCOn9o';
13
+ const TABLE = 'csh_telemetry';
14
+ // ─── Version helper ───────────────────────────────────────────────────────────
15
+ function getToolVersion() {
16
+ try {
17
+ const pkgPath = path_1.default.join(__dirname, '..', '..', 'package.json');
18
+ const pkg = JSON.parse(fs_1.default.readFileSync(pkgPath, 'utf-8'));
19
+ return pkg.version ?? 'unknown';
20
+ }
21
+ catch {
22
+ return 'unknown';
23
+ }
24
+ }
25
+ // ─── HTTP POST (no external deps — pure Node https) ──────────────────────────
26
+ function postToSupabase(payload) {
27
+ const body = JSON.stringify(payload);
28
+ const url = new URL(`/rest/v1/${TABLE}`, SUPABASE_URL);
29
+ const options = {
30
+ hostname: url.hostname,
31
+ path: url.pathname,
32
+ method: 'POST',
33
+ headers: {
34
+ 'Content-Type': 'application/json',
35
+ 'Content-Length': Buffer.byteLength(body),
36
+ 'apikey': SUPABASE_ANON_KEY,
37
+ 'Authorization': `Bearer ${SUPABASE_ANON_KEY}`,
38
+ 'Prefer': 'return=minimal',
39
+ },
40
+ };
41
+ const req = https_1.default.request(options);
42
+ req.on('error', () => { });
43
+ req.setTimeout(6000, () => { req.destroy(); });
44
+ req.write(body);
45
+ req.end();
46
+ }
47
+ // ─── Main export ──────────────────────────────────────────────────────────────
48
+ /**
49
+ * Sends a non-blocking, fire-and-forget telemetry ping to Supabase.
50
+ *
51
+ * Opt-out: set CSH_TELEMETRY=0 in the environment.
52
+ *
53
+ * What is collected:
54
+ * - Tool version, OS, Node.js version
55
+ * - Git remote URL, owner, repo name, platform (github/gitlab/etc.)
56
+ * - Whether the owner is an Org or personal User (via public GitHub API)
57
+ * - Whether a commercial license key was provided
58
+ * - Timestamp
59
+ *
60
+ * Nothing sensitive is ever collected (no secrets, no file contents, no code).
61
+ */
62
+ function sendTelemetry(gitCtx, licenseKeyProvided) {
63
+ // Respect opt-out
64
+ const telemetryEnv = process.env['CSH_TELEMETRY'];
65
+ if (telemetryEnv === '0' || telemetryEnv === 'false')
66
+ return;
67
+ const payload = {
68
+ tool_version: getToolVersion(),
69
+ os_platform: process.platform,
70
+ node_version: process.version,
71
+ repo_url: gitCtx?.repoUrl ?? null,
72
+ owner: gitCtx?.owner ?? null,
73
+ repo_name: gitCtx?.repoName ?? null,
74
+ git_platform: gitCtx?.platform ?? null,
75
+ account_type: gitCtx?.accountType ?? null,
76
+ license_key_provided: licenseKeyProvided,
77
+ timestamp: new Date().toISOString(),
78
+ };
79
+ // Fully async — does not await, does not block the CLI
80
+ try {
81
+ postToSupabase(payload);
82
+ }
83
+ catch {
84
+ // Never crash the CLI due to telemetry
85
+ }
86
+ }
87
+ //# sourceMappingURL=telemetry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/license/telemetry.ts"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,4CAAoB;AACpB,gDAAwB;AAGxB,gFAAgF;AAEhF,MAAM,YAAY,GAAG,0CAA0C,CAAC;AAChE,MAAM,iBAAiB,GAAG,gDAAgD,CAAC;AAC3E,MAAM,KAAK,GAAG,eAAe,CAAC;AAiB9B,iFAAiF;AAEjF,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAyB,CAAC;QAClF,OAAO,GAAG,CAAC,OAAO,IAAI,SAAS,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,gFAAgF;AAEhF,SAAS,cAAc,CAAC,OAAyB;IAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,YAAY,KAAK,EAAE,EAAE,YAAY,CAAC,CAAC;IAEvD,MAAM,OAAO,GAAG;QACd,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,IAAI,EAAE,GAAG,CAAC,QAAQ;QAClB,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,gBAAgB,EAAE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC;YACzC,QAAQ,EAAE,iBAAiB;YAC3B,eAAe,EAAE,UAAU,iBAAiB,EAAE;YAC9C,QAAQ,EAAE,gBAAgB;SAC3B;KACF,CAAC;IAEF,MAAM,GAAG,GAAG,eAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAuC,CAAC,CAAC,CAAC;IAC/D,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/C,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChB,GAAG,CAAC,GAAG,EAAE,CAAC;AACZ,CAAC;AAED,iFAAiF;AAEjF;;;;;;;;;;;;;GAaG;AACH,uBAA8B,MAAyB,EAAE,kBAA2B;IAClF,kBAAkB;IAClB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAClD,IAAI,YAAY,KAAK,GAAG,IAAI,YAAY,KAAK,OAAO;QAAE,OAAO;IAE7D,MAAM,OAAO,GAAqB;QAChC,YAAY,EAAE,cAAc,EAAE;QAC9B,WAAW,EAAE,OAAO,CAAC,QAAQ;QAC7B,YAAY,EAAE,OAAO,CAAC,OAAO;QAC7B,QAAQ,EAAE,MAAM,EAAE,OAAO,IAAI,IAAI;QACjC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,IAAI;QAC5B,SAAS,EAAE,MAAM,EAAE,QAAQ,IAAI,IAAI;QACnC,YAAY,EAAE,MAAM,EAAE,QAAQ,IAAI,IAAI;QACtC,YAAY,EAAE,MAAM,EAAE,WAAW,IAAI,IAAI;QACzC,oBAAoB,EAAE,kBAAkB;QACxC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IAEF,uDAAuD;IACvD,IAAI,CAAC;QACH,cAAc,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { ScanSummary } from '../types';
2
+ export declare function printConsoleReport(summary: ScanSummary): void;
3
+ //# sourceMappingURL=console.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/reporter/console.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAqB,MAAM,UAAU,CAAC;AA8B1D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CA4E7D"}
@@ -0,0 +1,96 @@
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.printConsoleReport = printConsoleReport;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const SEVERITY_COLORS = {
10
+ critical: (s) => chalk_1.default.bgRed.white.bold(s),
11
+ high: (s) => chalk_1.default.red.bold(s),
12
+ medium: (s) => chalk_1.default.yellow.bold(s),
13
+ low: (s) => chalk_1.default.blue(s),
14
+ };
15
+ const SEVERITY_ICONS = {
16
+ critical: '🚨',
17
+ high: '🔴',
18
+ medium: '🟡',
19
+ low: 'đŸ”ĩ',
20
+ };
21
+ function maskValue(value) {
22
+ if (value.length <= 8)
23
+ return '*'.repeat(value.length);
24
+ return value.slice(0, 4) + '*'.repeat(Math.min(value.length - 8, 20)) + value.slice(-4);
25
+ }
26
+ function groupByFile(findings) {
27
+ const map = new Map();
28
+ for (const f of findings) {
29
+ if (!map.has(f.file))
30
+ map.set(f.file, []);
31
+ map.get(f.file).push(f);
32
+ }
33
+ return map;
34
+ }
35
+ function printConsoleReport(summary) {
36
+ const { findings, filesScanned, filesWithSecrets, totalFindings, dryRun, envFile, scannedAt } = summary;
37
+ console.log('\n' + chalk_1.default.bold.cyan('═'.repeat(70)));
38
+ console.log(chalk_1.default.bold.cyan(' 🔐 CODE SECRET HANDLER — Scan Report'));
39
+ console.log(chalk_1.default.bold.cyan('═'.repeat(70)));
40
+ console.log(chalk_1.default.gray(` Scanned at : ${scannedAt}`));
41
+ console.log(chalk_1.default.gray(` Target dir : ${summary.targetDir}`));
42
+ console.log(chalk_1.default.gray(` Env file : ${envFile}`));
43
+ if (dryRun)
44
+ console.log(chalk_1.default.yellow(' âš ī¸ DRY RUN MODE — No files were modified'));
45
+ console.log('');
46
+ if (totalFindings === 0) {
47
+ console.log(chalk_1.default.green.bold(' ✅ No hardcoded secrets detected. Great job!\n'));
48
+ return;
49
+ }
50
+ // Summary line
51
+ console.log(chalk_1.default.bold(` Found ${chalk_1.default.red(String(totalFindings))} secret(s) across `) +
52
+ chalk_1.default.bold(`${chalk_1.default.red(String(filesWithSecrets))} file(s) `) +
53
+ chalk_1.default.gray(`(${filesScanned} files scanned)`));
54
+ console.log('');
55
+ // Severity breakdown
56
+ const bySeverity = { critical: 0, high: 0, medium: 0, low: 0 };
57
+ for (const f of findings)
58
+ bySeverity[f.rule.severity]++;
59
+ console.log(' Severity breakdown:');
60
+ for (const [sev, count] of Object.entries(bySeverity)) {
61
+ if (count === 0)
62
+ continue;
63
+ const colored = SEVERITY_COLORS[sev];
64
+ console.log(` ${SEVERITY_ICONS[sev]} ${colored(sev.padEnd(8))} ${count}`);
65
+ }
66
+ console.log('');
67
+ // Per-file findings
68
+ const byFile = groupByFile(findings);
69
+ for (const [filePath, fileFindings] of byFile) {
70
+ const relPath = path_1.default.relative(summary.targetDir, filePath);
71
+ console.log(chalk_1.default.underline.bold(` 📄 ${relPath}`));
72
+ for (const f of fileFindings) {
73
+ const sevColor = SEVERITY_COLORS[f.rule.severity];
74
+ const icon = SEVERITY_ICONS[f.rule.severity];
75
+ console.log(` ${icon} ${sevColor(`[${f.rule.severity.toUpperCase()}]`)} ` +
76
+ chalk_1.default.cyan(`Line ${f.line}:${f.column}`) +
77
+ ` ${chalk_1.default.gray(f.rule.description)}`);
78
+ console.log(` Rule ID : ${chalk_1.default.gray(f.rule.id)}`);
79
+ console.log(` Value : ${chalk_1.default.red(maskValue(f.rawValue))}`);
80
+ console.log(` Env Key : ${chalk_1.default.green(f.envKey)}`);
81
+ if (!dryRun) {
82
+ console.log(` Context : ${chalk_1.default.dim(f.lineContent.trim().slice(0, 80))}`);
83
+ }
84
+ console.log('');
85
+ }
86
+ }
87
+ console.log(chalk_1.default.bold.cyan('═'.repeat(70)));
88
+ if (!dryRun) {
89
+ console.log(chalk_1.default.green.bold(`\n ✅ ${totalFindings} secret(s) moved to ${chalk_1.default.underline(envFile)}`));
90
+ console.log(chalk_1.default.yellow(` âš ī¸ Verify source file changes, then add .env to .gitignore!\n`));
91
+ }
92
+ else {
93
+ console.log(chalk_1.default.yellow(`\n â„šī¸ Dry run complete. Run without --dry-run to apply changes.\n`));
94
+ }
95
+ }
96
+ //# sourceMappingURL=console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/reporter/console.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { ScanSummary } from '../types';
2
+ /**
3
+ * Writes a CSV report of the scan findings.
4
+ */
5
+ export declare function writeCsvReport(summary: ScanSummary, outputPath: string): void;
6
+ //# sourceMappingURL=csv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"csv.d.ts","sourceRoot":"","sources":["../../src/reporter/csv.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAevC;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAkC7E"}