Go-Hunter: Multi-Cloud Attack Surface Management

Go-Hunter scans AWS, GCP, Azure, Cloudflare, and DigitalOcean for exposed infrastructure, misconfigurations, and configuration drift. It finds public S3 buckets, open ports, misconfigured services, and unauthorized changes across cloud providers from a single interface.

Dashboard

What it finds

The scanner covers attack surface systematically. Asset discovery enumerates all resources by calling provider APIs on schedule or on-demand. Port scanning uses TCP connect probes on common ports to identify exposed services, with banner grabbing for service version detection. S3 bucket checks test for public read and write access, catching the misconfiguration that leads to data leaks. Drift detection hashes asset state with SHA256 and alerts when configurations change unexpectedly, which helps catch unauthorized modifications or policy violations.

At peak throughput it processes over 1,000 assets per minute across providers.

Security design

All cloud credentials are encrypted at rest using the age library (X25519 + ChaCha20-Poly1305) before storage in PostgreSQL. Decryption happens in-memory only when workers need to execute scans. Workers decrypt credentials in isolated processes, use them for scanning, and discard them from memory. The API server never touches plaintext credentials. This compartmentalization limits the blast radius if a component is compromised.

Multi-tenant isolation is enforced at the database query layer. Every query includes organization ID filtering to prevent cross-tenant data leakage. I tested this isolation extensively because multi-tenant bugs are catastrophic. Row-level filtering with indexed foreign keys keeps queries fast even as data grows.

Audit logging captures credential access, scan execution, and configuration changes.

Multi-cloud integration

The integration challenge goes beyond API wrappers. Each provider has different authentication models, rate limits, and resource hierarchies. AWS uses IAM credentials with complex permission policies. GCP requires service accounts with specific role bindings. Azure needs app registrations. Cloudflare and DigitalOcean use API tokens. Go-Hunter normalizes these differences behind a single scanning interface.

Rate limiting proved unexpectedly complex. AWS throttles API calls aggressively, especially for discovery operations that enumerate resources across multiple regions. The solution uses per-provider rate limiters with exponential backoff. Scans take longer but don’t trigger throttling errors that would leave blind spots in asset inventory. Patient, consistent scanning beats aggressive parallelization for reliability.

Architecture

A stateless API server built with Chi handles HTTP requests and serves the dashboard. All state lives in PostgreSQL. Background workers using Asynq pull scan jobs from a Redis queue, execute cloud API calls, and write discovered assets back to the database. Adding capacity means spinning up more worker processes. No coordination required.

The data model is multi-tenant from the start. Organizations own Users and Credentials. Scans produce Assets. Assets accumulate Findings over time.

Performance optimization focused on database bottlenecks. Initial discovery scans inserted assets individually. Switching to batch inserts and adding composite indexes on organization ID and asset type improved throughput from roughly 50 assets per minute to over 1,000. The worker pool pattern with goroutines and context-aware cancellation keeps scanning responsive even when processing large cloud environments.

Tradeoffs and limitations

The HTMX dashboard works well for basic operations but shows its limits with complex filtering and data visualization. Building it was fast, which mattered for shipping quickly. A proper frontend framework would enable richer interactions for power users.

The scanner finds open ports and misconfigured storage, but it does not cross-reference discovered services with CVE databases. Connecting asset inventory to known vulnerabilities would make findings immediately actionable. That is the next iteration.


View on GitHub