Skip to main content

Scan codebases, GCP projects, and CI pipelines for exposed Google API credentials

Project description

keyguard

Scan codebases, GCP projects, and CI pipelines for exposed Google API credentials — before they get exploited.

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).

What keyguard does:

  • keyguard scan — finds credential strings in source files and git history using regex + entropy detection
  • keyguard audit — connects to live GCP projects and flags API keys that have Gemini access right now
  • keyguard ci — scans GitHub Actions, CircleCI, and GitLab CI logs and variables for leaked credentials

Install

pip install keyguard-scan

Or clone and install in development mode:

git clone https://github.com/arzaan789/keyguard.git
cd keyguard
pip install -e ".[dev]"

Quick Start

# Scan current directory and git history
keyguard scan .

# Audit your live GCP projects
keyguard audit

# Scan CI platforms
keyguard ci

Commands

keyguard scan

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.

# Scan a directory (files + full git history)
keyguard scan .

# Files only, skip git history
keyguard scan . --no-git-history

# Export to JSON and SARIF
keyguard scan . --output json --output sarif --out-file report

# Show actual key values (not redacted)
keyguard scan . --no-redact

# Use a custom config file
keyguard scan . --config /path/to/.keyguard.toml

Exit codes: 0 = clean, 1 = findings, 2 = error

keyguard audit

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.

Authentication uses Application Default Credentials by default — run gcloud auth application-default login first.

# Audit all accessible GCP projects
keyguard audit

# Audit specific project(s)
keyguard audit --project my-project-id --project another-project

# Use a service account key file
keyguard audit --gcp-credentials /path/to/key.json

# Export JSON findings
keyguard audit --output json --out-file gcp-findings.json

Findings:

  • CRITICAL — key has no API restrictions + Gemini is enabled (the silent Maps→Gemini upgrade scenario)
  • HIGH — key explicitly allows generativelanguage.googleapis.com (intentional but potentially embedded in client code)

keyguard ci

Scans CI platform logs and stored variables for exposed credentials. Supports GitHub Actions, CircleCI, and GitLab CI.

# Scan all configured platforms
keyguard ci

# Scan one platform only
keyguard ci --platform github

# Narrow to a specific repo
keyguard ci --repo my-org/api-service

# Export JSON findings
keyguard ci --output json --out-file ci-findings.json

What it scans:

  • GitHub Actions — plaintext repository variables + workflow run job logs
  • CircleCI — environment variable names (values are masked by CircleCI) + pipeline job step logs
  • GitLab CI — project variables (plaintext) + pipeline job traces

keyguard watch

Re-scans files on every change. Useful during development.

keyguard watch .

keyguard rules list

Lists all active detection rules.

keyguard rules list

keyguard config check

Validates a .keyguard.toml configuration file.

keyguard config check
keyguard config check --config /path/to/.keyguard.toml

Configuration

Create a .keyguard.toml in your project root:

[scan]
paths = ["."]
exclude = ["tests/fixtures/", "**/*.example"]
scan_git_history = true

[output]
format = ["terminal", "json"]
redact = true

[notify]
slack_webhook = "https://hooks.slack.com/services/..."

[rules]
disabled = []

# CI platform authentication and scope
[ci]
github_token    = "ghp_xxxxxxxxxxxxxxxxxxxx"
circleci_token  = "CCIPAT_xxxxxxxxxxxxxxxx"
gitlab_token    = "glpat-xxxxxxxxxxxxxxxxxxxx"
gitlab_url      = "https://gitlab.com"   # override for self-hosted GitLab
max_runs        = 10                     # recent runs/pipelines per repo

[ci.github]
orgs  = ["my-org"]
repos = ["my-org/specific-repo"]         # optional: scan specific repos only

[ci.circleci]
orgs = ["my-org"]

[ci.gitlab]
groups = ["my-group"]

Detection

Keyguard uses a regex + Shannon entropy approach. Each rule defines:

  • A pattern that matches the credential's structure (e.g., AIza[0-9A-Za-z\-_]{35} for Google API keys)
  • A minimum entropy threshold that filters out low-entropy placeholders

Built-in rules detect:

Rule ID What it finds
google-api-key Google API keys (AIza...) — including Maps keys silently granted Gemini access
gcp-service-account-key GCP service account RSA private keys
google-oauth-client-secret Google OAuth2 client secrets (GOCSPX-...)

You can add custom rules in .keyguard.toml:

[[rules.extra]]
id = "my-internal-token"
description = "Internal service token"
pattern = "tok-[0-9a-f]{32}"
entropy_min = 3.5
severity = "high"
tags = ["internal"]

CI Integration

GitHub Actions

name: keyguard scan

on: [push, pull_request]

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0          # full history for git scan
      - run: pip install keyguard-scan
      - run: keyguard scan .

Pre-commit hook

# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: keyguard
        name: keyguard credential scan
        entry: keyguard scan --no-git-history
        language: system
        pass_filenames: false

Docker

docker run --rm -v $(pwd):/repo ghcr.io/arzaan789/keyguard scan /repo

Output Formats

Terminal (default) — colored table grouped by severity.

JSON — machine-readable findings array:

keyguard scan . --output json --out-file findings.json

SARIF — integrates with GitHub's Security tab and other SAST tools:

keyguard scan . --output sarif --out-file findings.sarif

Slack webhook — posts a summary when findings are detected:

[notify]
slack_webhook = "https://hooks.slack.com/services/..."

Development

git clone https://github.com/arzaan789/keyguard.git
cd keyguard
pip install -e ".[dev]"
pytest

143 tests, 0 failures.

Project structure:

keyguard/
  scanner/      # file + git history scanners
  engine/       # regex + entropy detection (rules, matcher)
  output/       # terminal, JSON/SARIF, webhook
  auditor/      # GCP API client + audit logic
  ci/           # GitHub Actions, CircleCI, GitLab CI scanners
  cli.py        # Click CLI entry point
  config.py     # .keyguard.toml loader

Roadmap

  • v1 — File scanner (source code + git history)
  • v2 — GCP API auditor (live project audit via GCP APIs)
  • v3 — CI platform integration (GitHub Actions, CircleCI, GitLab CI)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

keyguard_scan-0.1.0.tar.gz (32.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

keyguard_scan-0.1.0-py3-none-any.whl (25.5 kB view details)

Uploaded Python 3

File details

Details for the file keyguard_scan-0.1.0.tar.gz.

File metadata

  • Download URL: keyguard_scan-0.1.0.tar.gz
  • Upload date:
  • Size: 32.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for keyguard_scan-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e0f5810ecdebef30089dc320ae29c847474dfe1335fdfb6dbb2a6f46463d0b4e
MD5 2b5b4227582e7e7dce302513ee7f1f96
BLAKE2b-256 7bcd8b6ff53b6da10107bd1cfd298043cb3f5a4150bf88e8ee87c64db0fec7fe

See more details on using hashes here.

File details

Details for the file keyguard_scan-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: keyguard_scan-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for keyguard_scan-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e457b608761467b0aad0427d6d0a7343544253fa733f9c97032f1ecf18bb429f
MD5 2934aaf3a977dfc58be6817481c6842a
BLAKE2b-256 7379473132001bd4c307448aea124aa6822ec4316d18bf1a6f3b7475ddc4279a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page