Pii Leakage in Buffalo
How PII Leakage Manifests in Buffalo
PII leakage in Buffalo applications often occurs through unintended data exposure in API responses, error messages, and logging. Buffalo's default JSON rendering and error handling can inadvertently expose sensitive user information if not properly configured.
One common pattern involves Buffalo's automatic JSON serialization of model structs. When returning database models directly in handlers, all struct fields—including sensitive ones—are serialized unless explicitly excluded. For example:
type User struct {
ID uuid.UUID `json:"id"`
Email string `json:"email"`
Password string `json:"password"`
SSN string `json:"ssn"`
CreatedAt time.Time `json:"created_at"`
}If this struct is returned directly from a handler, the password and SSN fields will be exposed in API responses. Buffalo's default behavior is to serialize all exported fields, making this a frequent source of PII leakage.
Another manifestation occurs in Buffalo's error handling. When database operations fail, Buffalo's default error responses often include raw SQL queries, database error messages, and even partial data from failed operations. This can expose table names, column structures, and in some cases, data fragments:
// Vulnerable: exposes database structure and partial data
func GetUser(c buffalo.Context) error {
id := c.Param("id")
var user User
err := DB.Find(&user, id)
if err != nil {
return c.Error(404, err) // Exposes raw database error
}
return c.Render(200, r.JSON(user))
}Buffalo's logging middleware can also inadvertently log PII. By default, request logging includes query parameters, headers, and response bodies. If authentication tokens, personal identifiers, or other sensitive data appear in these contexts, they get logged in plaintext:
// Vulnerable: logs sensitive data in request parameters
func UpdateProfile(c buffalo.Context) error {
var input struct {
Email string `json:"email"`
SSN string `json:"ssn"`
}
if err := c.Bind(&input); err != nil {
return err
}
// SSN and email now appear in request logs
return c.Render(200, r.JSON(input))
}Buffalo-Specific Detection
Detecting PII leakage in Buffalo applications requires examining both the codebase and runtime behavior. Start by auditing your model structs and API handlers for exposed sensitive fields.
For struct-level PII exposure, use Buffalo's struct tag system to control JSON serialization. Fields containing PII should be tagged with json:"-" or json:"-,omitempty" to prevent serialization:
type User struct {
ID uuid.UUID `json:"id"`
Email string `json:"email"`
Password string `json:"-"` // Excluded from JSON
SSN string `json:"-,omitempty"` // Excluded if empty
CreatedAt time.Time `json:"created_at"`
}For runtime detection, middleBrick's black-box scanning can identify PII exposure in API responses. The scanner tests endpoints with various inputs and analyzes responses for patterns matching PII data types. This includes detecting:
- Exposed email addresses, phone numbers, and physical addresses
- Social Security numbers and government IDs
- Authentication tokens and session identifiers
- Credit card numbers and financial data
- Medical record identifiers
middleBrick's scanning specifically tests Buffalo applications by sending requests to your API endpoints and analyzing the responses for these patterns. The scanner can identify when sensitive data is being returned in error responses, validation messages, or successful API responses.
For development-time detection, Buffalo's Pop integration provides query logging that can be configured to redact sensitive data. Add a logging hook to your Pop connection:
DB.AddDBHook(&pop.Hook{
BeforeCreate: func(ctx context.Context, model pop.Model) error {
if user, ok := model.(*models.User); ok {
user.Password = "[REDACTED]"
}
return nil
},
})Buffalo-Specific Remediation
Remediating PII leakage in Buffalo requires a multi-layered approach. First, implement proper data exposure controls at the model level using struct tags and custom marshaling.
For models that need different representations in different contexts, create separate DTO (Data Transfer Object) structs:
type User struct {
ID uuid.UUID `json:"id"`
Email string `json:"email"`
Password string `json:"-"`
SSN string `json:"-"`
CreatedAt time.Time `json:"created_at"`
}
type UserResponse struct {
ID uuid.UUID `json:"id"`
Email string `json:"email"`
CreatedAt time.Time `json:"created_at"`
}Then use the appropriate struct in your handlers:
func ListUsers(c buffalo.Context) error {
var users []User
if err := DB.All(&users); err != nil {
return c.Error(500, err)
}
var responses []UserResponse
for _, u := range users {
responses = append(responses, UserResponse{
ID: u.ID,
Email: u.Email,
CreatedAt: u.CreatedAt,
})
}
return c.Render(200, r.JSON(responses))
}For error handling, implement custom error types that redact sensitive information:
type apiError struct {
Message string `json:"message"`
Code int `json:"code"`
}
func (e *apiError) Error() string {
return e.Message
}
func (e *apiError) Response() buffalo.Response {
return c.Render(400, r.JSON(e))
}
// Usage in handlers
func UpdateUser(c buffalo.Context) error {
var input struct {
Email string `json:"email"`
SSN string `json:"ssn"`
}
if err := c.Bind(&input); err != nil {
return &apiError{"Invalid input", 400}
}
// Process update...
return c.Render(200, r.JSON(struct{ Success bool }{true}))
}Configure Buffalo's logging to redact sensitive information. In your main.go, customize the logger:
import "github.com/sirupsen/logrus"
func main() {
app := buffalo.New(buffalo.Options{
Env: envy.Get("GO_ENV", "development"),
SessionName: "_your_app_session",
})
// Custom logger that redacts PII
logger := logrus.New()
logger.Formatter = &logrus.JSONFormatter{}
// Add middleware with custom logger
app.Use(func(next buffalo.Handler) buffalo.Handler {
return func(c buffalo.Context) error {
// Redact sensitive headers
c.Logger().Infof("Request from %s", c.Request().RemoteAddr)
return next(c)
}
})
}For comprehensive protection, integrate middleBrick's CLI into your development workflow. Install it via npm and scan your Buffalo application:
npm install -g middlebrick
middlebrick scan https://your-buffalo-app.com/api
The CLI provides JSON output that can be integrated into your CI/CD pipeline, ensuring PII leakage is caught before deployment. For GitHub Actions integration:
- name: Scan for PII leakage
uses: middlebrick/middlebrick-action@v1
with:
url: https://staging.your-buffalo-app.com
fail-on-severity: high
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 |