HIGH pii leakageginfirestore

Pii Leakage in Gin with Firestore

Pii Leakage in Gin with Firestore — how this specific combination creates or exposes the vulnerability

When building a REST API with the Gin framework and persisting data in Google Cloud Firestore, PII leakage commonly arises from mismatched data modeling, broad query permissions, and unchecked reflection or JSON serialization behavior. Firestore’s document-level permissions and flexible schema can inadvertently expose sensitive fields if rules and application logic do not enforce least-privilege access at both the database and API layers.

In Gin, developers often unmarshal query parameters or request JSON directly into structs using c.ShouldBindJSON. If the struct embeds or exposes fields such as Email, PhoneNumber, or government IDs without explicit omission rules, those fields may be serialized back in HTTP responses, logged, or cached. Firestore documents that contain the same fields can amplify this risk: a single document read that returns a user profile may surface sensitive PII to an endpoint that should only return a subset of data, such as display name and public avatar URL.

Another common pattern is using Firestore client libraries with overly permissive authentication, such as default service account credentials in server-side code that lack tight rules. If an endpoint queries a collection like users/{userID} and returns the full document without field-level filtering, PII such as email, address, or internal identifiers can be exposed. MiddleBrick’s unauthenticated scan can detect endpoints that return sensitive fields without requiring authentication, highlighting cases where Firestore data is directly surfaced by Gin handlers.

Reflection-based binding in Gin can also contribute to leakage. For example, binding to map[string]interface{} or using c.Request.Body without schema validation may allow clients to request fields that the developer did not intend to expose. When those keys match Firestore document fields, sensitive data can be returned inadvertently. MiddleBrick’s Property Authorization and Data Exposure checks are designed to surface such findings, including mappings to OWASP API Top 10 and compliance frameworks like GDPR and SOC2.

Additionally, Firestore’s subcollections and array-merge behaviors can create hidden pathways for PII exposure when combined with broad query patterns in Gin. A handler that aggregates data from multiple documents might concatenate user metadata, payment tokens, or internal IDs into a response that appears safe but contains sensitive elements. Continuous monitoring in the Pro plan helps detect regressions in these patterns by scanning on a configurable schedule and alerting when new PII-bearing fields appear in API outputs.

Firestore-Specific Remediation in Gin — concrete code fixes

To mitigate PII leakage in Gin applications using Firestore, enforce strict field selection, structured binding, and defensive copying. Always define explicit structs that omit sensitive fields for public endpoints, and use Firestore’s projection queries to retrieve only the necessary fields.

1. Use selective Firestore field retrieval

Instead of retrieving entire documents, specify the fields you need. This reduces the attack surface and prevents accidental exposure of PII stored in the same document.

import (
    "context"
    "firebase.google.com/go/v4"
    "cloud.google.com/go/firestore"
    "google.golang.org/api/iterator"
)

func getUserPublicProfile(client *firestore.Client, userID string) (map[string]interface{}, error) {
    ctx := context.Background()
    iter := client.Collection("users").Doc(userID).Select("displayName", "avatarUrl").Documents(ctx)
    doc, err := iter.Next()
    if err == iterator.Done {
        return nil, nil
    }
    if err != nil {
        return nil, err
    }
    return doc.Data(), nil
}

2. Define separate request/response structs with JSON omitempty

Create distinct structures for input binding and output serialization. Use json:"email,omitempty" to ensure sensitive fields are excluded unless explicitly required and authorized.

type UserPublicResponse struct {
    DisplayName string `json:"displayName"`
    AvatarURL   string `json:"avatarUrl"`
}

func GetPublicProfile(c *gin.Context) {
    userID := c.Param("userID")
    profile, err := getUserPublicProfile(c.Request.Context(), userID)
    if err != nil {
        c.AbortWithStatusJSON(500, gin.H{"error": "unable to load profile"})
        return
    }
    resp := UserPublicResponse{
        DisplayName: profile["displayName"].(string),
        AvatarURL:   profile["avatarUrl"].(string),
    }
    c.JSON(200, resp)
}

3. Validate and restrict query parameters in Gin

Avoid binding raw query parameters to Firestore field names. Normalize inputs and allowlist only safe fields for projection.

var query struct {
    Fields []string `json:"fields" binding:"required"`
}
if c.ShouldBindJSON(&query) != nil {
    c.AbortWithStatusJSON(400, gin.H{"error": "invalid request"})
    return
}
allowed := map[string]bool{"displayName": true, "avatarUrl": true}
var selected []string
for _, f := range query.Fields {
    if allowed[f] {
        selected = append(selected, f)
    }
}
// Use selected to build a Select query as shown above

4. Enforce Firestore security rules to complement application logic

Even when Gin filters fields, secure Firestore rules to restrict read access to sensitive paths. Rules should align with the principle of least privilege, allowing reads only for permitted fields and users.

Example rule concept (not executable in Gin but critical for defense in depth):

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId} {
      allow read: if request.auth != null && request.auth.uid == userId
        && request.resource.data.keys().hasAll(['displayName', 'avatarUrl']);
    }
  }
}

5. Audit and monitor with middleware

Add Gin middleware to log response fields and detect potential PII exposure in real time. Combine this with MiddleBrick’s Data Exposure and Property Authorization checks to continuously validate that only intended fields are returned.

func AuditResponse(c *gin.Context) {
    c.Next()
    // Inspect response keys and compare against allowlist
    // Trigger alerts or metrics when unexpected fields appear
}

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

How does middleBrick detect PII leakage in Gin endpoints that use Firestore?
middleBrick runs unauthenticated scans that inspect HTTP responses for the presence of sensitive fields such as email, phone, or ID values. By correlating Firestore document structure with Gin handler outputs, it can identify endpoints that return PII without explicit field selection or authorization checks.
Can the Pro plan help prevent PII leakage in CI/CD for Gin and Firestore services?
Yes. With continuous monitoring and configurable thresholds, the Pro plan scans APIs on a schedule and integrates with GitHub Actions to fail builds when new PII-bearing fields appear in responses, helping you catch regressions before deployment.