Building a Firebase Security Scanner: Lessons from a 100-Line Go Tool
Hook
A single misconfigured Firebase database exposed 70 million user records in 2019. The security rule that would have prevented it? One line of JSON.
Context
Firebase Realtime Database revolutionized backend development by letting frontend developers build apps without managing servers. You define JSON data structures, set security rules, and Firebase handles the rest. But this simplicity creates a dangerous trap: the default configuration during development allows public read/write access. Developers prototype with open permissions, then forget to lock them down before shipping. The firebaseio-checker-go tool exists because this specific misconfiguration is alarmingly common and trivially exploitable.
Unlike traditional databases hidden behind application servers, Firebase exposes a REST API at predictable URLs following the pattern https://[project-id].firebaseio.com/.json. Append .json to any Firebase database URL, make an HTTP GET request, and you’ll either get the entire database or a permission denied error. This makes reconnaissance simple: no SQL injection, no authentication bypass, just a basic HTTP request. Random-robbie’s tool automates this check across lists of potential targets, making it valuable for security researchers, penetration testers, and organizations auditing their own Firebase footprint.
Technical Insight
The architecture demonstrates Go’s strength for network-bound I/O operations. At its core, the scanner reads URLs from a file, spawns goroutines to check each one concurrently, and uses a sized wait group to prevent overwhelming the system or triggering aggressive rate limiting. The key architectural decision is the remixlabs/sizedwaitgroup package, which provides semaphore-like behavior with a cleaner API than raw channels.
Here’s the essential concurrency pattern:
swg := sizedwaitgroup.New(25) // Max 25 concurrent requests
for scanner.Scan() {
url := strings.TrimSpace(scanner.Text())
if url == "" {
continue
}
swg.Add()
go func(firebaseURL string) {
defer swg.Done()
checkFirebase(firebaseURL)
}(url)
}
swg.Wait() // Block until all goroutines complete
This pattern elegantly solves the “too many goroutines” problem that plagues naive concurrent scanners. Without the sized wait group, scanning 10,000 URLs would spawn 10,000 simultaneous HTTP requests, exhausting file descriptors and triggering defensive systems. The semaphore limits concurrency to 25, keeping resource usage predictable while maintaining parallelism benefits.
The actual Firebase checking logic is refreshingly simple. The tool constructs the REST API endpoint by ensuring the URL ends with .json, then makes a GET request with a 10-second timeout:
client := &http.Client{
Timeout: 10 * time.Second,
}
targetURL := firebaseURL
if !strings.HasSuffix(targetURL, ".json") {
targetURL += "/.json"
}
resp, err := client.Get(targetURL)
if err != nil {
return // Network error, move on
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
// Database is readable - download everything
body, _ := ioutil.ReadAll(resp.Body)
saveToFile(firebaseURL, body)
}
The decision to download the entire database on a successful hit is both the tool’s strength and weakness. Firebase’s REST API returns the complete JSON structure in a single response, making data exfiltration trivial for attackers but also convenient for security audits. The tool saves each exposed database to a timestamped JSON file, preserving evidence for reporting.
What makes this implementation particularly Go-idiomatic is the error handling philosophy. Rather than complex error propagation, the tool uses early returns and deferred cleanup. If a request fails due to network issues, timeouts, or permission denial, the goroutine simply exits. This “fail fast, continue scanning” approach prioritizes throughput over perfect error reporting—appropriate for a security scanner where the goal is finding vulnerable targets, not diagnosing why specific URLs are unreachable.
The HTTP timeout deserves special attention. Ten seconds is generous for modern cloud infrastructure, but Firebase’s globally distributed architecture occasionally has slow cold-start responses. A shorter timeout would miss legitimate vulnerable databases; a longer one would let hung connections consume goroutine slots. This calibration reflects real-world testing experience.
Gotcha
The tool’s narrowness is both its strength and fatal flaw depending on your use case. It exclusively checks read permissions on Firebase Realtime Database, ignoring write access, Firestore, Cloud Storage, and authentication configurations. A database might reject unauthenticated reads but accept unauthenticated writes—an arguably more dangerous misconfiguration that this tool would miss entirely. There’s no attempt to enumerate Firebase projects, discover database URLs through reconnaissance, or check for partial path accessibility where the root is locked but specific child nodes are exposed.
The lack of rate limiting or request spacing makes the tool highly detectable. Scanning thousands of Firebase URLs in rapid succession creates obvious traffic patterns that security teams monitor for. Google’s infrastructure will likely throttle or temporarily block IP addresses performing these scans at scale, and responsible security research requires coordination with target organizations. The tool also offers no proxy support, user-agent randomization, or jitter—features expected in modern reconnaissance tools. For bug bounty hunters or penetration testers working under time pressure against monitored infrastructure, these omissions significantly limit operational effectiveness.
Verdict
Use if: You’re conducting authorized security assessments of Firebase implementations and need quick triage of read-permission misconfigurations across many potential targets. This tool excels at answering “which of these 500 suspected Firebase URLs are publicly readable?” during the reconnaissance phase. It’s also valuable for organizations auditing their own Firebase footprint after acquisitions or during security compliance reviews. The simplicity is an advantage when you need transparent, auditable tooling without complex dependencies. Skip if: You need comprehensive Firebase security testing beyond read-permission checks, require stealth and rate-limiting for operational security, or want automated discovery rather than just verification of known URLs. For serious Firebase security work, you’ll need this as one component in a larger toolkit alongside Firestore checkers, authentication testing, and proper project enumeration tools. The code is better viewed as a reference implementation for building custom scanners than a complete security solution.