Preventive GCP security scanner for crypto mining and Gemini API abuse vectors
Project description
gcp-abuse-scanner
Preventive GCP security scanner for crypto mining and Gemini API abuse vectors.
gcp-abuse-scanner is an open source CLI tool that scans Google Cloud Platform organizations and projects for security misconfigurations that can be exploited for:
- 🪙 Crypto mining — unauthorized compute resource abuse
- 🤖 Gemini API abuse — unauthorized or uncontrolled access to Generative AI APIs
The tool is read-only and preventive: it never modifies resources, never disables APIs, and never revokes permissions. It produces a prioritized remediation report so you know exactly what to fix and in what order.
Features
- 🔍 ~65+ security checks across Compute, GKE, Cloud Run, IAM, Networking, API Keys, Vertex AI, Billing, and Org Policies
- 🏢 Organization-wide or per-project scanning
- 🔐 Service account authentication (impersonation recommended, key file supported)
- 📊 Multiple output formats: Console (rich), JSON, Markdown, HTML, SARIF 2.1.0
- ⚡ Concurrent collection with retry/backoff — handles large orgs with thousands of projects
- 🎯 Prioritized findings with CRITICAL / HIGH / MEDIUM / LOW severity
- 🚫 Allowlist support for known exceptions
- 🔌 Plugin architecture — add new checks without touching the core
Quickstart
Installation
# Recommended: pipx (isolated environment)
pipx install gcp-abuse-scanner
# Or pip
pip install gcp-abuse-scanner
# Or Docker
docker run --rm -v ~/.config/gcloud:/root/.config/gcloud \
ghcr.io/lmoreno0435/gcp-abuse-scanner:latest scan --org YOUR_ORG_ID
Authentication
Recommended: Service Account Impersonation
gcp-abuse-scanner scan --org 123456789012 \
--impersonate-service-account scanner-sa@your-project.iam.gserviceaccount.com
Alternative: Service Account Key File
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/sa-key.json
gcp-abuse-scanner scan --org 123456789012
⚠️ Using key files is an anti-pattern. Prefer impersonation or Workload Identity Federation.
Basic Usage
# Scan entire organization
gcp-abuse-scanner scan --org 123456789012
# Scan specific projects
gcp-abuse-scanner scan --project my-project-1 --project my-project-2
# Output as JSON
gcp-abuse-scanner scan --org 123456789012 --format json --output report.json
# Output as Markdown
gcp-abuse-scanner scan --org 123456789012 --format markdown --output report.md
# Output as self-contained HTML report
gcp-abuse-scanner scan --org 123456789012 --format html --output report.html
# Output as SARIF 2.1.0 (GitHub Advanced Security, VS Code)
gcp-abuse-scanner scan --org 123456789012 --format sarif --output results.sarif
# All formats at once (auto-named files)
gcp-abuse-scanner scan --org 123456789012 --format all
# Scan only Gemini abuse vector
gcp-abuse-scanner scan --org 123456789012 --vector gemini_abuse
# Speed up re-runs with inventory cache (1h TTL)
gcp-abuse-scanner scan --org 123456789012 --cache
# List all available checks
gcp-abuse-scanner list-checks
# Dry run (resolve scope without scanning)
gcp-abuse-scanner scan --org 123456789012 --dry-run
Prerequisites — GCP APIs
The scanner calls GCP APIs to collect resource inventory. These APIs must be enabled before running a scan.
Quick setup (recommended)
# Clone the repo to get the script, then run:
bash scripts/enable_apis.sh \
--org YOUR_ORG_ID \
--scanner-project YOUR_SCANNER_PROJECT
# Dry-run first to preview changes:
bash scripts/enable_apis.sh \
--org YOUR_ORG_ID \
--scanner-project YOUR_SCANNER_PROJECT \
--dry-run
Manual setup
In the scanner project (enable once):
gcloud services enable \
cloudasset.googleapis.com \
cloudbilling.googleapis.com \
billingbudgets.googleapis.com \
orgpolicy.googleapis.com \
--project=YOUR_SCANNER_PROJECT
In each scanned project:
gcloud services enable \
serviceusage.googleapis.com \
iam.googleapis.com \
compute.googleapis.com \
container.googleapis.com \
run.googleapis.com \
aiplatform.googleapis.com \
apikeys.googleapis.com \
recommender.googleapis.com \
--project=PROJECT_ID
What happens if an API is disabled? The scanner skips that resource type for that project — it does not fail the scan. Use
--verboseto see which APIs were skipped. See docs/apis.md for the full dependency map.
Required IAM Roles
The service account running this tool needs the following read-only roles, assigned at the organization level (for org-wide scans) or project level:
| Role | Purpose |
|---|---|
roles/cloudasset.viewer |
Enumerate all resources and IAM policies efficiently |
roles/iam.securityReviewer |
Read IAM policies across all resources |
roles/compute.viewer |
Read Compute Engine instances, firewall rules, networks |
roles/container.viewer |
Read GKE clusters and node pools |
roles/run.viewer |
Read Cloud Run services and jobs |
roles/serviceusage.serviceUsageViewer |
Determine which APIs are enabled per project |
roles/serviceusage.apiKeysViewer |
List API keys and their restrictions |
roles/aiplatform.viewer |
Read Vertex AI endpoints and model configuration |
roles/billing.viewer |
Verify billing accounts and budget existence |
roles/recommender.viewer |
Read IAM recommender insights |
roles/orgpolicy.policyViewer |
Read Organization Policy constraints |
roles/monitoring.viewer |
(Optional) Verify alerting policies |
See docs/iam-setup.md for step-by-step setup instructions and docs/apis.md for the complete API reference.
Security Checks
Crypto Mining Vector (~40 checks)
| ID | Severity | Description |
|---|---|---|
| CM-001 | HIGH | VM instances with external IP addresses |
| CM-004 | CRITICAL | Firewall allows SSH/RDP from 0.0.0.0/0 |
| CM-009 | MEDIUM | Shielded VM not enabled |
| CM-020 | HIGH | GKE node pools with unbounded autoscaling |
| CM-023 | HIGH | GKE cluster with public endpoint and no authorized networks |
| CM-030 | HIGH | Cloud Run services with public invoker (allUsers) |
| CM-040 | HIGH | SA with compute admin roles granted broadly |
| CM-041 | HIGH | Service accounts with user-managed (exported) keys |
| CM-043 | CRITICAL | IAM binding grants allUsers/allAuthenticatedUsers |
| CM-044 | HIGH | Default Compute SA has Editor/Owner role |
| ... | ... | See docs/checks/crypto_mining.md |
Gemini API Abuse Vector (~25 checks)
| ID | Severity | Description |
|---|---|---|
| GEM-001 | CRITICAL | API key has no API restrictions |
| GEM-002 | CRITICAL | API key has no application restrictions |
| GEM-003 | HIGH | API key explicitly targets Gemini API without app restrictions |
| GEM-020 | HIGH | Vertex AI role granted to broad principal (domain/group) |
| GEM-021 | CRITICAL | Vertex AI role granted to allUsers/allAuthenticatedUsers |
| GEM-030 | HIGH | Vertex AI endpoint accessible without private endpoint |
| GEM-040 | MEDIUM | Vertex AI quotas at default (high) values |
| GEM-051 | HIGH | No budget covering Vertex AI/Gemini spend |
| ... | ... | See docs/checks/gemini_abuse.md |
Common Checks (~6 checks)
| ID | Severity | Description |
|---|---|---|
| CMN-001 | HIGH | Billing account has no budget configured |
| CMN-002 | MEDIUM | Budget exists but has no threshold alert rules |
| CMN-005 | MEDIUM | Key org policy constraints absent |
| CMN-006 | MEDIUM | Cloud Audit Logs (Data Access) disabled |
Report Format
Each finding includes:
- Severity: CRITICAL / HIGH / MEDIUM / LOW
- Priority rank: Global ordering for the remediation plan
- Evidence: Exact resource details that triggered the finding
- Impact: What an attacker can do with this misconfiguration
- Remediation: Step-by-step fix with
gcloudcommands, Terraform reference, and effort estimate
Example finding (JSON):
{
"check_id": "GEM-002",
"title": "API key has no application restrictions",
"severity": "CRITICAL",
"priority_rank": 1,
"resource": {"project_id": "my-project", "resource_id": "..."},
"remediation": {
"summary": "Add HTTP referrer or IP restrictions to the key.",
"effort": "LOW",
"gcloud_commands": ["gcloud services api-keys update KEY_UID --allowed-referrers=..."]
}
}
Configuration
Create a config.yaml to customize behavior:
# See examples/config.example.yaml for full reference
allowlist:
- check_id: CM-001
project_id: my-legacy-project
reason: "External IP required for on-prem VPN — reviewed 2024-01-15"
Contributing
See CONTRIBUTING.md for how to add new checks, collectors, and reporters.
License
Apache 2.0 — see LICENSE.
Disclaimer: This tool is read-only and preventive. It does not guarantee detection of all security issues. Always combine with other security controls and monitoring.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gcp_abuse_scanner-0.1.5.tar.gz.
File metadata
- Download URL: gcp_abuse_scanner-0.1.5.tar.gz
- Upload date:
- Size: 150.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4add28c429bd69d33376e11574a1eba251404ebaac93f1f5922dc55caf8ff26d
|
|
| MD5 |
5689a2bdc201e2c7f0bcd323155bda9a
|
|
| BLAKE2b-256 |
9e39911cd7eea8e68fd49669fa1e26a44a3007ecb9d2b3ab826af681e4e31acb
|
Provenance
The following attestation bundles were made for gcp_abuse_scanner-0.1.5.tar.gz:
Publisher:
release.yml on lmoreno0435/gcp-abuse-scanner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gcp_abuse_scanner-0.1.5.tar.gz -
Subject digest:
4add28c429bd69d33376e11574a1eba251404ebaac93f1f5922dc55caf8ff26d - Sigstore transparency entry: 2192576873
- Sigstore integration time:
-
Permalink:
lmoreno0435/gcp-abuse-scanner@e96599520e860bbacab4709f217afee48780f0f1 -
Branch / Tag:
refs/tags/v0.1.5 - Owner: https://github.com/lmoreno0435
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e96599520e860bbacab4709f217afee48780f0f1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file gcp_abuse_scanner-0.1.5-py3-none-any.whl.
File metadata
- Download URL: gcp_abuse_scanner-0.1.5-py3-none-any.whl
- Upload date:
- Size: 117.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3dc22cf512fa12af6a0de8ec8d3da4cc89f8985cb77940aa9fe08b8e3820fb84
|
|
| MD5 |
cff3287f721f0fa6e3a5384b5bd6124e
|
|
| BLAKE2b-256 |
c1f095b55f6dbe1ef227a28c21ee8e72d0ec4fc357b34a369ff973a9e203286c
|
Provenance
The following attestation bundles were made for gcp_abuse_scanner-0.1.5-py3-none-any.whl:
Publisher:
release.yml on lmoreno0435/gcp-abuse-scanner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gcp_abuse_scanner-0.1.5-py3-none-any.whl -
Subject digest:
3dc22cf512fa12af6a0de8ec8d3da4cc89f8985cb77940aa9fe08b8e3820fb84 - Sigstore transparency entry: 2192576895
- Sigstore integration time:
-
Permalink:
lmoreno0435/gcp-abuse-scanner@e96599520e860bbacab4709f217afee48780f0f1 -
Branch / Tag:
refs/tags/v0.1.5 - Owner: https://github.com/lmoreno0435
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e96599520e860bbacab4709f217afee48780f0f1 -
Trigger Event:
push
-
Statement type: