keyguard-scan 0.1.0__tar.gz
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.
- keyguard_scan-0.1.0/PKG-INFO +339 -0
- keyguard_scan-0.1.0/README.md +311 -0
- keyguard_scan-0.1.0/keyguard/__init__.py +1 -0
- keyguard_scan-0.1.0/keyguard/auditor/__init__.py +0 -0
- keyguard_scan-0.1.0/keyguard/auditor/audit.py +84 -0
- keyguard_scan-0.1.0/keyguard/auditor/client.py +82 -0
- keyguard_scan-0.1.0/keyguard/auditor/output.py +62 -0
- keyguard_scan-0.1.0/keyguard/ci/__init__.py +0 -0
- keyguard_scan-0.1.0/keyguard/ci/circleci.py +116 -0
- keyguard_scan-0.1.0/keyguard/ci/github.py +101 -0
- keyguard_scan-0.1.0/keyguard/ci/gitlab.py +94 -0
- keyguard_scan-0.1.0/keyguard/ci/models.py +39 -0
- keyguard_scan-0.1.0/keyguard/ci/output.py +68 -0
- keyguard_scan-0.1.0/keyguard/ci/scan.py +62 -0
- keyguard_scan-0.1.0/keyguard/cli.py +258 -0
- keyguard_scan-0.1.0/keyguard/config.py +81 -0
- keyguard_scan-0.1.0/keyguard/engine/__init__.py +0 -0
- keyguard_scan-0.1.0/keyguard/engine/matcher.py +35 -0
- keyguard_scan-0.1.0/keyguard/engine/rules.py +36 -0
- keyguard_scan-0.1.0/keyguard/entropy.py +14 -0
- keyguard_scan-0.1.0/keyguard/models.py +48 -0
- keyguard_scan-0.1.0/keyguard/output/__init__.py +0 -0
- keyguard_scan-0.1.0/keyguard/output/structured.py +64 -0
- keyguard_scan-0.1.0/keyguard/output/terminal.py +41 -0
- keyguard_scan-0.1.0/keyguard/output/webhook.py +38 -0
- keyguard_scan-0.1.0/keyguard/scan.py +28 -0
- keyguard_scan-0.1.0/keyguard/scanner/__init__.py +0 -0
- keyguard_scan-0.1.0/keyguard/scanner/file.py +33 -0
- keyguard_scan-0.1.0/keyguard/scanner/git.py +54 -0
- keyguard_scan-0.1.0/keyguard_scan.egg-info/PKG-INFO +339 -0
- keyguard_scan-0.1.0/keyguard_scan.egg-info/SOURCES.txt +59 -0
- keyguard_scan-0.1.0/keyguard_scan.egg-info/dependency_links.txt +1 -0
- keyguard_scan-0.1.0/keyguard_scan.egg-info/entry_points.txt +2 -0
- keyguard_scan-0.1.0/keyguard_scan.egg-info/requires.txt +12 -0
- keyguard_scan-0.1.0/keyguard_scan.egg-info/top_level.txt +1 -0
- keyguard_scan-0.1.0/pyproject.toml +46 -0
- keyguard_scan-0.1.0/setup.cfg +4 -0
- keyguard_scan-0.1.0/tests/test_ci_circleci.py +107 -0
- keyguard_scan-0.1.0/tests/test_ci_cli.py +70 -0
- keyguard_scan-0.1.0/tests/test_ci_config.py +56 -0
- keyguard_scan-0.1.0/tests/test_ci_github.py +91 -0
- keyguard_scan-0.1.0/tests/test_ci_gitlab.py +67 -0
- keyguard_scan-0.1.0/tests/test_ci_models.py +67 -0
- keyguard_scan-0.1.0/tests/test_ci_output.py +65 -0
- keyguard_scan-0.1.0/tests/test_ci_scan.py +74 -0
- keyguard_scan-0.1.0/tests/test_cli.py +97 -0
- keyguard_scan-0.1.0/tests/test_config.py +54 -0
- keyguard_scan-0.1.0/tests/test_entropy.py +27 -0
- keyguard_scan-0.1.0/tests/test_file_scanner.py +62 -0
- keyguard_scan-0.1.0/tests/test_gcp_audit.py +167 -0
- keyguard_scan-0.1.0/tests/test_gcp_cli.py +82 -0
- keyguard_scan-0.1.0/tests/test_gcp_client.py +101 -0
- keyguard_scan-0.1.0/tests/test_gcp_output.py +80 -0
- keyguard_scan-0.1.0/tests/test_git_scanner.py +57 -0
- keyguard_scan-0.1.0/tests/test_integration.py +93 -0
- keyguard_scan-0.1.0/tests/test_matcher.py +86 -0
- keyguard_scan-0.1.0/tests/test_models.py +51 -0
- keyguard_scan-0.1.0/tests/test_rules.py +43 -0
- keyguard_scan-0.1.0/tests/test_structured.py +73 -0
- keyguard_scan-0.1.0/tests/test_terminal.py +65 -0
- keyguard_scan-0.1.0/tests/test_webhook.py +76 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: keyguard-scan
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Scan codebases, GCP projects, and CI pipelines for exposed Google API credentials
|
|
5
|
+
Author-email: arzaan789 <arzaaan789@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/arzaan789/keyguard
|
|
8
|
+
Project-URL: Repository, https://github.com/arzaan789/keyguard
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/arzaan789/keyguard/issues
|
|
10
|
+
Keywords: security,credentials,api-keys,google-cloud,gemini,secret-scanning
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Security
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Requires-Python: >=3.11
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
Requires-Dist: click>=8.1
|
|
18
|
+
Requires-Dist: rich>=13.0
|
|
19
|
+
Requires-Dist: gitpython>=3.1
|
|
20
|
+
Requires-Dist: pathspec>=0.12
|
|
21
|
+
Requires-Dist: watchdog>=4.0
|
|
22
|
+
Requires-Dist: requests>=2.31
|
|
23
|
+
Requires-Dist: google-auth>=2.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
27
|
+
Requires-Dist: responses>=0.25; extra == "dev"
|
|
28
|
+
|
|
29
|
+
# keyguard
|
|
30
|
+
|
|
31
|
+
Scan codebases, GCP projects, and CI pipelines for exposed Google API credentials — before they get exploited.
|
|
32
|
+
|
|
33
|
+
**The problem:** Google retroactively enabled Gemini API access on existing API keys (Maps, Places, etc.) that were designed to be public and embedded in client-side code. When someone on your team enables Gemini in the same GCP project, those already-public keys silently become Gemini credentials — exposing your project to unauthorized AI usage and $80k+ billing incidents ([context](https://news.ycombinator.com/item?id=47156925)).
|
|
34
|
+
|
|
35
|
+
**What keyguard does:**
|
|
36
|
+
- `keyguard scan` — finds credential strings in source files and git history using regex + entropy detection
|
|
37
|
+
- `keyguard audit` — connects to live GCP projects and flags API keys that have Gemini access right now
|
|
38
|
+
- `keyguard ci` — scans GitHub Actions, CircleCI, and GitLab CI logs and variables for leaked credentials
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install keyguard-scan
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or clone and install in development mode:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
git clone https://github.com/arzaan789/keyguard.git
|
|
52
|
+
cd keyguard
|
|
53
|
+
pip install -e ".[dev]"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Quick Start
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Scan current directory and git history
|
|
62
|
+
keyguard scan .
|
|
63
|
+
|
|
64
|
+
# Audit your live GCP projects
|
|
65
|
+
keyguard audit
|
|
66
|
+
|
|
67
|
+
# Scan CI platforms
|
|
68
|
+
keyguard ci
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Commands
|
|
74
|
+
|
|
75
|
+
### `keyguard scan`
|
|
76
|
+
|
|
77
|
+
Scans source files and git history for exposed credentials using regex + Shannon entropy filtering. Low-entropy placeholders like `"REPLACE_ME"` or `"XXXXXXXX"` are automatically ignored.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Scan a directory (files + full git history)
|
|
81
|
+
keyguard scan .
|
|
82
|
+
|
|
83
|
+
# Files only, skip git history
|
|
84
|
+
keyguard scan . --no-git-history
|
|
85
|
+
|
|
86
|
+
# Export to JSON and SARIF
|
|
87
|
+
keyguard scan . --output json --output sarif --out-file report
|
|
88
|
+
|
|
89
|
+
# Show actual key values (not redacted)
|
|
90
|
+
keyguard scan . --no-redact
|
|
91
|
+
|
|
92
|
+
# Use a custom config file
|
|
93
|
+
keyguard scan . --config /path/to/.keyguard.toml
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**Exit codes:** `0` = clean, `1` = findings, `2` = error
|
|
97
|
+
|
|
98
|
+
### `keyguard audit`
|
|
99
|
+
|
|
100
|
+
Connects to live GCP projects via the Cloud Resource Manager, Service Usage, and API Keys APIs. Flags keys that are unrestricted (silent Gemini access) or that explicitly allow `generativelanguage.googleapis.com` while Gemini is enabled on the project.
|
|
101
|
+
|
|
102
|
+
Authentication uses [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials) by default — run `gcloud auth application-default login` first.
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
# Audit all accessible GCP projects
|
|
106
|
+
keyguard audit
|
|
107
|
+
|
|
108
|
+
# Audit specific project(s)
|
|
109
|
+
keyguard audit --project my-project-id --project another-project
|
|
110
|
+
|
|
111
|
+
# Use a service account key file
|
|
112
|
+
keyguard audit --gcp-credentials /path/to/key.json
|
|
113
|
+
|
|
114
|
+
# Export JSON findings
|
|
115
|
+
keyguard audit --output json --out-file gcp-findings.json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
**Findings:**
|
|
119
|
+
- `CRITICAL` — key has no API restrictions + Gemini is enabled (the silent Maps→Gemini upgrade scenario)
|
|
120
|
+
- `HIGH` — key explicitly allows `generativelanguage.googleapis.com` (intentional but potentially embedded in client code)
|
|
121
|
+
|
|
122
|
+
### `keyguard ci`
|
|
123
|
+
|
|
124
|
+
Scans CI platform logs and stored variables for exposed credentials. Supports GitHub Actions, CircleCI, and GitLab CI.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Scan all configured platforms
|
|
128
|
+
keyguard ci
|
|
129
|
+
|
|
130
|
+
# Scan one platform only
|
|
131
|
+
keyguard ci --platform github
|
|
132
|
+
|
|
133
|
+
# Narrow to a specific repo
|
|
134
|
+
keyguard ci --repo my-org/api-service
|
|
135
|
+
|
|
136
|
+
# Export JSON findings
|
|
137
|
+
keyguard ci --output json --out-file ci-findings.json
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**What it scans:**
|
|
141
|
+
- **GitHub Actions** — plaintext repository variables + workflow run job logs
|
|
142
|
+
- **CircleCI** — environment variable names (values are masked by CircleCI) + pipeline job step logs
|
|
143
|
+
- **GitLab CI** — project variables (plaintext) + pipeline job traces
|
|
144
|
+
|
|
145
|
+
### `keyguard watch`
|
|
146
|
+
|
|
147
|
+
Re-scans files on every change. Useful during development.
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
keyguard watch .
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### `keyguard rules list`
|
|
154
|
+
|
|
155
|
+
Lists all active detection rules.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
keyguard rules list
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### `keyguard config check`
|
|
162
|
+
|
|
163
|
+
Validates a `.keyguard.toml` configuration file.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
keyguard config check
|
|
167
|
+
keyguard config check --config /path/to/.keyguard.toml
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Configuration
|
|
173
|
+
|
|
174
|
+
Create a `.keyguard.toml` in your project root:
|
|
175
|
+
|
|
176
|
+
```toml
|
|
177
|
+
[scan]
|
|
178
|
+
paths = ["."]
|
|
179
|
+
exclude = ["tests/fixtures/", "**/*.example"]
|
|
180
|
+
scan_git_history = true
|
|
181
|
+
|
|
182
|
+
[output]
|
|
183
|
+
format = ["terminal", "json"]
|
|
184
|
+
redact = true
|
|
185
|
+
|
|
186
|
+
[notify]
|
|
187
|
+
slack_webhook = "https://hooks.slack.com/services/..."
|
|
188
|
+
|
|
189
|
+
[rules]
|
|
190
|
+
disabled = []
|
|
191
|
+
|
|
192
|
+
# CI platform authentication and scope
|
|
193
|
+
[ci]
|
|
194
|
+
github_token = "ghp_xxxxxxxxxxxxxxxxxxxx"
|
|
195
|
+
circleci_token = "CCIPAT_xxxxxxxxxxxxxxxx"
|
|
196
|
+
gitlab_token = "glpat-xxxxxxxxxxxxxxxxxxxx"
|
|
197
|
+
gitlab_url = "https://gitlab.com" # override for self-hosted GitLab
|
|
198
|
+
max_runs = 10 # recent runs/pipelines per repo
|
|
199
|
+
|
|
200
|
+
[ci.github]
|
|
201
|
+
orgs = ["my-org"]
|
|
202
|
+
repos = ["my-org/specific-repo"] # optional: scan specific repos only
|
|
203
|
+
|
|
204
|
+
[ci.circleci]
|
|
205
|
+
orgs = ["my-org"]
|
|
206
|
+
|
|
207
|
+
[ci.gitlab]
|
|
208
|
+
groups = ["my-group"]
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Detection
|
|
214
|
+
|
|
215
|
+
Keyguard uses a **regex + Shannon entropy** approach. Each rule defines:
|
|
216
|
+
- A pattern that matches the credential's structure (e.g., `AIza[0-9A-Za-z\-_]{35}` for Google API keys)
|
|
217
|
+
- A minimum entropy threshold that filters out low-entropy placeholders
|
|
218
|
+
|
|
219
|
+
Built-in rules detect:
|
|
220
|
+
| Rule ID | What it finds |
|
|
221
|
+
|---|---|
|
|
222
|
+
| `google-api-key` | Google API keys (`AIza...`) — including Maps keys silently granted Gemini access |
|
|
223
|
+
| `gcp-service-account-key` | GCP service account RSA private keys |
|
|
224
|
+
| `google-oauth-client-secret` | Google OAuth2 client secrets (`GOCSPX-...`) |
|
|
225
|
+
|
|
226
|
+
You can add custom rules in `.keyguard.toml`:
|
|
227
|
+
|
|
228
|
+
```toml
|
|
229
|
+
[[rules.extra]]
|
|
230
|
+
id = "my-internal-token"
|
|
231
|
+
description = "Internal service token"
|
|
232
|
+
pattern = "tok-[0-9a-f]{32}"
|
|
233
|
+
entropy_min = 3.5
|
|
234
|
+
severity = "high"
|
|
235
|
+
tags = ["internal"]
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## CI Integration
|
|
241
|
+
|
|
242
|
+
### GitHub Actions
|
|
243
|
+
|
|
244
|
+
```yaml
|
|
245
|
+
name: keyguard scan
|
|
246
|
+
|
|
247
|
+
on: [push, pull_request]
|
|
248
|
+
|
|
249
|
+
jobs:
|
|
250
|
+
scan:
|
|
251
|
+
runs-on: ubuntu-latest
|
|
252
|
+
steps:
|
|
253
|
+
- uses: actions/checkout@v4
|
|
254
|
+
with:
|
|
255
|
+
fetch-depth: 0 # full history for git scan
|
|
256
|
+
- run: pip install keyguard-scan
|
|
257
|
+
- run: keyguard scan .
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Pre-commit hook
|
|
261
|
+
|
|
262
|
+
```yaml
|
|
263
|
+
# .pre-commit-config.yaml
|
|
264
|
+
repos:
|
|
265
|
+
- repo: local
|
|
266
|
+
hooks:
|
|
267
|
+
- id: keyguard
|
|
268
|
+
name: keyguard credential scan
|
|
269
|
+
entry: keyguard scan --no-git-history
|
|
270
|
+
language: system
|
|
271
|
+
pass_filenames: false
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Docker
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
docker run --rm -v $(pwd):/repo ghcr.io/arzaan789/keyguard scan /repo
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Output Formats
|
|
283
|
+
|
|
284
|
+
**Terminal** (default) — colored table grouped by severity.
|
|
285
|
+
|
|
286
|
+
**JSON** — machine-readable findings array:
|
|
287
|
+
```bash
|
|
288
|
+
keyguard scan . --output json --out-file findings.json
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
**SARIF** — integrates with GitHub's Security tab and other SAST tools:
|
|
292
|
+
```bash
|
|
293
|
+
keyguard scan . --output sarif --out-file findings.sarif
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
**Slack webhook** — posts a summary when findings are detected:
|
|
297
|
+
```toml
|
|
298
|
+
[notify]
|
|
299
|
+
slack_webhook = "https://hooks.slack.com/services/..."
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Development
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
git clone https://github.com/arzaan789/keyguard.git
|
|
308
|
+
cd keyguard
|
|
309
|
+
pip install -e ".[dev]"
|
|
310
|
+
pytest
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**143 tests, 0 failures.**
|
|
314
|
+
|
|
315
|
+
Project structure:
|
|
316
|
+
```
|
|
317
|
+
keyguard/
|
|
318
|
+
scanner/ # file + git history scanners
|
|
319
|
+
engine/ # regex + entropy detection (rules, matcher)
|
|
320
|
+
output/ # terminal, JSON/SARIF, webhook
|
|
321
|
+
auditor/ # GCP API client + audit logic
|
|
322
|
+
ci/ # GitHub Actions, CircleCI, GitLab CI scanners
|
|
323
|
+
cli.py # Click CLI entry point
|
|
324
|
+
config.py # .keyguard.toml loader
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Roadmap
|
|
330
|
+
|
|
331
|
+
- [x] v1 — File scanner (source code + git history)
|
|
332
|
+
- [x] v2 — GCP API auditor (live project audit via GCP APIs)
|
|
333
|
+
- [x] v3 — CI platform integration (GitHub Actions, CircleCI, GitLab CI)
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## License
|
|
338
|
+
|
|
339
|
+
MIT
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# keyguard
|
|
2
|
+
|
|
3
|
+
Scan codebases, GCP projects, and CI pipelines for exposed Google API credentials — before they get exploited.
|
|
4
|
+
|
|
5
|
+
**The problem:** Google retroactively enabled Gemini API access on existing API keys (Maps, Places, etc.) that were designed to be public and embedded in client-side code. When someone on your team enables Gemini in the same GCP project, those already-public keys silently become Gemini credentials — exposing your project to unauthorized AI usage and $80k+ billing incidents ([context](https://news.ycombinator.com/item?id=47156925)).
|
|
6
|
+
|
|
7
|
+
**What keyguard does:**
|
|
8
|
+
- `keyguard scan` — finds credential strings in source files and git history using regex + entropy detection
|
|
9
|
+
- `keyguard audit` — connects to live GCP projects and flags API keys that have Gemini access right now
|
|
10
|
+
- `keyguard ci` — scans GitHub Actions, CircleCI, and GitLab CI logs and variables for leaked credentials
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install keyguard-scan
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or clone and install in development mode:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git clone https://github.com/arzaan789/keyguard.git
|
|
24
|
+
cd keyguard
|
|
25
|
+
pip install -e ".[dev]"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Quick Start
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Scan current directory and git history
|
|
34
|
+
keyguard scan .
|
|
35
|
+
|
|
36
|
+
# Audit your live GCP projects
|
|
37
|
+
keyguard audit
|
|
38
|
+
|
|
39
|
+
# Scan CI platforms
|
|
40
|
+
keyguard ci
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Commands
|
|
46
|
+
|
|
47
|
+
### `keyguard scan`
|
|
48
|
+
|
|
49
|
+
Scans source files and git history for exposed credentials using regex + Shannon entropy filtering. Low-entropy placeholders like `"REPLACE_ME"` or `"XXXXXXXX"` are automatically ignored.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Scan a directory (files + full git history)
|
|
53
|
+
keyguard scan .
|
|
54
|
+
|
|
55
|
+
# Files only, skip git history
|
|
56
|
+
keyguard scan . --no-git-history
|
|
57
|
+
|
|
58
|
+
# Export to JSON and SARIF
|
|
59
|
+
keyguard scan . --output json --output sarif --out-file report
|
|
60
|
+
|
|
61
|
+
# Show actual key values (not redacted)
|
|
62
|
+
keyguard scan . --no-redact
|
|
63
|
+
|
|
64
|
+
# Use a custom config file
|
|
65
|
+
keyguard scan . --config /path/to/.keyguard.toml
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Exit codes:** `0` = clean, `1` = findings, `2` = error
|
|
69
|
+
|
|
70
|
+
### `keyguard audit`
|
|
71
|
+
|
|
72
|
+
Connects to live GCP projects via the Cloud Resource Manager, Service Usage, and API Keys APIs. Flags keys that are unrestricted (silent Gemini access) or that explicitly allow `generativelanguage.googleapis.com` while Gemini is enabled on the project.
|
|
73
|
+
|
|
74
|
+
Authentication uses [Application Default Credentials](https://cloud.google.com/docs/authentication/application-default-credentials) by default — run `gcloud auth application-default login` first.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Audit all accessible GCP projects
|
|
78
|
+
keyguard audit
|
|
79
|
+
|
|
80
|
+
# Audit specific project(s)
|
|
81
|
+
keyguard audit --project my-project-id --project another-project
|
|
82
|
+
|
|
83
|
+
# Use a service account key file
|
|
84
|
+
keyguard audit --gcp-credentials /path/to/key.json
|
|
85
|
+
|
|
86
|
+
# Export JSON findings
|
|
87
|
+
keyguard audit --output json --out-file gcp-findings.json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Findings:**
|
|
91
|
+
- `CRITICAL` — key has no API restrictions + Gemini is enabled (the silent Maps→Gemini upgrade scenario)
|
|
92
|
+
- `HIGH` — key explicitly allows `generativelanguage.googleapis.com` (intentional but potentially embedded in client code)
|
|
93
|
+
|
|
94
|
+
### `keyguard ci`
|
|
95
|
+
|
|
96
|
+
Scans CI platform logs and stored variables for exposed credentials. Supports GitHub Actions, CircleCI, and GitLab CI.
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Scan all configured platforms
|
|
100
|
+
keyguard ci
|
|
101
|
+
|
|
102
|
+
# Scan one platform only
|
|
103
|
+
keyguard ci --platform github
|
|
104
|
+
|
|
105
|
+
# Narrow to a specific repo
|
|
106
|
+
keyguard ci --repo my-org/api-service
|
|
107
|
+
|
|
108
|
+
# Export JSON findings
|
|
109
|
+
keyguard ci --output json --out-file ci-findings.json
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**What it scans:**
|
|
113
|
+
- **GitHub Actions** — plaintext repository variables + workflow run job logs
|
|
114
|
+
- **CircleCI** — environment variable names (values are masked by CircleCI) + pipeline job step logs
|
|
115
|
+
- **GitLab CI** — project variables (plaintext) + pipeline job traces
|
|
116
|
+
|
|
117
|
+
### `keyguard watch`
|
|
118
|
+
|
|
119
|
+
Re-scans files on every change. Useful during development.
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
keyguard watch .
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### `keyguard rules list`
|
|
126
|
+
|
|
127
|
+
Lists all active detection rules.
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
keyguard rules list
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `keyguard config check`
|
|
134
|
+
|
|
135
|
+
Validates a `.keyguard.toml` configuration file.
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
keyguard config check
|
|
139
|
+
keyguard config check --config /path/to/.keyguard.toml
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Configuration
|
|
145
|
+
|
|
146
|
+
Create a `.keyguard.toml` in your project root:
|
|
147
|
+
|
|
148
|
+
```toml
|
|
149
|
+
[scan]
|
|
150
|
+
paths = ["."]
|
|
151
|
+
exclude = ["tests/fixtures/", "**/*.example"]
|
|
152
|
+
scan_git_history = true
|
|
153
|
+
|
|
154
|
+
[output]
|
|
155
|
+
format = ["terminal", "json"]
|
|
156
|
+
redact = true
|
|
157
|
+
|
|
158
|
+
[notify]
|
|
159
|
+
slack_webhook = "https://hooks.slack.com/services/..."
|
|
160
|
+
|
|
161
|
+
[rules]
|
|
162
|
+
disabled = []
|
|
163
|
+
|
|
164
|
+
# CI platform authentication and scope
|
|
165
|
+
[ci]
|
|
166
|
+
github_token = "ghp_xxxxxxxxxxxxxxxxxxxx"
|
|
167
|
+
circleci_token = "CCIPAT_xxxxxxxxxxxxxxxx"
|
|
168
|
+
gitlab_token = "glpat-xxxxxxxxxxxxxxxxxxxx"
|
|
169
|
+
gitlab_url = "https://gitlab.com" # override for self-hosted GitLab
|
|
170
|
+
max_runs = 10 # recent runs/pipelines per repo
|
|
171
|
+
|
|
172
|
+
[ci.github]
|
|
173
|
+
orgs = ["my-org"]
|
|
174
|
+
repos = ["my-org/specific-repo"] # optional: scan specific repos only
|
|
175
|
+
|
|
176
|
+
[ci.circleci]
|
|
177
|
+
orgs = ["my-org"]
|
|
178
|
+
|
|
179
|
+
[ci.gitlab]
|
|
180
|
+
groups = ["my-group"]
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Detection
|
|
186
|
+
|
|
187
|
+
Keyguard uses a **regex + Shannon entropy** approach. Each rule defines:
|
|
188
|
+
- A pattern that matches the credential's structure (e.g., `AIza[0-9A-Za-z\-_]{35}` for Google API keys)
|
|
189
|
+
- A minimum entropy threshold that filters out low-entropy placeholders
|
|
190
|
+
|
|
191
|
+
Built-in rules detect:
|
|
192
|
+
| Rule ID | What it finds |
|
|
193
|
+
|---|---|
|
|
194
|
+
| `google-api-key` | Google API keys (`AIza...`) — including Maps keys silently granted Gemini access |
|
|
195
|
+
| `gcp-service-account-key` | GCP service account RSA private keys |
|
|
196
|
+
| `google-oauth-client-secret` | Google OAuth2 client secrets (`GOCSPX-...`) |
|
|
197
|
+
|
|
198
|
+
You can add custom rules in `.keyguard.toml`:
|
|
199
|
+
|
|
200
|
+
```toml
|
|
201
|
+
[[rules.extra]]
|
|
202
|
+
id = "my-internal-token"
|
|
203
|
+
description = "Internal service token"
|
|
204
|
+
pattern = "tok-[0-9a-f]{32}"
|
|
205
|
+
entropy_min = 3.5
|
|
206
|
+
severity = "high"
|
|
207
|
+
tags = ["internal"]
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## CI Integration
|
|
213
|
+
|
|
214
|
+
### GitHub Actions
|
|
215
|
+
|
|
216
|
+
```yaml
|
|
217
|
+
name: keyguard scan
|
|
218
|
+
|
|
219
|
+
on: [push, pull_request]
|
|
220
|
+
|
|
221
|
+
jobs:
|
|
222
|
+
scan:
|
|
223
|
+
runs-on: ubuntu-latest
|
|
224
|
+
steps:
|
|
225
|
+
- uses: actions/checkout@v4
|
|
226
|
+
with:
|
|
227
|
+
fetch-depth: 0 # full history for git scan
|
|
228
|
+
- run: pip install keyguard-scan
|
|
229
|
+
- run: keyguard scan .
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Pre-commit hook
|
|
233
|
+
|
|
234
|
+
```yaml
|
|
235
|
+
# .pre-commit-config.yaml
|
|
236
|
+
repos:
|
|
237
|
+
- repo: local
|
|
238
|
+
hooks:
|
|
239
|
+
- id: keyguard
|
|
240
|
+
name: keyguard credential scan
|
|
241
|
+
entry: keyguard scan --no-git-history
|
|
242
|
+
language: system
|
|
243
|
+
pass_filenames: false
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Docker
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
docker run --rm -v $(pwd):/repo ghcr.io/arzaan789/keyguard scan /repo
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Output Formats
|
|
255
|
+
|
|
256
|
+
**Terminal** (default) — colored table grouped by severity.
|
|
257
|
+
|
|
258
|
+
**JSON** — machine-readable findings array:
|
|
259
|
+
```bash
|
|
260
|
+
keyguard scan . --output json --out-file findings.json
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**SARIF** — integrates with GitHub's Security tab and other SAST tools:
|
|
264
|
+
```bash
|
|
265
|
+
keyguard scan . --output sarif --out-file findings.sarif
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Slack webhook** — posts a summary when findings are detected:
|
|
269
|
+
```toml
|
|
270
|
+
[notify]
|
|
271
|
+
slack_webhook = "https://hooks.slack.com/services/..."
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Development
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
git clone https://github.com/arzaan789/keyguard.git
|
|
280
|
+
cd keyguard
|
|
281
|
+
pip install -e ".[dev]"
|
|
282
|
+
pytest
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
**143 tests, 0 failures.**
|
|
286
|
+
|
|
287
|
+
Project structure:
|
|
288
|
+
```
|
|
289
|
+
keyguard/
|
|
290
|
+
scanner/ # file + git history scanners
|
|
291
|
+
engine/ # regex + entropy detection (rules, matcher)
|
|
292
|
+
output/ # terminal, JSON/SARIF, webhook
|
|
293
|
+
auditor/ # GCP API client + audit logic
|
|
294
|
+
ci/ # GitHub Actions, CircleCI, GitLab CI scanners
|
|
295
|
+
cli.py # Click CLI entry point
|
|
296
|
+
config.py # .keyguard.toml loader
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Roadmap
|
|
302
|
+
|
|
303
|
+
- [x] v1 — File scanner (source code + git history)
|
|
304
|
+
- [x] v2 — GCP API auditor (live project audit via GCP APIs)
|
|
305
|
+
- [x] v3 — CI platform integration (GitHub Actions, CircleCI, GitLab CI)
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## License
|
|
310
|
+
|
|
311
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
File without changes
|