keysentinel 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.
- package/LICENSE +21 -0
- package/README.md +474 -0
- package/dist/cli.d.ts +5 -0
- package/dist/config.d.ts +66 -0
- package/dist/github.d.ts +54 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +37296 -0
- package/dist/index.js.map +1 -0
- package/dist/licenses.txt +613 -0
- package/dist/mask.d.ts +22 -0
- package/dist/patterns.d.ts +49 -0
- package/dist/scanner.d.ts +36 -0
- package/dist/sourcemap-register.js +1 -0
- package/lib/cli.d.ts +5 -0
- package/lib/cli.js +194 -0
- package/lib/config.d.ts +66 -0
- package/lib/config.js +271 -0
- package/lib/github.d.ts +54 -0
- package/lib/github.js +273 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.js +140 -0
- package/lib/mask.d.ts +22 -0
- package/lib/mask.js +79 -0
- package/lib/patterns.d.ts +49 -0
- package/lib/patterns.js +310 -0
- package/lib/scanner.d.ts +36 -0
- package/lib/scanner.js +216 -0
- package/package.json +43 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vishrut Agarwalla
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,474 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
# 🔐 KeySentinel
|
|
6
|
+
|
|
7
|
+
**Stop secrets from leaking into your codebase. Catch API keys, tokens, and passwords before they reach production.**
|
|
8
|
+
|
|
9
|
+
[](https://github.com/marketplace/actions/keysentinel)
|
|
10
|
+
[](https://www.npmjs.com/package/keysentinel)
|
|
11
|
+
[](LICENSE)
|
|
12
|
+
[](https://github.com/Vishrut19/KeySentinel/releases)
|
|
13
|
+
[](https://github.com/Vishrut19/KeySentinel/stargazers)
|
|
14
|
+
|
|
15
|
+
[🚀 Quick Start](#-quick-start) • [📖 Documentation](#-configuration) • [💻 CLI](#-block-secrets-locally) • [🔧 Configuration](#-configuration) • [🤝 Contributing](#-contributing)
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
## 🎯 Why KeySentinel?
|
|
20
|
+
|
|
21
|
+
**Accidental secret leaks happen.** A developer commits an API key. A config file gets pushed with credentials. Before you know it, your secrets are exposed in your repository history.
|
|
22
|
+
|
|
23
|
+
**KeySentinel stops leaks at the source** — scanning pull requests and local commits to catch secrets before they reach your main branch. Powerful, local-first secret detection that works seamlessly in your existing workflow.
|
|
24
|
+
|
|
25
|
+
### ✨ Key Features
|
|
26
|
+
|
|
27
|
+
- 🚀 **Fast & Efficient** - Scans only PR diffs, not entire repositories
|
|
28
|
+
- 🔍 **Comprehensive Detection** - 50+ secret patterns (AWS, GitHub, Stripe, Slack, and more)
|
|
29
|
+
- 🧠 **Smart Detection** - Entropy-based analysis catches unknown secret formats
|
|
30
|
+
- 🛡️ **Safe by Default** - Never logs full secrets, only masked previews
|
|
31
|
+
- ⚡ **Local & CI** - Pre-commit hooks + GitHub Actions for complete coverage
|
|
32
|
+
- 🎛️ **Highly Configurable** - Custom allowlists, ignore patterns, severity levels
|
|
33
|
+
- 💰 **Free Forever** - Core features always free, with optional premium features coming soon
|
|
34
|
+
|
|
35
|
+
## 🚀 Quick Start
|
|
36
|
+
|
|
37
|
+
### Option 1: GitHub Action (Recommended for Teams)
|
|
38
|
+
|
|
39
|
+
Add KeySentinel to your repository in **3 simple steps**:
|
|
40
|
+
|
|
41
|
+
**Step 1:** Create `.github/workflows/keysentinel.yml`
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
name: KeySentinel
|
|
45
|
+
on:
|
|
46
|
+
pull_request:
|
|
47
|
+
types: [opened, synchronize, reopened]
|
|
48
|
+
|
|
49
|
+
permissions:
|
|
50
|
+
contents: read
|
|
51
|
+
pull-requests: write
|
|
52
|
+
issues: write
|
|
53
|
+
|
|
54
|
+
jobs:
|
|
55
|
+
scan:
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
- uses: Vishrut19/KeySentinel@v0
|
|
60
|
+
env:
|
|
61
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Step 2:** Enable Write Permissions
|
|
65
|
+
|
|
66
|
+
Go to **Repository Settings → Actions → General → Workflow Permissions** → Select ✅ **Read and write permissions** → Save
|
|
67
|
+
|
|
68
|
+
**Step 3:** Open a Pull Request
|
|
69
|
+
|
|
70
|
+
KeySentinel will automatically scan for secrets and post findings as PR comments! 🎉
|
|
71
|
+
|
|
72
|
+
### Option 2: Local Pre-commit Hook (Recommended for Individual Developers)
|
|
73
|
+
|
|
74
|
+
**Install globally:**
|
|
75
|
+
```bash
|
|
76
|
+
npm install -g keysentinel
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Install git hooks:**
|
|
80
|
+
```bash
|
|
81
|
+
keysentinel install
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Done! Now every commit and push will be scanned for secrets automatically.
|
|
85
|
+
|
|
86
|
+
## 📸 What It Looks Like
|
|
87
|
+
|
|
88
|
+
When KeySentinel finds secrets, it posts a clear, actionable comment on your PR:
|
|
89
|
+
|
|
90
|
+
<img width="1469" height="776" alt="KeySentinel PR Comment Example" src="https://github.com/user-attachments/assets/e9edc920-222c-45ab-8c97-f8e1ede956aa" />
|
|
91
|
+
|
|
92
|
+
## 💻 Block Secrets Locally
|
|
93
|
+
|
|
94
|
+
**Stop secrets before they're committed** with KeySentinel's pre-commit and pre-push hooks. Perfect for catching leaks during development.
|
|
95
|
+
|
|
96
|
+
### Installation
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Global install (recommended)
|
|
100
|
+
npm install -g keysentinel
|
|
101
|
+
|
|
102
|
+
# Or as a project dependency
|
|
103
|
+
npm install -D keysentinel
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Setup Git Hooks
|
|
107
|
+
|
|
108
|
+
From your repository root:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
keysentinel install
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This installs both `.git/hooks/pre-commit` and `.git/hooks/pre-push` hooks that automatically scan staged changes. The hooks:
|
|
115
|
+
- ✅ Use `keysentinel` if available in PATH
|
|
116
|
+
- ✅ Fall back to `npx keysentinel scan` for local installs
|
|
117
|
+
- ✅ Block commits/pushes when secrets are detected
|
|
118
|
+
- ✅ Show clear error messages with findings
|
|
119
|
+
|
|
120
|
+
### Manual Scan
|
|
121
|
+
|
|
122
|
+
Scan staged files without committing:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
keysentinel scan
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Exit codes:**
|
|
129
|
+
- `0` - No secrets found (or below `fail_on` threshold)
|
|
130
|
+
- `1` - Secrets detected at or above `fail_on` severity
|
|
131
|
+
|
|
132
|
+
> 💡 **Tip:** The same `.keysentinel.yml` configuration file works for both the CLI and GitHub Action, keeping your rules consistent across local and CI environments.
|
|
133
|
+
|
|
134
|
+
## 🔧 Configuration
|
|
135
|
+
|
|
136
|
+
KeySentinel is highly configurable. Use action inputs for quick setup, or create a `.keysentinel.yml` file for advanced configuration.
|
|
137
|
+
|
|
138
|
+
### Action Inputs
|
|
139
|
+
|
|
140
|
+
| Input | Description | Default |
|
|
141
|
+
|-------|-------------|---------|
|
|
142
|
+
| `github_token` | GitHub token for API access | `${{ github.token }}` |
|
|
143
|
+
| `fail_on` | Fail workflow at this severity (`high`, `medium`, `low`, `off`) | `high` |
|
|
144
|
+
| `post_no_findings` | Post comment when no secrets found | `false` |
|
|
145
|
+
| `ignore` | Comma-separated file globs to ignore | (see defaults) |
|
|
146
|
+
| `allowlist` | Comma-separated regex patterns to allow | `""` |
|
|
147
|
+
| `max_files` | Maximum files to scan per PR | `100` |
|
|
148
|
+
| `config_path` | Path to config file | `.keysentinel.yml` |
|
|
149
|
+
|
|
150
|
+
### Configuration File
|
|
151
|
+
|
|
152
|
+
Create `.keysentinel.yml` in your repository root for advanced configuration. This file is shared between the GitHub Action and local CLI, ensuring consistent behavior.
|
|
153
|
+
|
|
154
|
+
```yaml
|
|
155
|
+
# Severity threshold for failing workflows
|
|
156
|
+
fail_on: high # Options: high | medium | low | off
|
|
157
|
+
|
|
158
|
+
# Post comment even when no secrets found
|
|
159
|
+
post_no_findings: false
|
|
160
|
+
|
|
161
|
+
# Maximum files to scan per PR
|
|
162
|
+
max_files: 100
|
|
163
|
+
|
|
164
|
+
# Files to ignore (in addition to defaults)
|
|
165
|
+
ignore:
|
|
166
|
+
- "*.test.ts"
|
|
167
|
+
- "**/__fixtures__/**"
|
|
168
|
+
- "docs/**"
|
|
169
|
+
- "*.spec.js"
|
|
170
|
+
|
|
171
|
+
# Patterns to allowlist (regex)
|
|
172
|
+
allowlist:
|
|
173
|
+
- "EXAMPLE_[A-Z]+"
|
|
174
|
+
- "test_api_key_.*"
|
|
175
|
+
- "fake_secret_.*"
|
|
176
|
+
- "MOCK_.*"
|
|
177
|
+
|
|
178
|
+
# Enable/disable specific pattern groups
|
|
179
|
+
patterns:
|
|
180
|
+
aws: true
|
|
181
|
+
github: true
|
|
182
|
+
slack: true
|
|
183
|
+
stripe: true
|
|
184
|
+
generic: true
|
|
185
|
+
keys: true
|
|
186
|
+
google: true
|
|
187
|
+
database: true
|
|
188
|
+
twilio: true
|
|
189
|
+
sendgrid: true
|
|
190
|
+
mailchimp: true
|
|
191
|
+
npm: true
|
|
192
|
+
discord: true
|
|
193
|
+
heroku: true
|
|
194
|
+
jwt: true
|
|
195
|
+
|
|
196
|
+
# Entropy detection (catches unknown secret formats)
|
|
197
|
+
entropy:
|
|
198
|
+
enabled: true
|
|
199
|
+
min_length: 20
|
|
200
|
+
threshold: 4.2
|
|
201
|
+
ignore_base64_like: true
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Default Ignored Files
|
|
205
|
+
|
|
206
|
+
These patterns are automatically ignored:
|
|
207
|
+
|
|
208
|
+
- Build artifacts: `node_modules/**`, `dist/**`, `build/**`, `vendor/**`
|
|
209
|
+
- Minified files: `*.min.js`, `*.min.css`
|
|
210
|
+
- Lock files: `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `*.lock`
|
|
211
|
+
- Source maps: `*.map`
|
|
212
|
+
- Git files: `.git/**`
|
|
213
|
+
- Documentation: `*.md`, `LICENSE*`, `CHANGELOG*`
|
|
214
|
+
- Coverage: `coverage/**`
|
|
215
|
+
|
|
216
|
+
## 🔍 Detected Secret Types
|
|
217
|
+
|
|
218
|
+
KeySentinel detects **50+ secret patterns** across major services:
|
|
219
|
+
|
|
220
|
+
| Category | Detected Patterns |
|
|
221
|
+
|----------|------------------|
|
|
222
|
+
| **🔷 AWS** | Access Key ID (`AKIA...`), Secret Access Key |
|
|
223
|
+
| **🐙 GitHub** | Personal Access Token (`ghp_...`), OAuth Token, App Token, Fine-Grained Token |
|
|
224
|
+
| **💬 Slack** | Bot Token (`xoxb-...`), User Token (`xoxp-...`), Webhook URL |
|
|
225
|
+
| **💳 Stripe** | Live Key (`sk_live_...`), Test Key (`sk_test_...`), Restricted Key |
|
|
226
|
+
| **🔍 Google** | API Key, OAuth Client Secret |
|
|
227
|
+
| **🔑 Private Keys** | RSA, SSH, PGP, EC private keys |
|
|
228
|
+
| **🗄️ Database** | MongoDB, PostgreSQL, MySQL, Redis connection strings |
|
|
229
|
+
| **📧 Email Services** | Twilio, SendGrid, Mailchimp API keys |
|
|
230
|
+
| **🔐 Generic** | API keys, Bearer tokens, Basic auth credentials |
|
|
231
|
+
| **📦 Others** | NPM tokens, Discord tokens, Heroku API keys, JWT secrets |
|
|
232
|
+
|
|
233
|
+
> 💡 **Smart Detection:** KeySentinel uses entropy analysis to catch high-entropy strings that match secret patterns, even if they don't match known formats.
|
|
234
|
+
|
|
235
|
+
## 📊 Example Output
|
|
236
|
+
|
|
237
|
+
When secrets are detected, KeySentinel posts a formatted comment on your PR:
|
|
238
|
+
|
|
239
|
+
> ⚠️ **Found 2 potential secret(s)** in this pull request.
|
|
240
|
+
>
|
|
241
|
+
> 🔴 **High:** 1
|
|
242
|
+
> 🟠 **Medium:** 1
|
|
243
|
+
>
|
|
244
|
+
> | Severity | File | Line | Type | Confidence | Preview |
|
|
245
|
+
> |:---|:---|---:|:---|:---|:---|
|
|
246
|
+
> | 🔴 High | `src/config.ts` | 15 | AWS Access Key ID | high | `aws_key = "AKI**********XYZ"` |
|
|
247
|
+
> | 🟠 Medium | `api/handler.ts` | 42 | Generic API Key | high | `api_key: "abc**********xyz"` |
|
|
248
|
+
|
|
249
|
+
## 🎛️ Advanced Usage
|
|
250
|
+
|
|
251
|
+
### Using Action Outputs
|
|
252
|
+
|
|
253
|
+
Access scan results in your workflow:
|
|
254
|
+
|
|
255
|
+
```yaml
|
|
256
|
+
- uses: Vishrut19/KeySentinel@v0
|
|
257
|
+
id: scan
|
|
258
|
+
env:
|
|
259
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
260
|
+
|
|
261
|
+
- name: Check results
|
|
262
|
+
run: |
|
|
263
|
+
echo "Found ${{ steps.scan.outputs.secrets_found }} secrets"
|
|
264
|
+
echo "${{ steps.scan.outputs.findings }}" | jq .
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Custom Failure Behavior
|
|
268
|
+
|
|
269
|
+
Fail on medium or high severity:
|
|
270
|
+
|
|
271
|
+
```yaml
|
|
272
|
+
- uses: Vishrut19/KeySentinel@v0
|
|
273
|
+
with:
|
|
274
|
+
github_token: ${{ github.token }}
|
|
275
|
+
fail_on: medium # Fail on medium and high
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Ignore Specific Files
|
|
279
|
+
|
|
280
|
+
```yaml
|
|
281
|
+
- uses: Vishrut19/KeySentinel@v0
|
|
282
|
+
with:
|
|
283
|
+
github_token: ${{ github.token }}
|
|
284
|
+
ignore: "*.test.ts,fixtures/**,docs/**"
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Allowlist False Positives
|
|
288
|
+
|
|
289
|
+
```yaml
|
|
290
|
+
- uses: Vishrut19/KeySentinel@v0
|
|
291
|
+
with:
|
|
292
|
+
github_token: ${{ github.token }}
|
|
293
|
+
allowlist: "EXAMPLE_KEY_.*,test_token_.*"
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Using with Forked PRs
|
|
297
|
+
|
|
298
|
+
For forks, use `pull_request_target` (use with caution):
|
|
299
|
+
|
|
300
|
+
```yaml
|
|
301
|
+
on:
|
|
302
|
+
pull_request_target:
|
|
303
|
+
types: [opened, synchronize, reopened]
|
|
304
|
+
|
|
305
|
+
jobs:
|
|
306
|
+
scan:
|
|
307
|
+
runs-on: ubuntu-latest
|
|
308
|
+
steps:
|
|
309
|
+
- uses: actions/checkout@v4
|
|
310
|
+
with:
|
|
311
|
+
ref: ${{ github.event.pull_request.head.sha }}
|
|
312
|
+
- uses: Vishrut19/KeySentinel@v0
|
|
313
|
+
env:
|
|
314
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
## 🛡️ Security & Privacy
|
|
318
|
+
|
|
319
|
+
**KeySentinel is designed with security in mind:**
|
|
320
|
+
|
|
321
|
+
1. ✅ **Secrets are masked** - Never logs full secret values. Only masked previews (first 3 + last 3 characters) are shown
|
|
322
|
+
2. ✅ **Minimal scope** - Scans only added lines in PR diffs, not entire repositories
|
|
323
|
+
3. ✅ **No external calls** - Runs entirely within GitHub Actions, no data leaves your environment
|
|
324
|
+
4. ✅ **Safe permissions** - Uses GitHub's built-in `GITHUB_TOKEN` with minimal required scopes
|
|
325
|
+
5. ✅ **Local-first** - CLI runs entirely locally, no network calls
|
|
326
|
+
|
|
327
|
+
> ⚠️ **Important:** KeySentinel is a safety net, not a replacement for comprehensive secret scanning. Consider using GitHub's built-in secret scanning for broader protection.
|
|
328
|
+
|
|
329
|
+
## 🐛 Troubleshooting
|
|
330
|
+
|
|
331
|
+
### Action doesn't run
|
|
332
|
+
|
|
333
|
+
Ensure the workflow triggers on `pull_request`:
|
|
334
|
+
|
|
335
|
+
```yaml
|
|
336
|
+
on:
|
|
337
|
+
pull_request:
|
|
338
|
+
types: [opened, synchronize, reopened]
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### No comment posted
|
|
342
|
+
|
|
343
|
+
Check that the workflow has `pull-requests: write` permission:
|
|
344
|
+
|
|
345
|
+
```yaml
|
|
346
|
+
permissions:
|
|
347
|
+
contents: read
|
|
348
|
+
pull-requests: write
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
Also verify **Repository Settings → Actions → General → Workflow Permissions** is set to **Read and write permissions**.
|
|
352
|
+
|
|
353
|
+
### Too many false positives
|
|
354
|
+
|
|
355
|
+
1. Add patterns to the allowlist in `.keysentinel.yml`
|
|
356
|
+
2. Increase entropy threshold (e.g., `threshold: 4.5`)
|
|
357
|
+
3. Disable specific pattern groups that aren't relevant
|
|
358
|
+
|
|
359
|
+
### Missing detections
|
|
360
|
+
|
|
361
|
+
1. Ensure the file isn't in the ignore list
|
|
362
|
+
2. Check if the pattern group is enabled in `.keysentinel.yml`
|
|
363
|
+
3. Lower the entropy threshold if using entropy detection
|
|
364
|
+
|
|
365
|
+
### Pre-commit hook not working
|
|
366
|
+
|
|
367
|
+
- Verify the hook is executable: `chmod +x .git/hooks/pre-commit`
|
|
368
|
+
- Check if `keysentinel` is in your PATH or use `npx keysentinel scan`
|
|
369
|
+
- Run manually: `keysentinel scan` to see error messages
|
|
370
|
+
|
|
371
|
+
## 💰 Pricing
|
|
372
|
+
|
|
373
|
+
**KeySentinel offers a generous free tier with premium features coming soon.**
|
|
374
|
+
|
|
375
|
+
### 🆓 Free Tier (Always Available)
|
|
376
|
+
|
|
377
|
+
The core KeySentinel functionality is **free forever**:
|
|
378
|
+
|
|
379
|
+
- ✅ Unlimited secret scanning
|
|
380
|
+
- ✅ All 50+ detection patterns
|
|
381
|
+
- ✅ GitHub Action integration
|
|
382
|
+
- ✅ Pre-commit & pre-push hooks
|
|
383
|
+
- ✅ Local CLI tool
|
|
384
|
+
- ✅ Full configuration options
|
|
385
|
+
- ✅ No usage limits
|
|
386
|
+
- ✅ No external service dependencies
|
|
387
|
+
- ✅ Runs entirely within GitHub Actions
|
|
388
|
+
|
|
389
|
+
### 🚀 Premium Features (Coming Soon)
|
|
390
|
+
|
|
391
|
+
We're building premium features to help teams scale:
|
|
392
|
+
|
|
393
|
+
- 🔒 **Advanced Pattern Detection** - Custom pattern creation and ML-based detection
|
|
394
|
+
- 📊 **Analytics Dashboard** - Track secret detection trends and team compliance
|
|
395
|
+
- 🔔 **Slack/Email Notifications** - Real-time alerts for critical findings
|
|
396
|
+
- 👥 **Team Management** - Role-based access control and team policies
|
|
397
|
+
- 🔄 **CI/CD Integrations** - Native support for GitLab, Bitbucket, Azure DevOps
|
|
398
|
+
- 📈 **Historical Analysis** - Scan entire repository history for existing leaks
|
|
399
|
+
- 🛡️ **Enterprise Support** - Priority support and custom integrations
|
|
400
|
+
|
|
401
|
+
**Interested in premium features?** [Join our waitlist](https://github.com/Vishrut19/KeySentinel/discussions) or [contact us](mailto:support@keysentinel.dev) for early access.
|
|
402
|
+
|
|
403
|
+
> 💡 **Note:** The free tier will always include all current features. Premium features will be additive, not replacements.
|
|
404
|
+
|
|
405
|
+
## 🗺️ Roadmap
|
|
406
|
+
|
|
407
|
+
We're constantly improving KeySentinel. Here's what's coming:
|
|
408
|
+
|
|
409
|
+
### 🎯 Q2 2025
|
|
410
|
+
- [ ] Custom pattern builder UI
|
|
411
|
+
- [ ] Slack/Teams integration
|
|
412
|
+
- [ ] Enhanced analytics dashboard
|
|
413
|
+
- [ ] GitLab CI/CD support
|
|
414
|
+
|
|
415
|
+
### 🎯 Q3 2025
|
|
416
|
+
- [ ] ML-based secret detection
|
|
417
|
+
- [ ] Historical repository scanning
|
|
418
|
+
- [ ] Enterprise SSO integration
|
|
419
|
+
- [ ] API for custom integrations
|
|
420
|
+
|
|
421
|
+
### 🎯 Future
|
|
422
|
+
- [ ] IDE plugins (VS Code, IntelliJ)
|
|
423
|
+
- [ ] Real-time scanning service
|
|
424
|
+
- [ ] Compliance reporting (SOC2, ISO27001)
|
|
425
|
+
- [ ] Custom remediation workflows
|
|
426
|
+
|
|
427
|
+
**Have a feature request?** [Open an issue](https://github.com/Vishrut19/KeySentinel/issues) or [join our discussions](https://github.com/Vishrut19/KeySentinel/discussions).
|
|
428
|
+
|
|
429
|
+
## 💝 Support KeySentinel
|
|
430
|
+
|
|
431
|
+
KeySentinel is free and open source, but maintaining it takes time and resources. Here's how you can help:
|
|
432
|
+
|
|
433
|
+
- ⭐ **Star the repository** - Help others discover KeySentinel
|
|
434
|
+
- 🐛 **Report bugs** - Help us improve stability
|
|
435
|
+
- 💡 **Suggest features** - Shape the future of KeySentinel
|
|
436
|
+
- 📢 **Share with your team** - Spread the word
|
|
437
|
+
- ☕ [**Sponsor the project**](https://github.com/sponsors/Vishrut19) - Support ongoing development
|
|
438
|
+
|
|
439
|
+
Your support helps us build better tools for the developer community! 🙏
|
|
440
|
+
|
|
441
|
+
## 🤝 Contributing
|
|
442
|
+
|
|
443
|
+
Contributions are welcome! Whether it's:
|
|
444
|
+
- 🐛 Reporting bugs
|
|
445
|
+
- 💡 Suggesting features
|
|
446
|
+
- 📝 Improving documentation
|
|
447
|
+
- 🔧 Submitting pull requests
|
|
448
|
+
|
|
449
|
+
We appreciate your help making KeySentinel better for everyone.
|
|
450
|
+
|
|
451
|
+
**Getting started:**
|
|
452
|
+
1. Fork the repository
|
|
453
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
454
|
+
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
455
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
456
|
+
5. Open a Pull Request
|
|
457
|
+
|
|
458
|
+
## 📄 License
|
|
459
|
+
|
|
460
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
461
|
+
|
|
462
|
+
## ⭐ Show Your Support
|
|
463
|
+
|
|
464
|
+
If KeySentinel has helped protect your codebase, consider giving it a star! ⭐
|
|
465
|
+
|
|
466
|
+
[](https://github.com/Vishrut19/KeySentinel/stargazers)
|
|
467
|
+
|
|
468
|
+
<div align="center">
|
|
469
|
+
|
|
470
|
+
**Made with ❤️ by the Vishrut Agarwalla**
|
|
471
|
+
|
|
472
|
+
[Report Bug](https://github.com/Vishrut19/KeySentinel/issues) • [Request Feature](https://github.com/Vishrut19/KeySentinel/issues) • [Documentation](https://github.com/Vishrut19/KeySentinel#readme)
|
|
473
|
+
|
|
474
|
+
</div>
|
package/dist/cli.d.ts
ADDED
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration handling for KeySentinel
|
|
3
|
+
*/
|
|
4
|
+
import { Severity, EntropyConfig } from './patterns';
|
|
5
|
+
export interface Config {
|
|
6
|
+
failOn: Severity | 'off';
|
|
7
|
+
postNoFindings: boolean;
|
|
8
|
+
ignore: string[];
|
|
9
|
+
allowlist: RegExp[];
|
|
10
|
+
maxFiles: number;
|
|
11
|
+
patterns: Record<string, boolean>;
|
|
12
|
+
entropy: EntropyConfig;
|
|
13
|
+
}
|
|
14
|
+
/** Overrides for config (e.g. from Action inputs or CLI flags). */
|
|
15
|
+
export interface ConfigOverrides {
|
|
16
|
+
failOn?: string;
|
|
17
|
+
postNoFindings?: boolean;
|
|
18
|
+
ignore?: string;
|
|
19
|
+
allowlist?: string;
|
|
20
|
+
maxFiles?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface ConfigLogger {
|
|
23
|
+
warn?(message: string): void;
|
|
24
|
+
debug?(message: string): void;
|
|
25
|
+
info?(message: string): void;
|
|
26
|
+
}
|
|
27
|
+
interface YamlConfig {
|
|
28
|
+
fail_on?: string;
|
|
29
|
+
post_no_findings?: boolean;
|
|
30
|
+
ignore?: string[];
|
|
31
|
+
allowlist?: string[];
|
|
32
|
+
max_files?: number;
|
|
33
|
+
patterns?: Record<string, boolean>;
|
|
34
|
+
entropy?: {
|
|
35
|
+
enabled?: boolean;
|
|
36
|
+
min_length?: number;
|
|
37
|
+
threshold?: number;
|
|
38
|
+
ignore_base64_like?: boolean;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Load YAML config from path. Uses logger for messages (Action passes core, CLI uses console).
|
|
43
|
+
*/
|
|
44
|
+
export declare function loadYamlConfig(configPath: string, logger?: ConfigLogger): YamlConfig | null;
|
|
45
|
+
/**
|
|
46
|
+
* Build Config from YAML and overrides. Pure merge: defaults, then YAML, then overrides.
|
|
47
|
+
*/
|
|
48
|
+
export declare function buildConfig(yamlConfig: YamlConfig | null, overrides: ConfigOverrides, logger?: ConfigLogger): Config;
|
|
49
|
+
/** Load config for GitHub Action (uses @actions/core inputs). */
|
|
50
|
+
export declare function loadConfig(): Config;
|
|
51
|
+
/**
|
|
52
|
+
* Load config for CLI (no @actions/core). Reads .keysentinel.yml from cwd (or configPath).
|
|
53
|
+
*/
|
|
54
|
+
export declare function loadConfigForCli(options?: {
|
|
55
|
+
cwd?: string;
|
|
56
|
+
configPath?: string;
|
|
57
|
+
}): Config;
|
|
58
|
+
/**
|
|
59
|
+
* Check if a file path matches any ignore glob
|
|
60
|
+
*/
|
|
61
|
+
export declare function shouldIgnoreFile(filePath: string, ignorePatterns: string[]): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Check if a value matches any allowlist pattern
|
|
64
|
+
*/
|
|
65
|
+
export declare function isAllowlisted(value: string, allowlist: RegExp[]): boolean;
|
|
66
|
+
export {};
|
package/dist/github.d.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub API wrapper for KeySentinel
|
|
3
|
+
*/
|
|
4
|
+
import * as github from '@actions/github';
|
|
5
|
+
export type Octokit = ReturnType<typeof github.getOctokit>;
|
|
6
|
+
export interface PullRequestFile {
|
|
7
|
+
filename: string;
|
|
8
|
+
status: string;
|
|
9
|
+
additions: number;
|
|
10
|
+
deletions: number;
|
|
11
|
+
changes: number;
|
|
12
|
+
patch?: string;
|
|
13
|
+
sha: string;
|
|
14
|
+
blob_url: string;
|
|
15
|
+
raw_url: string;
|
|
16
|
+
contents_url: string;
|
|
17
|
+
}
|
|
18
|
+
export interface CommentInfo {
|
|
19
|
+
id: number;
|
|
20
|
+
body: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function createOctokit(token: string): Octokit;
|
|
23
|
+
/**
|
|
24
|
+
* Get PR context from the event
|
|
25
|
+
*/
|
|
26
|
+
export declare function getPRContext(): {
|
|
27
|
+
owner: string;
|
|
28
|
+
repo: string;
|
|
29
|
+
pullNumber: number;
|
|
30
|
+
} | null;
|
|
31
|
+
/**
|
|
32
|
+
* Fetch files changed in a PR
|
|
33
|
+
*/
|
|
34
|
+
export declare function getPRFiles(octokit: Octokit, owner: string, repo: string, pullNumber: number, maxFiles: number): Promise<PullRequestFile[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Fetch file content at a specific ref
|
|
37
|
+
*/
|
|
38
|
+
export declare function getFileContent(octokit: Octokit, owner: string, repo: string, path: string, ref: string): Promise<string | null>;
|
|
39
|
+
/**
|
|
40
|
+
* Find existing KeySentinel comment on PR
|
|
41
|
+
*/
|
|
42
|
+
export declare function findExistingComment(octokit: Octokit, owner: string, repo: string, pullNumber: number): Promise<CommentInfo | null>;
|
|
43
|
+
/**
|
|
44
|
+
* Create or update PR comment
|
|
45
|
+
*/
|
|
46
|
+
export declare function upsertComment(octokit: Octokit, owner: string, repo: string, pullNumber: number, body: string): Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Delete existing KeySentinel comment if present
|
|
49
|
+
*/
|
|
50
|
+
export declare function deleteExistingComment(octokit: Octokit, owner: string, repo: string, pullNumber: number): Promise<boolean>;
|
|
51
|
+
/**
|
|
52
|
+
* Get the PR head SHA
|
|
53
|
+
*/
|
|
54
|
+
export declare function getPRHeadSha(): string;
|
package/dist/index.d.ts
ADDED