vibecheck-score 0.1.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 (87) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +217 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/output/confirm.d.ts +3 -0
  6. package/dist/output/confirm.d.ts.map +1 -0
  7. package/dist/output/confirm.js +37 -0
  8. package/dist/output/confirm.js.map +1 -0
  9. package/dist/output/narrative.d.ts +3 -0
  10. package/dist/output/narrative.d.ts.map +1 -0
  11. package/dist/output/narrative.js +94 -0
  12. package/dist/output/narrative.js.map +1 -0
  13. package/dist/output/terminal.d.ts +4 -0
  14. package/dist/output/terminal.d.ts.map +1 -0
  15. package/dist/output/terminal.js +95 -0
  16. package/dist/output/terminal.js.map +1 -0
  17. package/dist/scanners/agents.d.ts +7 -0
  18. package/dist/scanners/agents.d.ts.map +1 -0
  19. package/dist/scanners/agents.js +95 -0
  20. package/dist/scanners/agents.js.map +1 -0
  21. package/dist/scanners/deploy.d.ts +7 -0
  22. package/dist/scanners/deploy.d.ts.map +1 -0
  23. package/dist/scanners/deploy.js +139 -0
  24. package/dist/scanners/deploy.js.map +1 -0
  25. package/dist/scanners/environment.d.ts +7 -0
  26. package/dist/scanners/environment.d.ts.map +1 -0
  27. package/dist/scanners/environment.js +110 -0
  28. package/dist/scanners/environment.js.map +1 -0
  29. package/dist/scanners/index.d.ts +7 -0
  30. package/dist/scanners/index.d.ts.map +1 -0
  31. package/dist/scanners/index.js +23 -0
  32. package/dist/scanners/index.js.map +1 -0
  33. package/dist/scanners/mcp.d.ts +7 -0
  34. package/dist/scanners/mcp.d.ts.map +1 -0
  35. package/dist/scanners/mcp.js +138 -0
  36. package/dist/scanners/mcp.js.map +1 -0
  37. package/dist/scanners/memory.d.ts +7 -0
  38. package/dist/scanners/memory.d.ts.map +1 -0
  39. package/dist/scanners/memory.js +131 -0
  40. package/dist/scanners/memory.js.map +1 -0
  41. package/dist/scanners/orchestration.d.ts +7 -0
  42. package/dist/scanners/orchestration.d.ts.map +1 -0
  43. package/dist/scanners/orchestration.js +99 -0
  44. package/dist/scanners/orchestration.js.map +1 -0
  45. package/dist/scanners/repositories.d.ts +7 -0
  46. package/dist/scanners/repositories.d.ts.map +1 -0
  47. package/dist/scanners/repositories.js +301 -0
  48. package/dist/scanners/repositories.js.map +1 -0
  49. package/dist/scanners/security.d.ts +7 -0
  50. package/dist/scanners/security.d.ts.map +1 -0
  51. package/dist/scanners/security.js +113 -0
  52. package/dist/scanners/security.js.map +1 -0
  53. package/dist/scanners/social.d.ts +7 -0
  54. package/dist/scanners/social.d.ts.map +1 -0
  55. package/dist/scanners/social.js +68 -0
  56. package/dist/scanners/social.js.map +1 -0
  57. package/dist/scanners/universal-file.d.ts +10 -0
  58. package/dist/scanners/universal-file.d.ts.map +1 -0
  59. package/dist/scanners/universal-file.js +526 -0
  60. package/dist/scanners/universal-file.js.map +1 -0
  61. package/dist/scanners/utils.d.ts +6 -0
  62. package/dist/scanners/utils.d.ts.map +1 -0
  63. package/dist/scanners/utils.js +51 -0
  64. package/dist/scanners/utils.js.map +1 -0
  65. package/dist/scanners/workspace.d.ts +3 -0
  66. package/dist/scanners/workspace.d.ts.map +1 -0
  67. package/dist/scanners/workspace.js +59 -0
  68. package/dist/scanners/workspace.js.map +1 -0
  69. package/dist/scoring/engine.d.ts +11 -0
  70. package/dist/scoring/engine.d.ts.map +1 -0
  71. package/dist/scoring/engine.js +85 -0
  72. package/dist/scoring/engine.js.map +1 -0
  73. package/dist/scoring/tiers.d.ts +11 -0
  74. package/dist/scoring/tiers.d.ts.map +1 -0
  75. package/dist/scoring/tiers.js +20 -0
  76. package/dist/scoring/tiers.js.map +1 -0
  77. package/dist/taxonomy/classifier.d.ts +9 -0
  78. package/dist/taxonomy/classifier.d.ts.map +1 -0
  79. package/dist/taxonomy/classifier.js +44 -0
  80. package/dist/taxonomy/classifier.js.map +1 -0
  81. package/dist/taxonomy/registry.json +189 -0
  82. package/dist/types.d.ts +109 -0
  83. package/dist/types.d.ts.map +1 -0
  84. package/dist/types.js +58 -0
  85. package/dist/types.js.map +1 -0
  86. package/package.json +44 -0
  87. package/src/taxonomy/registry.json +189 -0
@@ -0,0 +1,99 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import { classify } from "../taxonomy/classifier.js";
3
+ import { fileExists, shellOutput, expandHome } from "./utils.js";
4
+ export class OrchestrationScanner {
5
+ name = "orchestration";
6
+ async scan() {
7
+ const start = performance.now();
8
+ const findings = [];
9
+ // tmux
10
+ const tmux = await shellOutput("which tmux");
11
+ if (tmux) {
12
+ const hasTmuxConf = await fileExists("~/.tmux.conf");
13
+ findings.push({
14
+ id: "tmux",
15
+ source: hasTmuxConf ? "~/.tmux.conf" : "which tmux",
16
+ confidence: hasTmuxConf ? "high" : "medium",
17
+ });
18
+ }
19
+ // git worktrees
20
+ const worktrees = await shellOutput("git worktree list");
21
+ if (worktrees) {
22
+ const count = worktrees.split("\n").length;
23
+ if (count > 1) {
24
+ findings.push({
25
+ id: "git-worktrees",
26
+ source: "git worktree list",
27
+ confidence: "high",
28
+ details: { worktreeCount: count },
29
+ });
30
+ }
31
+ }
32
+ // Orchestrator CLIs
33
+ const orchestrators = [
34
+ { cmd: "which gt", id: "orchestrator-gastown" },
35
+ { cmd: "which claude-flow", id: "orchestrator-claudeflow" },
36
+ { cmd: "which openclaw", id: "orchestrator-openclaw" },
37
+ { cmd: "which devswarm", id: "orchestrator-devswarm" },
38
+ ];
39
+ const orchResults = await Promise.all(orchestrators.map(({ cmd }) => shellOutput(cmd)));
40
+ for (let i = 0; i < orchestrators.length; i++) {
41
+ if (orchResults[i]) {
42
+ findings.push({
43
+ id: orchestrators[i].id,
44
+ source: orchestrators[i].cmd,
45
+ confidence: "high",
46
+ });
47
+ }
48
+ }
49
+ // HEARTBEAT.md
50
+ const heartbeatPaths = ["HEARTBEAT.md", "~/HEARTBEAT.md"];
51
+ for (const path of heartbeatPaths) {
52
+ if (await fileExists(path)) {
53
+ findings.push({
54
+ id: "heartbeat",
55
+ source: path,
56
+ confidence: "high",
57
+ });
58
+ break;
59
+ }
60
+ }
61
+ // Crontab for agent-related entries
62
+ const crontab = await shellOutput("crontab -l");
63
+ if (crontab) {
64
+ const agentPatterns = /claude|agent|heartbeat|sweep|cron.*ai/i;
65
+ if (agentPatterns.test(crontab)) {
66
+ findings.push({
67
+ id: "parallel-scripts",
68
+ source: "crontab",
69
+ confidence: "medium",
70
+ details: { type: "crontab" },
71
+ });
72
+ }
73
+ }
74
+ // macOS LaunchAgents
75
+ try {
76
+ const launchAgentsDir = expandHome("~/Library/LaunchAgents");
77
+ const plists = await readdir(launchAgentsDir);
78
+ const agentPlists = plists.filter((p) => /claude|claude-?flow|openclaw|devswarm|heartbeat|ai-?agent/i.test(p) &&
79
+ p.endsWith(".plist"));
80
+ if (agentPlists.length > 0) {
81
+ findings.push({
82
+ id: "parallel-scripts",
83
+ source: "~/Library/LaunchAgents/",
84
+ confidence: "medium",
85
+ details: { plists: agentPlists },
86
+ });
87
+ }
88
+ }
89
+ catch {
90
+ // directory doesn't exist or not macOS
91
+ }
92
+ return {
93
+ scanner: this.name,
94
+ detections: classify(findings),
95
+ duration: Math.round(performance.now() - start),
96
+ };
97
+ }
98
+ }
99
+ //# sourceMappingURL=orchestration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestration.js","sourceRoot":"","sources":["../../src/scanners/orchestration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ScanResult } from "../types.js";
2
+ import type { Scanner } from "./index.js";
3
+ export declare class RepositoriesScanner implements Scanner {
4
+ name: string;
5
+ scan(): Promise<ScanResult>;
6
+ }
7
+ //# sourceMappingURL=repositories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositories.d.ts","sourceRoot":"","sources":["../../src/scanners/repositories.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AA8D1C,qBAAa,mBAAoB,YAAW,OAAO;IACjD,IAAI,SAAkB;IAEhB,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;CAgSlC"}
@@ -0,0 +1,301 @@
1
+ import { readdir } from "node:fs/promises";
2
+ import { classify } from "../taxonomy/classifier.js";
3
+ import { fileExists, readJsonIfExists, readFileIfExists } from "./utils.js";
4
+ const SKIP_DIRS = new Set(["node_modules", ".git", "dist", "build", ".next", ".turbo"]);
5
+ const CODE_QUALITY_CONFIGS = [
6
+ { globs: ["eslint.config.js", "eslint.config.mjs", "eslint.config.cjs", "eslint.config.ts", ".eslintrc", ".eslintrc.js", ".eslintrc.json", ".eslintrc.yml"], id: "eslint" },
7
+ { globs: ["prettier.config.js", "prettier.config.mjs", "prettier.config.cjs", ".prettierrc", ".prettierrc.js", ".prettierrc.json", ".prettierrc.yml"], id: "prettier" },
8
+ { globs: ["biome.json", "biome.jsonc"], id: "biome" },
9
+ ];
10
+ const TEST_CONFIGS = [
11
+ { glob: "vitest.config", id: "vitest" },
12
+ { glob: "jest.config", id: "jest" },
13
+ { glob: "pytest.ini", id: "pytest" },
14
+ ];
15
+ const E2E_CONFIGS = [
16
+ { glob: "playwright.config", id: "playwright" },
17
+ { glob: "cypress.config", id: "cypress" },
18
+ ];
19
+ const MONOREPO_TOOLS = [
20
+ { file: "turbo.json", id: "turbo" },
21
+ { file: "nx.json", id: "nx" },
22
+ { file: "pnpm-workspace.yaml", id: "pnpm-workspace" },
23
+ { file: "lerna.json", id: "lerna" },
24
+ ];
25
+ async function findSubProjects() {
26
+ const dirs = [];
27
+ try {
28
+ const level1 = await readdir(".", { withFileTypes: true });
29
+ for (const d of level1) {
30
+ if (!d.isDirectory() || SKIP_DIRS.has(d.name))
31
+ continue;
32
+ if (await fileExists(`${d.name}/package.json`))
33
+ dirs.push(d.name);
34
+ try {
35
+ const level2 = await readdir(d.name, { withFileTypes: true });
36
+ for (const d2 of level2) {
37
+ if (!d2.isDirectory() || SKIP_DIRS.has(d2.name))
38
+ continue;
39
+ const path = `${d.name}/${d2.name}`;
40
+ if (await fileExists(`${path}/package.json`))
41
+ dirs.push(path);
42
+ }
43
+ }
44
+ catch { /* not readable */ }
45
+ }
46
+ }
47
+ catch { /* cwd not readable */ }
48
+ return dirs;
49
+ }
50
+ export class RepositoriesScanner {
51
+ name = "repositories";
52
+ async scan() {
53
+ const start = performance.now();
54
+ const findings = [];
55
+ // GitHub Actions workflows
56
+ try {
57
+ const workflows = await readdir(".github/workflows");
58
+ const ymlFiles = workflows.filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"));
59
+ if (ymlFiles.length > 0) {
60
+ findings.push({
61
+ id: "github-actions",
62
+ source: ".github/workflows/",
63
+ confidence: "high",
64
+ details: { workflowCount: ymlFiles.length },
65
+ });
66
+ }
67
+ }
68
+ catch {
69
+ // no workflows dir
70
+ }
71
+ // Test framework configs
72
+ for (const { glob, id } of TEST_CONFIGS) {
73
+ const extensions = ["", ".ts", ".js", ".mjs", ".cjs"];
74
+ for (const ext of extensions) {
75
+ if (await fileExists(`${glob}${ext}`)) {
76
+ findings.push({ id, source: `${glob}${ext}`, confidence: "high" });
77
+ break;
78
+ }
79
+ }
80
+ }
81
+ // E2E test framework configs
82
+ for (const { glob, id } of E2E_CONFIGS) {
83
+ const extensions = ["", ".ts", ".js", ".mjs", ".cjs"];
84
+ for (const ext of extensions) {
85
+ if (await fileExists(`${glob}${ext}`)) {
86
+ findings.push({ id, source: `${glob}${ext}`, confidence: "high" });
87
+ break;
88
+ }
89
+ }
90
+ }
91
+ // Code quality configs
92
+ for (const { globs, id } of CODE_QUALITY_CONFIGS) {
93
+ for (const file of globs) {
94
+ if (await fileExists(file)) {
95
+ findings.push({ id, source: file, confidence: "high" });
96
+ break;
97
+ }
98
+ }
99
+ }
100
+ // TypeScript strict mode
101
+ const tsconfig = await readJsonIfExists("tsconfig.json");
102
+ if (tsconfig?.compilerOptions?.strict === true) {
103
+ findings.push({
104
+ id: "typescript-strict",
105
+ source: "tsconfig.json",
106
+ confidence: "high",
107
+ });
108
+ }
109
+ // Also check pyproject.toml for pytest
110
+ const pyproject = await readFileIfExists("pyproject.toml");
111
+ if (pyproject && /\[tool\.pytest/i.test(pyproject)) {
112
+ const hasPytest = findings.some((f) => f.id === "pytest");
113
+ if (!hasPytest) {
114
+ findings.push({
115
+ id: "pytest",
116
+ source: "pyproject.toml",
117
+ confidence: "high",
118
+ });
119
+ }
120
+ }
121
+ // Package.json scripts analysis
122
+ const pkg = await readJsonIfExists("package.json");
123
+ if (pkg?.scripts) {
124
+ const scriptNames = Object.keys(pkg.scripts);
125
+ const scriptValues = Object.values(pkg.scripts);
126
+ // npm-scripts detection
127
+ const hasDevOps = scriptNames.some((s) => /^(build|dev|lint|start|test|format|typecheck)$/.test(s));
128
+ if (hasDevOps) {
129
+ findings.push({
130
+ id: "npm-scripts",
131
+ source: "package.json",
132
+ confidence: "high",
133
+ details: { scripts: scriptNames },
134
+ });
135
+ }
136
+ // Maintenance scripts
137
+ const hasMaintenance = scriptNames.some((s) => /clean|migrate|seed|reset|setup|postinstall/.test(s));
138
+ if (hasMaintenance) {
139
+ findings.push({
140
+ id: "maintenance-scripts",
141
+ source: "package.json",
142
+ confidence: "medium",
143
+ });
144
+ }
145
+ // Kanban integration
146
+ const hasKanban = scriptValues.some((v) => /linear|jira|notion|asana/i.test(v));
147
+ if (hasKanban) {
148
+ findings.push({
149
+ id: "kanban-integration",
150
+ source: "package.json",
151
+ confidence: "medium",
152
+ });
153
+ }
154
+ // Automated docs
155
+ const hasDocs = scriptValues.some((v) => /typedoc|jsdoc|storybook|docusaurus/i.test(v));
156
+ if (hasDocs) {
157
+ findings.push({
158
+ id: "automated-docs",
159
+ source: "package.json",
160
+ confidence: "high",
161
+ });
162
+ }
163
+ // Monitoring config
164
+ const hasMonitoring = scriptValues.some((v) => /sentry|datadog|newrelic/i.test(v));
165
+ const deps = {
166
+ ...(pkg.dependencies ?? {}),
167
+ ...(pkg.devDependencies ?? {}),
168
+ };
169
+ const hasMonitoringDep = Object.keys(deps).some((d) => /sentry|datadog|newrelic/i.test(d));
170
+ if (hasMonitoring || hasMonitoringDep) {
171
+ findings.push({
172
+ id: "monitoring-config",
173
+ source: "package.json",
174
+ confidence: "medium",
175
+ });
176
+ }
177
+ }
178
+ // Makefile / scripts directory
179
+ if (await fileExists("Makefile")) {
180
+ const hasMaintenance = findings.some((f) => f.id === "maintenance-scripts");
181
+ if (!hasMaintenance) {
182
+ findings.push({
183
+ id: "maintenance-scripts",
184
+ source: "Makefile",
185
+ confidence: "medium",
186
+ });
187
+ }
188
+ }
189
+ try {
190
+ await readdir("scripts");
191
+ const hasMaintenance = findings.some((f) => f.id === "maintenance-scripts");
192
+ if (!hasMaintenance) {
193
+ findings.push({
194
+ id: "maintenance-scripts",
195
+ source: "scripts/",
196
+ confidence: "medium",
197
+ });
198
+ }
199
+ }
200
+ catch {
201
+ // no scripts dir
202
+ }
203
+ // Documentation
204
+ if (await fileExists("README.md")) {
205
+ findings.push({
206
+ id: "documentation",
207
+ source: "README.md",
208
+ confidence: "high",
209
+ });
210
+ }
211
+ // Task tracking
212
+ const claudeMd = await readFileIfExists("CLAUDE.md");
213
+ if (claudeMd && /todo|task|backlog/i.test(claudeMd)) {
214
+ findings.push({
215
+ id: "task-tracking",
216
+ source: "CLAUDE.md",
217
+ confidence: "medium",
218
+ });
219
+ }
220
+ // Monitoring config files
221
+ const monitorConfigs = [
222
+ "sentry.client.config.ts",
223
+ "sentry.server.config.ts",
224
+ "sentry.config.ts",
225
+ "datadog.config.ts",
226
+ ];
227
+ for (const cfg of monitorConfigs) {
228
+ if (await fileExists(cfg)) {
229
+ const hasMonitoring = findings.some((f) => f.id === "monitoring-config");
230
+ if (!hasMonitoring) {
231
+ findings.push({
232
+ id: "monitoring-config",
233
+ source: cfg,
234
+ confidence: "high",
235
+ });
236
+ }
237
+ break;
238
+ }
239
+ }
240
+ // Monorepo orchestration tools
241
+ for (const { file, id } of MONOREPO_TOOLS) {
242
+ if (await fileExists(file)) {
243
+ findings.push({ id, source: file, confidence: "high" });
244
+ }
245
+ }
246
+ // Sub-project scanning: walk 2 levels deep for package.json dirs
247
+ const seenIds = new Set(findings.map((f) => f.id));
248
+ const subProjects = await findSubProjects();
249
+ for (const dir of subProjects) {
250
+ // Config-based checks in sub-projects
251
+ const extensions = ["", ".ts", ".js", ".mjs", ".cjs"];
252
+ for (const { glob, id } of TEST_CONFIGS) {
253
+ if (seenIds.has(id))
254
+ continue;
255
+ for (const ext of extensions) {
256
+ if (await fileExists(`${dir}/${glob}${ext}`)) {
257
+ findings.push({ id, source: `${dir}/${glob}${ext}`, confidence: "high" });
258
+ seenIds.add(id);
259
+ break;
260
+ }
261
+ }
262
+ }
263
+ for (const { glob, id } of E2E_CONFIGS) {
264
+ if (seenIds.has(id))
265
+ continue;
266
+ for (const ext of extensions) {
267
+ if (await fileExists(`${dir}/${glob}${ext}`)) {
268
+ findings.push({ id, source: `${dir}/${glob}${ext}`, confidence: "high" });
269
+ seenIds.add(id);
270
+ break;
271
+ }
272
+ }
273
+ }
274
+ for (const { globs, id } of CODE_QUALITY_CONFIGS) {
275
+ if (seenIds.has(id))
276
+ continue;
277
+ for (const file of globs) {
278
+ if (await fileExists(`${dir}/${file}`)) {
279
+ findings.push({ id, source: `${dir}/${file}`, confidence: "high" });
280
+ seenIds.add(id);
281
+ break;
282
+ }
283
+ }
284
+ }
285
+ // TypeScript strict in sub-project
286
+ if (!seenIds.has("typescript-strict")) {
287
+ const subTsconfig = await readJsonIfExists(`${dir}/tsconfig.json`);
288
+ if (subTsconfig?.compilerOptions?.strict === true) {
289
+ findings.push({ id: "typescript-strict", source: `${dir}/tsconfig.json`, confidence: "high" });
290
+ seenIds.add("typescript-strict");
291
+ }
292
+ }
293
+ }
294
+ return {
295
+ scanner: this.name,
296
+ detections: classify(findings),
297
+ duration: Math.round(performance.now() - start),
298
+ };
299
+ }
300
+ }
301
+ //# sourceMappingURL=repositories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repositories.js","sourceRoot":"","sources":["../../src/scanners/repositories.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ScanResult } from "../types.js";
2
+ import type { Scanner } from "./index.js";
3
+ export declare class SecurityScanner implements Scanner {
4
+ name: string;
5
+ scan(): Promise<ScanResult>;
6
+ }
7
+ //# sourceMappingURL=security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../../src/scanners/security.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAgB1C,qBAAa,eAAgB,YAAW,OAAO;IAC7C,IAAI,SAAc;IAEZ,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;CAuHlC"}
@@ -0,0 +1,113 @@
1
+ import { stat } from "node:fs/promises";
2
+ import { classify } from "../taxonomy/classifier.js";
3
+ import { readFileIfExists, readJsonIfExists, expandHome, } from "./utils.js";
4
+ export class SecurityScanner {
5
+ name = "security";
6
+ async scan() {
7
+ const start = performance.now();
8
+ const findings = [];
9
+ // .gitignore covers .env
10
+ const gitignore = await readFileIfExists(".gitignore");
11
+ if (gitignore) {
12
+ const envPatterns = /^\.env/m;
13
+ if (envPatterns.test(gitignore)) {
14
+ findings.push({
15
+ id: "gitignore-env",
16
+ source: ".gitignore",
17
+ confidence: "high",
18
+ });
19
+ }
20
+ }
21
+ // Environment variable secrets (just presence detection)
22
+ const shellFiles = [
23
+ "~/.zshrc",
24
+ "~/.bashrc",
25
+ "~/.zprofile",
26
+ "~/.bash_profile",
27
+ ];
28
+ for (const file of shellFiles) {
29
+ const content = await readFileIfExists(file);
30
+ if (content && /export\s+\w*(KEY|SECRET|TOKEN|PASSWORD)\w*\s*=/i.test(content)) {
31
+ findings.push({
32
+ id: "env-vars",
33
+ source: file,
34
+ confidence: "high",
35
+ });
36
+ break;
37
+ }
38
+ }
39
+ // Agent permission scoping
40
+ const settings = await readJsonIfExists(".claude/settings.json");
41
+ if (settings) {
42
+ const hasPermissions = settings.allowedTools ||
43
+ settings.blockedCommands ||
44
+ settings.permissions;
45
+ if (hasPermissions) {
46
+ findings.push({
47
+ id: "agent-permissions",
48
+ source: ".claude/settings.json",
49
+ confidence: "medium",
50
+ });
51
+ }
52
+ }
53
+ // File permissions on sensitive files
54
+ const sensitiveFiles = [
55
+ "~/.ssh/id_rsa",
56
+ "~/.ssh/id_ed25519",
57
+ "~/.env",
58
+ ".env",
59
+ ];
60
+ for (const file of sensitiveFiles) {
61
+ try {
62
+ const s = await stat(expandHome(file));
63
+ const perms = s.mode & 0o777;
64
+ // Owner-only read/write is secure (0o600 or 0o400)
65
+ if (perms <= 0o600) {
66
+ findings.push({
67
+ id: "file-permissions",
68
+ source: file,
69
+ confidence: "high",
70
+ details: { permissions: `0o${perms.toString(8)}` },
71
+ });
72
+ break;
73
+ }
74
+ }
75
+ catch {
76
+ // file doesn't exist
77
+ }
78
+ }
79
+ // Canary tokens
80
+ const configFiles = ["CLAUDE.md", "AGENTS.md", ".claude/settings.json"];
81
+ for (const file of configFiles) {
82
+ const content = await readFileIfExists(file);
83
+ if (content && /canary|honeypot|tripwire/i.test(content)) {
84
+ findings.push({
85
+ id: "canary-tokens",
86
+ source: file,
87
+ confidence: "medium",
88
+ });
89
+ break;
90
+ }
91
+ }
92
+ // Prompt injection defense
93
+ const defenseFiles = ["CLAUDE.md", "AGENTS.md"];
94
+ for (const file of defenseFiles) {
95
+ const content = await readFileIfExists(file);
96
+ if (content &&
97
+ /prompt.?injection|safety.?boundar|injection.?defense|do not execute/i.test(content)) {
98
+ findings.push({
99
+ id: "prompt-injection-defense",
100
+ source: file,
101
+ confidence: "medium",
102
+ });
103
+ break;
104
+ }
105
+ }
106
+ return {
107
+ scanner: this.name,
108
+ detections: classify(findings),
109
+ duration: Math.round(performance.now() - start),
110
+ };
111
+ }
112
+ }
113
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/scanners/security.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { ScanResult } from "../types.js";
2
+ import type { Scanner } from "./index.js";
3
+ export declare class SocialScanner implements Scanner {
4
+ name: string;
5
+ scan(): Promise<ScanResult>;
6
+ }
7
+ //# sourceMappingURL=social.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"social.d.ts","sourceRoot":"","sources":["../../src/scanners/social.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAU1C,qBAAa,aAAc,YAAW,OAAO;IAC3C,IAAI,SAAY;IAEV,IAAI,IAAI,OAAO,CAAC,UAAU,CAAC;CAmElC"}
@@ -0,0 +1,68 @@
1
+ import { classify } from "../taxonomy/classifier.js";
2
+ import { shellOutput, readJsonIfExists, readFileIfExists } from "./utils.js";
3
+ export class SocialScanner {
4
+ name = "social";
5
+ async scan() {
6
+ const start = performance.now();
7
+ const findings = [];
8
+ // git remote for github.com
9
+ const remotes = await shellOutput("git remote -v");
10
+ if (remotes && /github\.com/i.test(remotes)) {
11
+ findings.push({
12
+ id: "github-repos",
13
+ source: "git remote -v",
14
+ confidence: "medium",
15
+ });
16
+ }
17
+ // package.json private field
18
+ const pkg = await readJsonIfExists("package.json");
19
+ if (pkg && pkg.private === false) {
20
+ findings.push({
21
+ id: "npm-public",
22
+ source: "package.json",
23
+ confidence: "high",
24
+ details: { packageName: pkg.name },
25
+ });
26
+ }
27
+ // Slack/Discord webhook patterns in configs
28
+ const configFiles = [
29
+ ".env",
30
+ ".env.local",
31
+ "package.json",
32
+ ];
33
+ for (const file of configFiles) {
34
+ const content = await readFileIfExists(file);
35
+ if (!content)
36
+ continue;
37
+ if (/SLACK_WEBHOOK|slack.*webhook/i.test(content)) {
38
+ findings.push({
39
+ id: "slack-webhook",
40
+ source: file,
41
+ confidence: "medium",
42
+ });
43
+ }
44
+ if (/DISCORD_WEBHOOK|DISCORD_BOT_TOKEN|discord.*webhook/i.test(content)) {
45
+ findings.push({
46
+ id: "discord-bot",
47
+ source: file,
48
+ confidence: "medium",
49
+ });
50
+ }
51
+ }
52
+ // npm org scope in package name
53
+ if (pkg?.name && pkg.name.startsWith("@") && pkg.private !== true) {
54
+ findings.push({
55
+ id: "npm-public",
56
+ source: "package.json",
57
+ confidence: "medium",
58
+ details: { scope: pkg.name.split("/")[0] },
59
+ });
60
+ }
61
+ return {
62
+ scanner: this.name,
63
+ detections: classify(findings),
64
+ duration: Math.round(performance.now() - start),
65
+ };
66
+ }
67
+ }
68
+ //# sourceMappingURL=social.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"social.js","sourceRoot":"","sources":["../../src/scanners/social.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAmB,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAQ7E,MAAM,OAAO,aAAa;IACxB,IAAI,GAAG,QAAQ,CAAC;IAEhB,KAAK,CAAC,IAAI;QACR,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAiB,EAAE,CAAC;QAElC,4BAA4B;QAC5B,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,CAAC;QACnD,IAAI,OAAO,IAAI,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,cAAc;gBAClB,MAAM,EAAE,eAAe;gBACvB,UAAU,EAAE,QAAQ;aACrB,CAAC,CAAC;QACL,CAAC;QAED,6BAA6B;QAC7B,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAc,cAAc,CAAC,CAAC;QAChE,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YACjC,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,YAAY;gBAChB,MAAM,EAAE,cAAc;gBACtB,UAAU,EAAE,MAAM;gBAClB,OAAO,EAAE,EAAE,WAAW,EAAE,GAAG,CAAC,IAAI,EAAE;aACnC,CAAC,CAAC;QACL,CAAC;QAED,4CAA4C;QAC5C,MAAM,WAAW,GAAG;YAClB,MAAM;YACN,YAAY;YACZ,cAAc;SACf,CAAC;QACF,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC;YAC7C,IAAI,CAAC,OAAO;gBAAE,SAAS;YAEvB,IAAI,+BAA+B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAClD,QAAQ,CAAC,IAAI,CAAC;oBACZ,EAAE,EAAE,eAAe;oBACnB,MAAM,EAAE,IAAI;oBACZ,UAAU,EAAE,QAAQ;iBACrB,CAAC,CAAC;YACL,CAAC;YACD,IAAI,qDAAqD,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxE,QAAQ,CAAC,IAAI,CAAC;oBACZ,EAAE,EAAE,aAAa;oBACjB,MAAM,EAAE,IAAI;oBACZ,UAAU,EAAE,QAAQ;iBACrB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,gCAAgC;QAChC,IAAI,GAAG,EAAE,IAAI,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAClE,QAAQ,CAAC,IAAI,CAAC;gBACZ,EAAE,EAAE,YAAY;gBAChB,MAAM,EAAE,cAAc;gBACtB,UAAU,EAAE,QAAQ;gBACpB,OAAO,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;aAC3C,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,IAAI;YAClB,UAAU,EAAE,QAAQ,CAAC,QAAQ,CAAC;YAC9B,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;SAChD,CAAC;IACJ,CAAC;CACF"}