@rahul-sch/vibeguard 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 (93) hide show
  1. package/README.md +162 -0
  2. package/bin/vibeguard.js +2 -0
  3. package/dist/ai/cache.d.ts +5 -0
  4. package/dist/ai/cache.js +20 -0
  5. package/dist/ai/index.d.ts +9 -0
  6. package/dist/ai/index.js +71 -0
  7. package/dist/ai/prompts.d.ts +7 -0
  8. package/dist/ai/prompts.js +65 -0
  9. package/dist/ai/provider.d.ts +12 -0
  10. package/dist/ai/provider.js +93 -0
  11. package/dist/ai/types.d.ts +21 -0
  12. package/dist/ai/types.js +1 -0
  13. package/dist/cli/commands/fix.d.ts +7 -0
  14. package/dist/cli/commands/fix.js +140 -0
  15. package/dist/cli/commands/github.d.ts +6 -0
  16. package/dist/cli/commands/github.js +24 -0
  17. package/dist/cli/commands/scan.d.ts +5 -0
  18. package/dist/cli/commands/scan.js +54 -0
  19. package/dist/cli/index.d.ts +1 -0
  20. package/dist/cli/index.js +49 -0
  21. package/dist/cli/options.d.ts +17 -0
  22. package/dist/cli/options.js +27 -0
  23. package/dist/config/defaults.d.ts +17 -0
  24. package/dist/config/defaults.js +21 -0
  25. package/dist/config/index.d.ts +17 -0
  26. package/dist/config/index.js +119 -0
  27. package/dist/config/schema.d.ts +20 -0
  28. package/dist/config/schema.js +39 -0
  29. package/dist/engine/file-walker.d.ts +12 -0
  30. package/dist/engine/file-walker.js +61 -0
  31. package/dist/engine/filter.d.ts +3 -0
  32. package/dist/engine/filter.js +50 -0
  33. package/dist/engine/index.d.ts +10 -0
  34. package/dist/engine/index.js +54 -0
  35. package/dist/engine/matcher.d.ts +10 -0
  36. package/dist/engine/matcher.js +47 -0
  37. package/dist/fix/engine.d.ts +37 -0
  38. package/dist/fix/engine.js +121 -0
  39. package/dist/fix/index.d.ts +2 -0
  40. package/dist/fix/index.js +2 -0
  41. package/dist/fix/patch.d.ts +23 -0
  42. package/dist/fix/patch.js +94 -0
  43. package/dist/fix/strategies.d.ts +21 -0
  44. package/dist/fix/strategies.js +213 -0
  45. package/dist/fix/types.d.ts +48 -0
  46. package/dist/fix/types.js +1 -0
  47. package/dist/github/client.d.ts +10 -0
  48. package/dist/github/client.js +43 -0
  49. package/dist/github/comment-formatter.d.ts +3 -0
  50. package/dist/github/comment-formatter.js +65 -0
  51. package/dist/github/index.d.ts +5 -0
  52. package/dist/github/index.js +5 -0
  53. package/dist/github/installer.d.ts +2 -0
  54. package/dist/github/installer.js +41 -0
  55. package/dist/github/types.d.ts +40 -0
  56. package/dist/github/types.js +1 -0
  57. package/dist/github/workflow-generator.d.ts +2 -0
  58. package/dist/github/workflow-generator.js +108 -0
  59. package/dist/index.d.ts +2 -0
  60. package/dist/index.js +2 -0
  61. package/dist/reporters/console.d.ts +9 -0
  62. package/dist/reporters/console.js +76 -0
  63. package/dist/reporters/index.d.ts +6 -0
  64. package/dist/reporters/index.js +17 -0
  65. package/dist/reporters/json.d.ts +5 -0
  66. package/dist/reporters/json.js +32 -0
  67. package/dist/reporters/sarif.d.ts +9 -0
  68. package/dist/reporters/sarif.js +78 -0
  69. package/dist/reporters/types.d.ts +5 -0
  70. package/dist/reporters/types.js +1 -0
  71. package/dist/rules/config.d.ts +2 -0
  72. package/dist/rules/config.js +31 -0
  73. package/dist/rules/dependencies.d.ts +2 -0
  74. package/dist/rules/dependencies.js +32 -0
  75. package/dist/rules/docker.d.ts +2 -0
  76. package/dist/rules/docker.js +44 -0
  77. package/dist/rules/index.d.ts +5 -0
  78. package/dist/rules/index.js +25 -0
  79. package/dist/rules/kubernetes.d.ts +2 -0
  80. package/dist/rules/kubernetes.js +44 -0
  81. package/dist/rules/node.d.ts +2 -0
  82. package/dist/rules/node.js +72 -0
  83. package/dist/rules/python.d.ts +2 -0
  84. package/dist/rules/python.js +91 -0
  85. package/dist/rules/secrets.d.ts +2 -0
  86. package/dist/rules/secrets.js +82 -0
  87. package/dist/rules/types.d.ts +75 -0
  88. package/dist/rules/types.js +1 -0
  89. package/dist/utils/binary-check.d.ts +1 -0
  90. package/dist/utils/binary-check.js +10 -0
  91. package/dist/utils/line-mapper.d.ts +6 -0
  92. package/dist/utils/line-mapper.js +40 -0
  93. package/package.json +52 -0
@@ -0,0 +1,5 @@
1
+ import type { DetectionRule } from './types.js';
2
+ export declare const allRules: DetectionRule[];
3
+ export declare const ruleById: Map<string, DetectionRule>;
4
+ export declare const rulesByLanguage: Map<string, DetectionRule[]>;
5
+ export { type DetectionRule, type Finding, type ScanConfig, type ScanResult } from './types.js';
@@ -0,0 +1,25 @@
1
+ import { secretsRules } from './secrets.js';
2
+ import { pythonRules } from './python.js';
3
+ import { nodeRules } from './node.js';
4
+ import { dockerRules } from './docker.js';
5
+ import { kubernetesRules } from './kubernetes.js';
6
+ import { configRules } from './config.js';
7
+ import { dependencyRules } from './dependencies.js';
8
+ export const allRules = [
9
+ ...secretsRules,
10
+ ...pythonRules,
11
+ ...nodeRules,
12
+ ...dockerRules,
13
+ ...kubernetesRules,
14
+ ...configRules,
15
+ ...dependencyRules,
16
+ ];
17
+ export const ruleById = new Map(allRules.map((r) => [r.id, r]));
18
+ export const rulesByLanguage = new Map();
19
+ for (const rule of allRules) {
20
+ for (const lang of rule.languages) {
21
+ const existing = rulesByLanguage.get(lang) || [];
22
+ existing.push(rule);
23
+ rulesByLanguage.set(lang, existing);
24
+ }
25
+ }
@@ -0,0 +1,2 @@
1
+ import type { DetectionRule } from './types.js';
2
+ export declare const kubernetesRules: DetectionRule[];
@@ -0,0 +1,44 @@
1
+ export const kubernetesRules = [
2
+ {
3
+ id: 'VG-K8S-001',
4
+ title: 'Cluster-Admin Role Binding',
5
+ severity: 'critical',
6
+ category: 'kubernetes',
7
+ languages: ['kubernetes', 'yaml'],
8
+ filePatterns: ['*.yml', '*.yaml'],
9
+ pattern: /cluster-?admin/gi,
10
+ message: 'cluster-admin role grants full cluster access. Compromised pod = compromised cluster.',
11
+ remediation: 'Use least-privilege RBAC. Create specific roles for required permissions.',
12
+ confidence: 'high',
13
+ cwe: 'CWE-250',
14
+ owasp: 'A01:2021',
15
+ },
16
+ {
17
+ id: 'VG-K8S-002',
18
+ title: 'Open Ingress Rules (0.0.0.0/0)',
19
+ severity: 'critical',
20
+ category: 'kubernetes',
21
+ languages: ['kubernetes', 'yaml'],
22
+ filePatterns: ['*.yml', '*.yaml'],
23
+ pattern: /(?:0\.0\.0\.0\/0|::\/0)/g,
24
+ message: 'Network policy allows traffic from any IP. Service exposed to entire internet.',
25
+ remediation: 'Restrict ingress to specific CIDR blocks or pod selectors.',
26
+ confidence: 'high',
27
+ cwe: 'CWE-284',
28
+ owasp: 'A01:2021',
29
+ },
30
+ {
31
+ id: 'VG-K8S-003',
32
+ title: 'Missing runAsNonRoot',
33
+ severity: 'warning',
34
+ category: 'kubernetes',
35
+ languages: ['kubernetes', 'yaml'],
36
+ filePatterns: ['*.yml', '*.yaml'],
37
+ pattern: /securityContext:(?:(?!runAsNonRoot\s*:\s*true)[\s\S])*?(?=securityContext:|$)/g,
38
+ message: 'Pod security context missing runAsNonRoot:true. Container may run as root.',
39
+ remediation: 'Add securityContext.runAsNonRoot: true to pod spec.',
40
+ confidence: 'medium',
41
+ cwe: 'CWE-250',
42
+ owasp: 'A05:2021',
43
+ },
44
+ ];
@@ -0,0 +1,2 @@
1
+ import type { DetectionRule } from './types.js';
2
+ export declare const nodeRules: DetectionRule[];
@@ -0,0 +1,72 @@
1
+ export const nodeRules = [
2
+ {
3
+ id: 'VG-NODE-001',
4
+ title: 'Child Process Exec',
5
+ severity: 'critical',
6
+ category: 'injection',
7
+ languages: ['node', 'typescript'],
8
+ filePatterns: ['*.js', '*.ts', '*.mjs', '*.cjs'],
9
+ pattern: /(?:child_process\.)?exec(?:Sync)?\s*\(`/g,
10
+ message: 'child_process.exec() runs commands in a shell. Untrusted input leads to command injection.',
11
+ remediation: 'Use child_process.spawn() or execFile() with argument arrays. Never pass user input to shell.',
12
+ confidence: 'high',
13
+ cwe: 'CWE-78',
14
+ owasp: 'A03:2021',
15
+ },
16
+ {
17
+ id: 'VG-NODE-002',
18
+ title: 'Spawn with Shell',
19
+ severity: 'critical',
20
+ category: 'injection',
21
+ languages: ['node', 'typescript'],
22
+ filePatterns: ['*.js', '*.ts', '*.mjs', '*.cjs'],
23
+ pattern: /spawn\s*\([^)]*\{\s*[^}]*shell\s*:\s*true/g,
24
+ message: 'spawn() with shell:true enables command injection via untrusted arguments.',
25
+ remediation: 'Remove shell:true. Pass commands and args separately.',
26
+ confidence: 'high',
27
+ cwe: 'CWE-78',
28
+ owasp: 'A03:2021',
29
+ },
30
+ {
31
+ id: 'VG-NODE-003',
32
+ title: 'Unsafe HTML Rendering (React)',
33
+ severity: 'critical',
34
+ category: 'injection',
35
+ languages: ['node', 'typescript'],
36
+ filePatterns: ['*.jsx', '*.tsx', '*.js', '*.ts'],
37
+ pattern: /dangerouslySetInnerHTML\s*=\s*\{\s*\{?\s*__html\s*:/g,
38
+ message: 'dangerouslySetInnerHTML renders raw HTML. User input causes XSS.',
39
+ remediation: 'Sanitize HTML with DOMPurify before rendering, or avoid raw HTML entirely.',
40
+ confidence: 'high',
41
+ cwe: 'CWE-79',
42
+ owasp: 'A03:2021',
43
+ },
44
+ {
45
+ id: 'VG-NODE-004',
46
+ title: 'Disabled TLS Verification',
47
+ severity: 'critical',
48
+ category: 'crypto',
49
+ languages: ['node', 'typescript'],
50
+ filePatterns: ['*.js', '*.ts', '*.mjs', '*.cjs'],
51
+ pattern: /rejectUnauthorized\s*:\s*false/g,
52
+ message: 'TLS certificate verification disabled. Vulnerable to MITM attacks.',
53
+ remediation: 'Remove rejectUnauthorized:false. Fix certificate chain issues properly.',
54
+ confidence: 'high',
55
+ cwe: 'CWE-295',
56
+ owasp: 'A02:2021',
57
+ },
58
+ {
59
+ id: 'VG-NODE-005',
60
+ title: 'TLS Reject Env Bypass',
61
+ severity: 'critical',
62
+ category: 'crypto',
63
+ languages: ['node', 'typescript'],
64
+ filePatterns: ['*.js', '*.ts', '*.mjs', '*.cjs'],
65
+ pattern: /NODE_TLS_REJECT_UNAUTHORIZED\s*=\s*['"]?0/g,
66
+ message: 'NODE_TLS_REJECT_UNAUTHORIZED=0 disables all TLS verification globally.',
67
+ remediation: 'Never disable TLS verification. Fix certificate issues at the source.',
68
+ confidence: 'high',
69
+ cwe: 'CWE-295',
70
+ owasp: 'A02:2021',
71
+ },
72
+ ];
@@ -0,0 +1,2 @@
1
+ import type { DetectionRule } from './types.js';
2
+ export declare const pythonRules: DetectionRule[];
@@ -0,0 +1,91 @@
1
+ export const pythonRules = [
2
+ {
3
+ id: 'VG-PY-001',
4
+ title: 'Shell Command Exec (shell=True)',
5
+ severity: 'critical',
6
+ category: 'injection',
7
+ languages: ['python'],
8
+ filePatterns: ['*.py'],
9
+ pattern: /subprocess\.\w+\s*\([^)]*shell\s*=\s*True/g,
10
+ message: 'subprocess with shell=True allows command injection if input is untrusted.',
11
+ remediation: 'Use shell=False and pass arguments as a list. Validate/sanitize all inputs.',
12
+ confidence: 'high',
13
+ cwe: 'CWE-78',
14
+ owasp: 'A03:2021',
15
+ fixable: true,
16
+ fixStrategy: 'shell-true-to-false',
17
+ },
18
+ {
19
+ id: 'VG-PY-002',
20
+ title: 'OS System Call',
21
+ severity: 'critical',
22
+ category: 'injection',
23
+ languages: ['python'],
24
+ filePatterns: ['*.py'],
25
+ pattern: /os\.system\s*\(/g,
26
+ message: 'os.system() executes shell commands. Vulnerable to command injection.',
27
+ remediation: 'Use subprocess.run() with shell=False and argument list.',
28
+ confidence: 'high',
29
+ cwe: 'CWE-78',
30
+ owasp: 'A03:2021',
31
+ },
32
+ {
33
+ id: 'VG-PY-003',
34
+ title: 'Unsafe YAML Load',
35
+ severity: 'critical',
36
+ category: 'deserialization',
37
+ languages: ['python'],
38
+ filePatterns: ['*.py'],
39
+ pattern: /yaml\.load\s*\([^)]*(?!Loader\s*=\s*yaml\.SafeLoader)/g,
40
+ allowPatterns: [/yaml\.safe_load/],
41
+ message: 'yaml.load() without SafeLoader can execute arbitrary Python objects.',
42
+ remediation: 'Use yaml.safe_load() or yaml.load(data, Loader=yaml.SafeLoader).',
43
+ confidence: 'high',
44
+ cwe: 'CWE-502',
45
+ owasp: 'A08:2021',
46
+ },
47
+ {
48
+ id: 'VG-PY-004',
49
+ title: 'Insecure Pickle Deserialization',
50
+ severity: 'critical',
51
+ category: 'deserialization',
52
+ languages: ['python'],
53
+ filePatterns: ['*.py'],
54
+ pattern: /pickle\.loads?\s*\(/g,
55
+ message: 'pickle deserializes arbitrary Python objects. Malicious payloads achieve RCE.',
56
+ remediation: 'Use JSON or other safe serialization. Never unpickle untrusted data.',
57
+ confidence: 'high',
58
+ cwe: 'CWE-502',
59
+ owasp: 'A08:2021',
60
+ },
61
+ {
62
+ id: 'VG-PY-005',
63
+ title: 'Flask Debug Mode Enabled',
64
+ severity: 'critical',
65
+ category: 'config',
66
+ languages: ['python'],
67
+ filePatterns: ['*.py'],
68
+ pattern: /app\.run\s*\([^)]*debug\s*=\s*True/g,
69
+ message: 'Flask debug mode exposes interactive debugger. Attackers can execute code via Werkzeug console.',
70
+ remediation: 'Set debug=False in production. Use environment variables for config.',
71
+ confidence: 'high',
72
+ cwe: 'CWE-489',
73
+ owasp: 'A05:2021',
74
+ },
75
+ {
76
+ id: 'VG-PY-006',
77
+ title: 'Disabled SSL Verification',
78
+ severity: 'critical',
79
+ category: 'crypto',
80
+ languages: ['python'],
81
+ filePatterns: ['*.py'],
82
+ pattern: /requests\.(?:get|post|put|delete|patch|head|options)\s*\([^)]*verify\s*=\s*False/g,
83
+ message: 'SSL verification disabled. Vulnerable to man-in-the-middle attacks.',
84
+ remediation: 'Remove verify=False. Fix certificate issues properly.',
85
+ confidence: 'high',
86
+ cwe: 'CWE-295',
87
+ owasp: 'A02:2021',
88
+ fixable: true,
89
+ fixStrategy: 'remove-verify-false',
90
+ },
91
+ ];
@@ -0,0 +1,2 @@
1
+ import type { DetectionRule } from './types.js';
2
+ export declare const secretsRules: DetectionRule[];
@@ -0,0 +1,82 @@
1
+ export const secretsRules = [
2
+ {
3
+ id: 'VG-SEC-001',
4
+ title: 'Dynamic Code Execution (eval)',
5
+ severity: 'critical',
6
+ category: 'injection',
7
+ languages: ['node', 'typescript', 'python'],
8
+ filePatterns: ['*.js', '*.ts', '*.jsx', '*.tsx', '*.mjs', '*.cjs', '*.py'],
9
+ pattern: /\beval\s*\(/g,
10
+ message: 'eval() executes arbitrary code. Attacker-controlled input leads to RCE.',
11
+ remediation: 'Use JSON.parse() for data, or a sandboxed interpreter if dynamic execution is required.',
12
+ confidence: 'high',
13
+ cwe: 'CWE-95',
14
+ owasp: 'A03:2021',
15
+ aiVerification: { enabled: true },
16
+ fixable: true,
17
+ fixStrategy: 'eval-to-json-parse',
18
+ },
19
+ {
20
+ id: 'VG-SEC-002',
21
+ title: 'SQL String Concatenation',
22
+ severity: 'critical',
23
+ category: 'injection',
24
+ languages: ['node', 'typescript', 'python'],
25
+ filePatterns: ['*.js', '*.ts', '*.jsx', '*.tsx', '*.mjs', '*.cjs', '*.py'],
26
+ pattern: /(?:SELECT|INSERT|UPDATE|DELETE|FROM|WHERE)[\s\S]{0,50}(?:\+\s*\w+|\$\{|f['"])/gi,
27
+ message: 'SQL query built with string concatenation. Vulnerable to SQL injection.',
28
+ remediation: 'Use parameterized queries or prepared statements.',
29
+ confidence: 'medium',
30
+ cwe: 'CWE-89',
31
+ owasp: 'A03:2021',
32
+ aiVerification: { enabled: true },
33
+ },
34
+ {
35
+ id: 'VG-SEC-003',
36
+ title: 'Hardcoded Secret/Credential',
37
+ severity: 'critical',
38
+ category: 'secrets',
39
+ languages: ['node', 'typescript', 'python'],
40
+ filePatterns: ['*.js', '*.ts', '*.jsx', '*.tsx', '*.mjs', '*.cjs', '*.py', '*.json', '*.yaml', '*.yml'],
41
+ pattern: /(?:api[_-]?key|secret|password|token|auth[_-]?token|private[_-]?key)\s*[:=]\s*['"][A-Za-z0-9+/=_-]{16,}['"]/gi,
42
+ allowPatterns: [/example|placeholder|your[_-]?|changeme|xxx|test|dummy/i],
43
+ message: 'Hardcoded credential detected. Secrets in source code can be extracted from version control.',
44
+ remediation: 'Use environment variables or a secrets manager (AWS Secrets Manager, HashiCorp Vault).',
45
+ confidence: 'high',
46
+ cwe: 'CWE-798',
47
+ owasp: 'A07:2021',
48
+ aiVerification: { enabled: true },
49
+ fixable: true,
50
+ fixStrategy: 'hardcoded-to-env',
51
+ },
52
+ {
53
+ id: 'VG-SEC-004',
54
+ title: 'Secret Logged to Console',
55
+ severity: 'warning',
56
+ category: 'secrets',
57
+ languages: ['node', 'typescript', 'python'],
58
+ filePatterns: ['*.js', '*.ts', '*.jsx', '*.tsx', '*.mjs', '*.cjs', '*.py'],
59
+ pattern: /(?:console\.log|print)\s*\([^)]*(?:key|token|password|secret|credential|api[_-]?key)/gi,
60
+ message: 'Potentially logging sensitive data. Logs may be accessible to unauthorized parties.',
61
+ remediation: 'Remove secret logging or redact sensitive values before logging.',
62
+ confidence: 'medium',
63
+ cwe: 'CWE-532',
64
+ owasp: 'A09:2021',
65
+ aiVerification: { enabled: true },
66
+ },
67
+ {
68
+ id: 'VG-SEC-005',
69
+ title: 'Secret in API Response',
70
+ severity: 'warning',
71
+ category: 'secrets',
72
+ languages: ['node', 'typescript', 'python'],
73
+ filePatterns: ['*.js', '*.ts', '*.jsx', '*.tsx', '*.mjs', '*.cjs', '*.py'],
74
+ pattern: /(?:res\.json|jsonify|return\s*\{)[^}]*(?:api_key|password|secret|token|private_key)\s*:/gi,
75
+ message: 'API response may include sensitive fields. Secrets exposed to clients.',
76
+ remediation: 'Filter sensitive fields before sending response. Use DTOs or serializers.',
77
+ confidence: 'medium',
78
+ cwe: 'CWE-200',
79
+ owasp: 'A01:2021',
80
+ aiVerification: { enabled: true },
81
+ },
82
+ ];
@@ -0,0 +1,75 @@
1
+ export type RuleSeverity = 'critical' | 'warning' | 'info';
2
+ export type RuleCategory = 'secrets' | 'injection' | 'deserialization' | 'config' | 'crypto' | 'docker' | 'kubernetes' | 'dependency';
3
+ export type Language = 'node' | 'typescript' | 'python' | 'docker' | 'kubernetes' | 'yaml' | 'json';
4
+ export interface DetectionRule {
5
+ id: string;
6
+ title: string;
7
+ severity: RuleSeverity;
8
+ category: RuleCategory;
9
+ languages: Language[];
10
+ filePatterns: string[];
11
+ pattern: RegExp;
12
+ allowPatterns?: RegExp[];
13
+ pathExclude?: string[];
14
+ message: string;
15
+ remediation?: string;
16
+ references?: string[];
17
+ confidence: 'high' | 'medium' | 'low';
18
+ cwe?: string;
19
+ owasp?: string;
20
+ aiVerification?: {
21
+ enabled: boolean;
22
+ promptTemplate?: string;
23
+ };
24
+ fixable?: boolean;
25
+ fixStrategy?: string;
26
+ }
27
+ export interface Finding {
28
+ ruleId: string;
29
+ title: string;
30
+ severity: RuleSeverity;
31
+ category: RuleCategory;
32
+ file: string;
33
+ line: number;
34
+ column: number;
35
+ endLine?: number;
36
+ endColumn?: number;
37
+ snippet: string;
38
+ match: string;
39
+ matchOffset?: number;
40
+ message: string;
41
+ remediation?: string;
42
+ cwe?: string;
43
+ owasp?: string;
44
+ aiVerdict?: {
45
+ verdict: 'true_positive' | 'false_positive' | 'unsure';
46
+ confidence: number;
47
+ rationale: string;
48
+ };
49
+ }
50
+ export interface ScanConfig {
51
+ targetPath: string;
52
+ ignorePatterns: string[];
53
+ maxFileSize: number;
54
+ includeSeverities: RuleSeverity[];
55
+ includeCategories?: RuleCategory[];
56
+ ruleIds?: string[];
57
+ format: 'console' | 'json' | 'sarif';
58
+ noColor: boolean;
59
+ verbose: boolean;
60
+ aiVerify: boolean;
61
+ aiProvider?: string;
62
+ aiApiKey?: string;
63
+ aiModel?: string;
64
+ }
65
+ export interface ScanResult {
66
+ scannedFiles: number;
67
+ skippedFiles: number;
68
+ totalFindings: number;
69
+ criticalCount: number;
70
+ warningCount: number;
71
+ infoCount: number;
72
+ findings: Finding[];
73
+ duration: number;
74
+ timestamp: string;
75
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export declare function isBinaryBuffer(buffer: Buffer): boolean;
@@ -0,0 +1,10 @@
1
+ const BINARY_CHECK_SIZE = 8192;
2
+ export function isBinaryBuffer(buffer) {
3
+ const checkSize = Math.min(buffer.length, BINARY_CHECK_SIZE);
4
+ for (let i = 0; i < checkSize; i++) {
5
+ if (buffer[i] === 0) {
6
+ return true;
7
+ }
8
+ }
9
+ return false;
10
+ }
@@ -0,0 +1,6 @@
1
+ export declare function buildLineIndex(content: string): number[];
2
+ export declare function offsetToLineCol(offset: number, lineStarts: number[]): {
3
+ line: number;
4
+ column: number;
5
+ };
6
+ export declare function extractSnippet(content: string, line: number, lineStarts: number[], maxLength?: number): string;
@@ -0,0 +1,40 @@
1
+ export function buildLineIndex(content) {
2
+ const starts = [0];
3
+ for (let i = 0; i < content.length; i++) {
4
+ if (content[i] === '\n') {
5
+ starts.push(i + 1);
6
+ }
7
+ }
8
+ return starts;
9
+ }
10
+ export function offsetToLineCol(offset, lineStarts) {
11
+ let low = 0;
12
+ let high = lineStarts.length - 1;
13
+ while (low < high) {
14
+ const mid = Math.floor((low + high + 1) / 2);
15
+ if (lineStarts[mid] <= offset) {
16
+ low = mid;
17
+ }
18
+ else {
19
+ high = mid - 1;
20
+ }
21
+ }
22
+ return {
23
+ line: low + 1,
24
+ column: offset - lineStarts[low] + 1,
25
+ };
26
+ }
27
+ export function extractSnippet(content, line, lineStarts, maxLength = 200) {
28
+ const lineIndex = line - 1;
29
+ if (lineIndex < 0 || lineIndex >= lineStarts.length) {
30
+ return '';
31
+ }
32
+ const start = lineStarts[lineIndex];
33
+ const end = lineIndex + 1 < lineStarts.length
34
+ ? lineStarts[lineIndex + 1] - 1
35
+ : content.length;
36
+ const snippet = content.slice(start, end).trim();
37
+ return snippet.length > maxLength
38
+ ? snippet.slice(0, maxLength - 3) + '...'
39
+ : snippet;
40
+ }
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@rahul-sch/vibeguard",
3
+ "version": "1.0.0",
4
+ "description": "Regex-first security scanner for AI-generated code",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "vibeguard": "bin/vibeguard.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "bin"
14
+ ],
15
+ "scripts": {
16
+ "prepublishOnly": "npm run build",
17
+ "build": "tsc",
18
+ "dev": "tsx src/index.ts",
19
+ "lint": "eslint src --ext .ts",
20
+ "format": "prettier --write src",
21
+ "test": "vitest run",
22
+ "test:watch": "vitest"
23
+ },
24
+ "keywords": [
25
+ "security",
26
+ "scanner",
27
+ "cli",
28
+ "vibe-coding",
29
+ "static-analysis"
30
+ ],
31
+ "author": "",
32
+ "license": "MIT",
33
+ "dependencies": {
34
+ "chalk": "^5.3.0",
35
+ "commander": "^12.1.0",
36
+ "fast-glob": "^3.3.2",
37
+ "lru-cache": "^10.4.3"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^20.14.0",
41
+ "@typescript-eslint/eslint-plugin": "^7.13.0",
42
+ "@typescript-eslint/parser": "^7.13.0",
43
+ "eslint": "^8.57.0",
44
+ "prettier": "^3.3.2",
45
+ "tsx": "^4.15.6",
46
+ "typescript": "^5.4.5",
47
+ "vitest": "^1.6.0"
48
+ },
49
+ "engines": {
50
+ "node": ">=18"
51
+ }
52
+ }