Pii Leakage in Echo Go with Firestore
Pii Leakage in Echo Go with Firestore — how this specific combination creates or exposes the vulnerability
When building HTTP services in Go with the Echo framework, integrating Google Cloud Firestore can inadvertently expose personally identifiable information (PII) if data access rules and application logic are not tightly aligned. Firestore documents often contain fields such as email, phone number, government ID, or location data. If an endpoint retrieves a document and returns the entire object without filtering, those PII fields are exposed in the HTTP response.
In an Echo-based service, a typical handler might call Firestore to fetch a user profile and write it directly to the response body. Because Firestore returns the full document as a map or struct, any PII stored in that document is included. For example, a handler that uses doc.Data() and returns it as JSON will propagate all fields, including sensitive ones, unless explicit exclusion logic is applied.
The risk is compounded when Firestore security rules are misconfigured, allowing broader read access than intended, or when the application trusts client-supplied identifiers (such as user IDs from URLs or tokens) without additional authorization checks. An attacker who can influence the document ID or path may be able to enumerate or retrieve documents that belong to other users, leading to horizontal IDOR-like exposure of PII. Even with properly configured Firestore rules, application-layer handling in Echo must ensure that only necessary fields are serialized and sent to the client.
Consider a scenario where an endpoint returns a user profile including fields like email, phone, and address. Without field-level filtering, the response becomes a direct channel for PII leakage. MiddleBrick’s LLM/AI Security checks and its comprehensive API scans can detect such exposure patterns by correlating Firestore read patterns with response payloads, highlighting endpoints that return sensitive data without appropriate controls.
Firestore-Specific Remediation in Echo Go — concrete code fixes
To prevent PII leakage when using Firestore in Echo, apply defense-in-depth: restrict Firestore access, minimize data exposure in handlers, and enforce field-level filtering before serialization.
1. Use Firestore views and selective field reads
Instead of retrieving entire documents, request only the fields you need. In Go, you can use DocumentsRef.Select to limit the returned data.
import (
"context"
"github.com/labstack/echo/v4"
"cloud.google.com/go/firestore"
"google.golang.org/api/iterator"
)
func GetPublicProfile(c echo.Context) error {
ctx := c.Request().Context()
client, err := firestore.NewClient(ctx, "your-project-id")
if err != nil {
return echo.NewHTTPError(500, "failed to create client")
}
defer client.Close()
userID := c.Param("userID")
docRef := client.Collection("users").Doc(userID)
iter := docRef.Select("public_name", "public_bio").Documents(ctx)
defer iter.Stop()
doc, err := iter.Next()
if err == iterator.Done {
return echo.NewHTTPError(404, "not found")
}
if err != nil {
return echo.NewHTTPError(500, "failed to read document")
}
// Return only selected, non-PII fields
return c.JSON(200, doc.Data())
}
2. Explicitly exclude PII fields in application logic
When full documents are necessary, remove PII keys before serialization. Define a helper to scrub sensitive fields.
func scrubPII(data map[string]interface{}) map[string]interface{} {
safe := make(map[string]interface{})
for k, v := range data {
switch k {
case "email", "phone", "ssn", "address", "ip_address":
// omit PII
continue
default:
safe[k] = v
}
}
return safe
}
func GetUserProfile(c echo.Context) error {
ctx := c.Request().Context()
client, err := firestore.NewClient(ctx, "your-project-id")
if err != nil {
return echo.NewHTTPError(500, "failed to create client")
}
defer client.Close()
userID := c.Param("userID")
doc, err := client.Collection("users").Doc(userID).Get(ctx)
if err != nil {
return echo.NewHTTPError(404, "not found")
}
// Scrub before returning
safeData := scrubPII(doc.Data())
return c.JSON(200, safeData)
}
3. Validate and authorize identifiers
Ensure that the user requesting a resource is authorized to access it. Do not rely solely on Firestore security rules for application-level authorization within Echo. Use identity information from the request (e.g., JWT subject) to verify ownership.
func GetOwnProfile(c echo.Context) error {
ctx := c.Request().Context()
client, err := firestore.NewClient(ctx, "your-project-id")
if err != nil {
return echo.NewHTTPError(500, "failed to create client")
}
defer client.Close()
claims := c.Get("claims").(*CustomClaims)
userID := claims.Subject
doc, err := client.Collection("users").Doc(userID).Get(ctx)
if err != nil {
return echo.NewHTTPError(404, "not found")
}
return c.JSON(200, doc.Data())
}
4. Leverage Firestore security rules as a secondary control
While rules are not a substitute for application-layer filtering, use them to enforce read access constraints. Configure rules to allow access only to specific fields or to restrict reads to authenticated users.
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read: if request.auth != null && request.auth.uid == userId;
}
}
}
By combining selective reads, explicit scrubbing, proper authorization checks in Echo handlers, and correctly configured Firestore rules, you significantly reduce the risk of PII leakage in your API.
Related CWEs: dataExposure
| CWE ID | Name | Severity |
|---|---|---|
| CWE-200 | Exposure of Sensitive Information | HIGH |
| CWE-209 | Error Information Disclosure | MEDIUM |
| CWE-213 | Exposure of Sensitive Information Due to Incompatible Policies | HIGH |
| CWE-215 | Insertion of Sensitive Information Into Debugging Code | MEDIUM |
| CWE-312 | Cleartext Storage of Sensitive Information | HIGH |
| CWE-359 | Exposure of Private Personal Information (PII) | HIGH |
| CWE-522 | Insufficiently Protected Credentials | CRITICAL |
| CWE-532 | Insertion of Sensitive Information into Log File | MEDIUM |
| CWE-538 | Insertion of Sensitive Information into Externally-Accessible File | HIGH |
| CWE-540 | Inclusion of Sensitive Information in Source Code | HIGH |