api-key-guard 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/.env.example ADDED
@@ -0,0 +1,7 @@
1
+ # Environment variables for api-key-guard
2
+
3
+ # Gemini API Key for README generation
4
+ # Get your API key from: https://makersuite.google.com/app/apikey
5
+ GEMINI_API_KEY=your_gemini_api_key_here
6
+
7
+ # Example: GEMINI_API_KEY=AIzaSyBxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
package/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # API Key Guard
2
+
3
+ A comprehensive CLI tool for detecting, preventing, and managing API key leaks in your codebase with AI-powered README generation.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ # Install the package
9
+ npm install -g api-key-guard
10
+
11
+ # Scan for API key leaks
12
+ api-key-guard scan
13
+
14
+ # Setup git hooks
15
+ api-key-guard setup-hooks
16
+
17
+ # Generate AI-powered README (requires GEMINI_API_KEY)
18
+ export GEMINI_API_KEY=your_gemini_api_key_here
19
+ api-key-guard readme
20
+ ```
21
+
22
+ ## Features
23
+
24
+ - šŸ” **API Key Detection**: Scan your codebase for potential API key leaks
25
+ - šŸ”— **Git Hooks Integration**: Automatically check for leaks before commits
26
+ - šŸ¤– **AI-Powered README**: Generate professional README files using Google's Gemini API
27
+ - āš™ļø **Configurable**: Customize scanning patterns and ignore rules
28
+ - šŸ›”ļø **Security First**: Built with security best practices in mind
29
+
30
+ ## CLI Commands
31
+
32
+ ### `api-key-guard scan`
33
+ Scan files for potential API key leaks.
34
+
35
+ Options:
36
+ - `-p, --path <path>`: Path to scan (default: current directory)
37
+ - `-v, --verbose`: Show detailed output
38
+
39
+ ### `api-key-guard setup-hooks`
40
+ Setup git hooks for automatic API key detection before commits.
41
+
42
+ ### `api-key-guard readme`
43
+ Generate an AI-powered README.md file using Gemini API.
44
+
45
+ Options:
46
+ - `-f, --force`: Overwrite existing README.md without confirmation
47
+ - `-o, --output <file>`: Output file path (default: README.md)
48
+
49
+ ## Environment Variables
50
+
51
+ - `GEMINI_API_KEY`: Required for README generation. Get your API key from [Google AI Studio](https://makersuite.google.com/app/apikey)
52
+
53
+ ## Installation
54
+
55
+ ```bash
56
+ npm install api-key-guard
57
+ ```
58
+
59
+ ## License
60
+
61
+ MIT
package/TESTING.md ADDED
@@ -0,0 +1,111 @@
1
+ # Testing the API Key Guard CLI
2
+
3
+ ## Demo Instructions
4
+
5
+ This guide helps you test the API Key Guard CLI tool with the AI-powered README generator.
6
+
7
+ ### Step 1: Install Dependencies
8
+ ```bash
9
+ cd api-key-guard
10
+ npm install
11
+ ```
12
+
13
+ ### Step 2: Test Basic Commands
14
+
15
+ #### Test the help system:
16
+ ```bash
17
+ node bin/cli.js --help
18
+ node bin/cli.js readme --help
19
+ node bin/cli.js scan --help
20
+ ```
21
+
22
+ #### Test the scanner:
23
+ ```bash
24
+ node bin/cli.js scan
25
+ node bin/cli.js scan --verbose
26
+ ```
27
+
28
+ ### Step 3: Test API Key Detection
29
+ Create a test file with fake API keys:
30
+ ```javascript
31
+ // test-keys.js
32
+ const config = {
33
+ api_key: "sk-1234567890abcdef1234567890abcdef12345678",
34
+ aws_key: "AKIA1234567890ABCDEF",
35
+ github_token: "ghp_abcdefghijklmnopqrstuvwxyz1234567890"
36
+ };
37
+ ```
38
+
39
+ Then scan:
40
+ ```bash
41
+ node bin/cli.js scan --verbose
42
+ ```
43
+
44
+ ### Step 4: Test README Generator
45
+
46
+ #### Without API key (should show error):
47
+ ```bash
48
+ node bin/cli.js readme --output test-readme.md
49
+ ```
50
+
51
+ #### With API key (requires real Gemini API key):
52
+ 1. Get API key from [Google AI Studio](https://makersuite.google.com/app/apikey)
53
+ 2. Set environment variable:
54
+ ```bash
55
+ # Windows PowerShell
56
+ $env:GEMINI_API_KEY = "your_actual_api_key"
57
+
58
+ # Then run
59
+ node bin/cli.js readme --force --output ai-generated-readme.md
60
+ ```
61
+
62
+ ### Step 5: Test Git Hooks
63
+ ```bash
64
+ # Initialize git (if not already done)
65
+ git init
66
+
67
+ # Install hooks
68
+ node bin/cli.js setup-hooks
69
+
70
+ # Test the hook by trying to commit a file with API keys
71
+ echo 'const key = "AKIA1234567890ABCDEF";' > bad-file.js
72
+ git add bad-file.js
73
+ git commit -m "test commit" # Should be blocked
74
+ ```
75
+
76
+ ## Expected Outputs
77
+
78
+ ### Successful README Generation
79
+ When you have a valid API key, you should see:
80
+ ```
81
+ šŸ¤– Generating README with AI...
82
+ šŸ“ Analyzing project structure...
83
+ šŸš€ Generating README with Gemini AI...
84
+ šŸ’¾ Writing README.md...
85
+ āœ… Successfully generated README.md!
86
+ ```
87
+
88
+ ### API Key Detection
89
+ When scanning files with API keys:
90
+ ```
91
+ šŸ” Scanning for API key leaks...
92
+ 🚨 Found X potential API key leak(s):
93
+ šŸ“„ filename.js:line_number
94
+ Pattern: detected_pattern
95
+ āš ļø Please review these findings and secure any exposed API keys!
96
+ ```
97
+
98
+ ### Error Handling
99
+ Without API key:
100
+ ```
101
+ Error generating README: GEMINI_API_KEY environment variable is required. Please set your Gemini API key.
102
+ ```
103
+
104
+ ## Cleanup After Testing
105
+ ```bash
106
+ # Remove test files
107
+ rm test-keys.js bad-file.js ai-generated-readme.md
108
+
109
+ # Remove git hooks if needed
110
+ rm .git/hooks/pre-commit
111
+ ```
package/USAGE.md ADDED
@@ -0,0 +1,126 @@
1
+ # API Key Guard - Usage Guide
2
+
3
+ ## Quick Setup
4
+
5
+ 1. **Install the package:**
6
+ ```bash
7
+ npm install -g api-key-guard
8
+ ```
9
+
10
+ 2. **Get a Gemini API key:**
11
+ - Visit [Google AI Studio](https://makersuite.google.com/app/apikey)
12
+ - Create a new API key
13
+ - Copy the API key
14
+
15
+ 3. **Set up environment variable:**
16
+ ```bash
17
+ # Windows (PowerShell)
18
+ $env:GEMINI_API_KEY = "your_gemini_api_key_here"
19
+
20
+ # Windows (Command Prompt)
21
+ set GEMINI_API_KEY=your_gemini_api_key_here
22
+
23
+ # macOS/Linux
24
+ export GEMINI_API_KEY=your_gemini_api_key_here
25
+ ```
26
+
27
+ ## Using the AI-Powered README Generator
28
+
29
+ ### Basic Usage
30
+ ```bash
31
+ # Generate README.md with AI
32
+ api-key-guard readme
33
+ ```
34
+
35
+ ### With Options
36
+ ```bash
37
+ # Force overwrite existing README.md
38
+ api-key-guard readme --force
39
+
40
+ # Output to a different file
41
+ api-key-guard readme --output DOCUMENTATION.md
42
+
43
+ # Combine options
44
+ api-key-guard readme --force --output NEW_README.md
45
+ ```
46
+
47
+ ### What the AI Generates
48
+ The README generator creates a comprehensive README.md that includes:
49
+
50
+ - **Project title and description**
51
+ - **Problem statement** explaining API key leak issues
52
+ - **Features list** showcasing all capabilities
53
+ - **Installation instructions** for npm
54
+ - **CLI usage examples** for all commands
55
+ - **Git hooks setup guide**
56
+ - **Configuration options**
57
+ - **Security best practices**
58
+ - **Contributing guidelines**
59
+ - **License information**
60
+
61
+ ## Other Commands
62
+
63
+ ### Scan for API Key Leaks
64
+ ```bash
65
+ # Scan current directory
66
+ api-key-guard scan
67
+
68
+ # Scan specific path
69
+ api-key-guard scan --path ./src
70
+
71
+ # Verbose output
72
+ api-key-guard scan --verbose
73
+ ```
74
+
75
+ ### Setup Git Hooks
76
+ ```bash
77
+ # Install pre-commit hook
78
+ api-key-guard setup-hooks
79
+ ```
80
+
81
+ ## Error Handling
82
+
83
+ The tool provides clear error messages for common issues:
84
+
85
+ - **Missing API key**: Clear instructions on how to set GEMINI_API_KEY
86
+ - **Network issues**: Helpful network troubleshooting information
87
+ - **Invalid API responses**: Detailed API error messages
88
+ - **File permissions**: Clear permission error messages
89
+
90
+ ## Security Features
91
+
92
+ - **No API key storage**: API keys are read from environment variables only
93
+ - **Pattern-based detection**: Uses regex patterns to detect various API key formats
94
+ - **Configurable ignore patterns**: Respects .gitignore-style patterns
95
+ - **Git hook integration**: Prevents commits with detected API keys
96
+
97
+ ## Supported API Key Formats
98
+
99
+ The scanner detects these common API key patterns:
100
+ - Generic API keys (`api_key`, `secret_key`, `access_token`)
101
+ - AWS Access Keys (`AKIA...`)
102
+ - GitHub Personal Access Tokens (`ghp_...`)
103
+ - Google API Keys (`AIza...`)
104
+ - Bearer tokens
105
+ - Custom patterns (configurable)
106
+
107
+ ## Configuration
108
+
109
+ Create a `api-key-guard.config.json` file to customize:
110
+
111
+ ```json
112
+ {
113
+ "ignorePatterns": [
114
+ "node_modules",
115
+ ".git",
116
+ "dist",
117
+ "*.log"
118
+ ],
119
+ "customPatterns": [
120
+ {
121
+ "name": "Custom API Key",
122
+ "pattern": "custom_[0-9a-f]{32}"
123
+ }
124
+ ]
125
+ }
126
+ ```
package/bin/cli.js ADDED
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { Command } = require('commander');
4
+ const chalk = require('chalk');
5
+ const { generateReadme } = require('../src/readmeGenerator');
6
+ const { scanForApiKeys } = require('../src/scanner');
7
+ const { setupGitHooks } = require('../src/gitHooks');
8
+
9
+ const program = new Command();
10
+
11
+ program
12
+ .name('api-key-guard')
13
+ .description('CLI tool to detect API key leaks and manage security')
14
+ .version('1.0.0');
15
+
16
+ // Scan command
17
+ program
18
+ .command('scan')
19
+ .description('Scan files for potential API key leaks')
20
+ .option('-p, --path <path>', 'Path to scan', '.')
21
+ .option('-v, --verbose', 'Show detailed output')
22
+ .action(async (options) => {
23
+ try {
24
+ console.log(chalk.blue('šŸ” Scanning for API key leaks...'));
25
+ await scanForApiKeys(options.path, options.verbose);
26
+ } catch (error) {
27
+ console.error(chalk.red('Error during scan:', error.message));
28
+ process.exit(1);
29
+ }
30
+ });
31
+
32
+ // Setup git hooks command
33
+ program
34
+ .command('setup-hooks')
35
+ .description('Setup git hooks for automatic API key detection')
36
+ .action(async () => {
37
+ try {
38
+ console.log(chalk.blue('āš™ļø Setting up git hooks...'));
39
+ await setupGitHooks();
40
+ } catch (error) {
41
+ console.error(chalk.red('Error setting up hooks:', error.message));
42
+ process.exit(1);
43
+ }
44
+ });
45
+
46
+ // README generator command
47
+ program
48
+ .command('readme')
49
+ .description('Generate an AI-powered README.md file using Gemini API')
50
+ .option('-f, --force', 'Overwrite existing README.md without confirmation')
51
+ .option('-o, --output <file>', 'Output file path', 'README.md')
52
+ .action(async (options) => {
53
+ try {
54
+ console.log(chalk.blue('šŸ¤– Generating README with AI...'));
55
+ await generateReadme(options);
56
+ } catch (error) {
57
+ console.error(chalk.red('Error generating README:', error.message));
58
+ process.exit(1);
59
+ }
60
+ });
61
+
62
+ program.parse();
@@ -0,0 +1,49 @@
1
+ {
2
+ "apiKeyPatterns": [
3
+ {
4
+ "name": "Generic API Key",
5
+ "pattern": "(?i)api[_-]?key[\\s]*[=:][\\s]*['\"]?([a-z0-9]{20,})",
6
+ "description": "Generic API key pattern"
7
+ },
8
+ {
9
+ "name": "Generic Secret Key",
10
+ "pattern": "(?i)secret[_-]?key[\\s]*[=:][\\s]*['\"]?([a-z0-9]{20,})",
11
+ "description": "Generic secret key pattern"
12
+ },
13
+ {
14
+ "name": "Access Token",
15
+ "pattern": "(?i)access[_-]?token[\\s]*[=:][\\s]*['\"]?([a-z0-9]{20,})",
16
+ "description": "Generic access token pattern"
17
+ },
18
+ {
19
+ "name": "AWS Access Key ID",
20
+ "pattern": "AKIA[0-9A-Z]{16}",
21
+ "description": "AWS Access Key ID"
22
+ },
23
+ {
24
+ "name": "GitHub Token",
25
+ "pattern": "ghp_[0-9a-zA-Z]{36}",
26
+ "description": "GitHub personal access token"
27
+ },
28
+ {
29
+ "name": "Google API Key",
30
+ "pattern": "AIza[0-9A-Za-z\\-_]{35}",
31
+ "description": "Google API key"
32
+ }
33
+ ],
34
+ "ignorePatterns": [
35
+ "node_modules",
36
+ ".git",
37
+ "dist",
38
+ "build",
39
+ "*.log",
40
+ "*.min.js",
41
+ "package-lock.json",
42
+ ".env.example"
43
+ ],
44
+ "fileExtensions": [
45
+ ".js", ".ts", ".jsx", ".tsx", ".json", ".md", ".txt", ".yml", ".yaml",
46
+ ".xml", ".html", ".css", ".scss", ".sass", ".less", ".env", ".config",
47
+ ".py", ".java", ".php", ".rb", ".go", ".rs", ".cpp", ".c", ".h"
48
+ ]
49
+ }
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "api-key-guard",
3
+ "version": "1.0.0",
4
+ "description": "A comprehensive tool to detect, prevent, and manage API key leaks in your codebase with AI-powered README generation",
5
+ "main": "src/index.js",
6
+ "bin": {
7
+ "api-key-guard": "./bin/cli.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node bin/cli.js",
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "keywords": [
14
+ "api-key",
15
+ "security",
16
+ "git-hooks",
17
+ "leak-detection",
18
+ "cli",
19
+ "readme-generator"
20
+ ],
21
+ "author": "your-name",
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "commander": "^11.0.0",
25
+ "chalk": "^4.1.2",
26
+ "axios": "^1.6.0"
27
+ },
28
+ "engines": {
29
+ "node": ">=14.0.0"
30
+ }
31
+ }
@@ -0,0 +1,61 @@
1
+ const fs = require('fs').promises;
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+
5
+ /**
6
+ * Setup git hooks for automatic API key detection
7
+ */
8
+ async function setupGitHooks() {
9
+ const gitHooksDir = path.join(process.cwd(), '.git', 'hooks');
10
+ const preCommitHook = path.join(gitHooksDir, 'pre-commit');
11
+
12
+ try {
13
+ // Check if .git directory exists
14
+ await fs.access(path.join(process.cwd(), '.git'));
15
+ } catch (error) {
16
+ throw new Error('No git repository found. Please initialize git first.');
17
+ }
18
+
19
+ // Ensure hooks directory exists
20
+ try {
21
+ await fs.mkdir(gitHooksDir, { recursive: true });
22
+ } catch (error) {
23
+ // Directory already exists
24
+ }
25
+
26
+ const hookContent = `#!/bin/sh
27
+ # api-key-guard pre-commit hook
28
+ # This hook scans staged files for potential API key leaks
29
+
30
+ echo "šŸ” Scanning staged files for API key leaks..."
31
+
32
+ # Run api-key-guard scan
33
+ npx api-key-guard scan --path .
34
+
35
+ # Check exit code
36
+ if [ $? -ne 0 ]; then
37
+ echo "🚨 API key leaks detected! Commit aborted."
38
+ echo "Please review the findings and remove any exposed API keys before committing."
39
+ exit 1
40
+ fi
41
+
42
+ echo "āœ… No API key leaks detected. Proceeding with commit."
43
+ exit 0
44
+ `;
45
+
46
+ await fs.writeFile(preCommitHook, hookContent, 'utf8');
47
+
48
+ // Make the hook executable (Unix-like systems)
49
+ try {
50
+ await fs.chmod(preCommitHook, '755');
51
+ } catch (error) {
52
+ // Chmod might not work on Windows, but that's okay
53
+ }
54
+
55
+ console.log(chalk.green('āœ… Git pre-commit hook installed successfully!'));
56
+ console.log(chalk.blue('šŸ”— The hook will automatically scan for API key leaks before each commit.'));
57
+ }
58
+
59
+ module.exports = {
60
+ setupGitHooks
61
+ };
package/src/index.js ADDED
@@ -0,0 +1,9 @@
1
+ const { scanForApiKeys } = require('./scanner');
2
+ const { setupGitHooks } = require('./gitHooks');
3
+ const { generateReadme } = require('./readmeGenerator');
4
+
5
+ module.exports = {
6
+ scanForApiKeys,
7
+ setupGitHooks,
8
+ generateReadme
9
+ };
@@ -0,0 +1,221 @@
1
+ const axios = require('axios');
2
+ const fs = require('fs').promises;
3
+ const path = require('path');
4
+ const chalk = require('chalk');
5
+ const readline = require('readline');
6
+
7
+ /**
8
+ * Generate README.md using Google's Gemini API
9
+ */
10
+ async function generateReadme(options = {}) {
11
+ // Check for API key
12
+ const apiKey = process.env.GEMINI_API_KEY;
13
+ if (!apiKey) {
14
+ throw new Error('GEMINI_API_KEY environment variable is required. Please set your Gemini API key.');
15
+ }
16
+
17
+ const outputFile = options.output || 'README.md';
18
+ const force = options.force || false;
19
+
20
+ // Check if README.md already exists
21
+ if (!force) {
22
+ try {
23
+ await fs.access(outputFile);
24
+ const shouldOverwrite = await promptConfirmation(
25
+ `${outputFile} already exists. Do you want to overwrite it? (y/N): `
26
+ );
27
+ if (!shouldOverwrite) {
28
+ console.log(chalk.yellow('Operation cancelled.'));
29
+ return;
30
+ }
31
+ } catch (error) {
32
+ // File doesn't exist, proceed
33
+ }
34
+ }
35
+
36
+ console.log(chalk.blue('šŸ“ Analyzing project structure...'));
37
+ const projectContext = await analyzeProject();
38
+
39
+ console.log(chalk.blue('šŸš€ Generating README with Gemini AI...'));
40
+ const readmeContent = await generateWithGemini(apiKey, projectContext);
41
+
42
+ console.log(chalk.blue('šŸ’¾ Writing README.md...'));
43
+ await fs.writeFile(outputFile, readmeContent, 'utf8');
44
+
45
+ console.log(chalk.green(`āœ… Successfully generated ${outputFile}!`));
46
+ }
47
+
48
+ /**
49
+ * Analyze the current project to gather context
50
+ */
51
+ async function analyzeProject() {
52
+ const context = {
53
+ projectName: 'api-key-guard',
54
+ hasPackageJson: false,
55
+ hasSrcDirectory: false,
56
+ hasGitDirectory: false,
57
+ dependencies: [],
58
+ scripts: {}
59
+ };
60
+
61
+ try {
62
+ // Check for package.json
63
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
64
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
65
+ context.hasPackageJson = true;
66
+ context.projectName = packageJson.name || context.projectName;
67
+ context.dependencies = Object.keys(packageJson.dependencies || {});
68
+ context.scripts = packageJson.scripts || {};
69
+ } catch (error) {
70
+ // No package.json found
71
+ }
72
+
73
+ try {
74
+ // Check for src directory
75
+ await fs.access(path.join(process.cwd(), 'src'));
76
+ context.hasSrcDirectory = true;
77
+ } catch (error) {
78
+ // No src directory
79
+ }
80
+
81
+ try {
82
+ // Check for git directory
83
+ await fs.access(path.join(process.cwd(), '.git'));
84
+ context.hasGitDirectory = true;
85
+ } catch (error) {
86
+ // No git directory
87
+ }
88
+
89
+ return context;
90
+ }
91
+
92
+ /**
93
+ * Generate README content using Gemini API
94
+ */
95
+ async function generateWithGemini(apiKey, projectContext) {
96
+ const prompt = createGeminiPrompt(projectContext);
97
+
98
+ try {
99
+ const response = await axios.post(
100
+ `https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${apiKey}`,
101
+ {
102
+ contents: [{
103
+ parts: [{
104
+ text: prompt
105
+ }]
106
+ }],
107
+ generationConfig: {
108
+ temperature: 0.7,
109
+ topK: 40,
110
+ topP: 0.95,
111
+ maxOutputTokens: 2048,
112
+ },
113
+ safetySettings: [
114
+ {
115
+ category: "HARM_CATEGORY_HARASSMENT",
116
+ threshold: "BLOCK_MEDIUM_AND_ABOVE"
117
+ },
118
+ {
119
+ category: "HARM_CATEGORY_HATE_SPEECH",
120
+ threshold: "BLOCK_MEDIUM_AND_ABOVE"
121
+ },
122
+ {
123
+ category: "HARM_CATEGORY_SEXUALLY_EXPLICIT",
124
+ threshold: "BLOCK_MEDIUM_AND_ABOVE"
125
+ },
126
+ {
127
+ category: "HARM_CATEGORY_DANGEROUS_CONTENT",
128
+ threshold: "BLOCK_MEDIUM_AND_ABOVE"
129
+ }
130
+ ]
131
+ },
132
+ {
133
+ headers: {
134
+ 'Content-Type': 'application/json'
135
+ }
136
+ }
137
+ );
138
+
139
+ if (response.data.candidates && response.data.candidates[0].content.parts[0].text) {
140
+ return response.data.candidates[0].content.parts[0].text;
141
+ } else {
142
+ throw new Error('Invalid response from Gemini API');
143
+ }
144
+ } catch (error) {
145
+ if (error.response) {
146
+ throw new Error(`Gemini API error: ${error.response.status} - ${error.response.data?.error?.message || 'Unknown error'}`);
147
+ } else if (error.request) {
148
+ throw new Error('Network error: Unable to reach Gemini API');
149
+ } else {
150
+ throw new Error(`Error generating content: ${error.message}`);
151
+ }
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Create a detailed prompt for Gemini to generate README
157
+ */
158
+ function createGeminiPrompt(context) {
159
+ return `Generate a professional README.md file for the "${context.projectName}" Node.js package. This is a comprehensive CLI tool for detecting, preventing, and managing API key leaks in codebases.
160
+
161
+ Context about the project:
162
+ - Project name: ${context.projectName}
163
+ - Has package.json: ${context.hasPackageJson}
164
+ - Has src directory: ${context.hasSrcDirectory}
165
+ - Has git repository: ${context.hasGitDirectory}
166
+ - Dependencies: ${context.dependencies.join(', ')}
167
+
168
+ Please generate a comprehensive README.md with the following sections:
169
+
170
+ 1. **Project Title & Description**: Clear, concise description of what api-key-guard does
171
+ 2. **Problem Statement**: Explain the critical issue of API key leaks in code repositories
172
+ 3. **Features List**: Comprehensive list of features including:
173
+ - API key detection and scanning
174
+ - Git hooks integration
175
+ - CLI commands
176
+ - AI-powered README generation
177
+ - Multiple file format support
178
+ - Configurable ignore patterns
179
+ 4. **Installation**: Step-by-step installation instructions using npm
180
+ 5. **CLI Usage Examples**: Detailed examples of all CLI commands:
181
+ - \`api-key-guard scan\` with various options
182
+ - \`api-key-guard setup-hooks\` for git integration
183
+ - \`api-key-guard readme\` for README generation
184
+ 6. **Git Hooks Usage**: How to set up and use pre-commit hooks
185
+ 7. **Configuration**: Details about configuration files and ignore patterns
186
+ 8. **Security Best Practices**: Important security notes and recommendations
187
+ 9. **Future Roadmap**: Planned features and improvements
188
+ 10. **Contributing**: Guidelines for contributors
189
+ 11. **License**: MIT license information
190
+
191
+ Requirements:
192
+ - Use clear, developer-friendly language
193
+ - Include practical code examples
194
+ - Use proper markdown formatting with badges, code blocks, and tables
195
+ - Make it visually appealing with emojis and good structure
196
+ - Include security warnings and best practices
197
+ - Keep it professional but engaging
198
+
199
+ Generate ONLY the README.md content in markdown format, no additional text or explanations.`;
200
+ }
201
+
202
+ /**
203
+ * Prompt user for confirmation
204
+ */
205
+ function promptConfirmation(question) {
206
+ return new Promise((resolve) => {
207
+ const rl = readline.createInterface({
208
+ input: process.stdin,
209
+ output: process.stdout
210
+ });
211
+
212
+ rl.question(question, (answer) => {
213
+ rl.close();
214
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
215
+ });
216
+ });
217
+ }
218
+
219
+ module.exports = {
220
+ generateReadme
221
+ };
package/src/scanner.js ADDED
@@ -0,0 +1,143 @@
1
+ const fs = require('fs').promises;
2
+ const path = require('path');
3
+ const chalk = require('chalk');
4
+
5
+ /**
6
+ * Scan directory for potential API key leaks
7
+ */
8
+ async function scanForApiKeys(scanPath = '.', verbose = false) {
9
+ const apiKeyPatterns = [
10
+ /api[_-]?key[\s]*[=:][\s]*['"]?([a-z0-9]{20,})/gi,
11
+ /secret[_-]?key[\s]*[=:][\s]*['"]?([a-z0-9]{20,})/gi,
12
+ /access[_-]?token[\s]*[=:][\s]*['"]?([a-z0-9]{20,})/gi,
13
+ /auth[_-]?token[\s]*[=:][\s]*['"]?([a-z0-9]{20,})/gi,
14
+ /bearer[\s]*[=:][\s]*['"]?([a-z0-9]{20,})/gi,
15
+ // AWS patterns
16
+ /AKIA[0-9A-Z]{16}/g,
17
+ // GitHub tokens
18
+ /ghp_[0-9a-zA-Z]{36}/g,
19
+ // Google API keys
20
+ /AIza[0-9A-Za-z\-_]{35}/g,
21
+ ];
22
+
23
+ const ignorePatterns = [
24
+ 'node_modules',
25
+ '.git',
26
+ 'dist',
27
+ 'build',
28
+ '*.log',
29
+ '*.min.js',
30
+ 'package-lock.json'
31
+ ];
32
+
33
+ let findings = [];
34
+
35
+ try {
36
+ const files = await getFilesRecursively(scanPath, ignorePatterns);
37
+
38
+ for (const file of files) {
39
+ const content = await fs.readFile(file, 'utf8');
40
+
41
+ for (const pattern of apiKeyPatterns) {
42
+ let match;
43
+ while ((match = pattern.exec(content)) !== null) {
44
+ const lineNumber = content.substring(0, match.index).split('\n').length;
45
+ findings.push({
46
+ file: path.relative(process.cwd(), file),
47
+ line: lineNumber,
48
+ pattern: match[0],
49
+ type: 'potential-api-key'
50
+ });
51
+ }
52
+ }
53
+ }
54
+
55
+ if (findings.length > 0) {
56
+ console.log(chalk.red(`🚨 Found ${findings.length} potential API key leak(s):`));
57
+ findings.forEach(finding => {
58
+ console.log(chalk.yellow(` šŸ“„ ${finding.file}:${finding.line}`));
59
+ if (verbose) {
60
+ console.log(chalk.gray(` Pattern: ${finding.pattern}`));
61
+ }
62
+ });
63
+ console.log(chalk.red('\nāš ļø Please review these findings and secure any exposed API keys!'));
64
+ } else {
65
+ console.log(chalk.green('āœ… No potential API key leaks detected!'));
66
+ }
67
+
68
+ return findings;
69
+ } catch (error) {
70
+ throw new Error(`Scan failed: ${error.message}`);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * Get all files recursively, respecting ignore patterns
76
+ */
77
+ async function getFilesRecursively(dir, ignorePatterns = []) {
78
+ let files = [];
79
+
80
+ try {
81
+ const entries = await fs.readdir(dir, { withFileTypes: true });
82
+
83
+ for (const entry of entries) {
84
+ const fullPath = path.join(dir, entry.name);
85
+
86
+ // Check if should be ignored
87
+ if (shouldIgnore(entry.name, fullPath, ignorePatterns)) {
88
+ continue;
89
+ }
90
+
91
+ if (entry.isDirectory()) {
92
+ files = files.concat(await getFilesRecursively(fullPath, ignorePatterns));
93
+ } else {
94
+ // Only scan text files
95
+ if (isTextFile(entry.name)) {
96
+ files.push(fullPath);
97
+ }
98
+ }
99
+ }
100
+ } catch (error) {
101
+ // Skip directories we can't read
102
+ }
103
+
104
+ return files;
105
+ }
106
+
107
+ /**
108
+ * Check if file/directory should be ignored
109
+ */
110
+ function shouldIgnore(name, fullPath, ignorePatterns) {
111
+ for (const pattern of ignorePatterns) {
112
+ if (pattern.includes('*')) {
113
+ // Simple glob pattern matching
114
+ const regex = new RegExp(pattern.replace(/\*/g, '.*'));
115
+ if (regex.test(name)) {
116
+ return true;
117
+ }
118
+ } else {
119
+ if (name === pattern || fullPath.includes(pattern)) {
120
+ return true;
121
+ }
122
+ }
123
+ }
124
+ return false;
125
+ }
126
+
127
+ /**
128
+ * Check if file is likely a text file based on extension
129
+ */
130
+ function isTextFile(filename) {
131
+ const textExtensions = [
132
+ '.js', '.ts', '.jsx', '.tsx', '.json', '.md', '.txt', '.yml', '.yaml',
133
+ '.xml', '.html', '.css', '.scss', '.sass', '.less', '.env', '.config',
134
+ '.py', '.java', '.php', '.rb', '.go', '.rs', '.cpp', '.c', '.h'
135
+ ];
136
+
137
+ const ext = path.extname(filename).toLowerCase();
138
+ return textExtensions.includes(ext) || !ext; // Include files without extensions
139
+ }
140
+
141
+ module.exports = {
142
+ scanForApiKeys
143
+ };