Insufficient Logging in Fiber
How Insufficient Logging Manifests in Fiber
Insufficient logging in Fiber applications creates blind spots that attackers exploit to maintain persistent access and evade detection. The problem manifests in several Fiber-specific ways that developers often overlook.
Fiber's middleware-based architecture means logging gaps can occur at critical request boundaries. When developers implement custom authentication middleware without comprehensive logging, successful and failed authentication attempts disappear. Consider this common pattern:
app.Use(func(c *fiber.Ctx) error {
// Custom auth logic
token := c.Get("Authorization")
if token == "" {
return c.Status(fiber.StatusUnauthorized).SendString("Missing token")
}
// No logging of auth failures
return c.Next()
})
This creates perfect conditions for credential stuffing attacks. Attackers can hammer authentication endpoints without leaving forensic evidence. The absence of failed login logging means security teams cannot detect brute force attempts or identify compromised accounts.
API endpoint abuse represents another critical manifestation. Fiber's lightweight routing makes it easy to expose endpoints without proper access logging. A typical vulnerable pattern:
app.Post("/api/user", func(c *fiber.Ctx) error {
// Create user without logging who created it
return c.JSON(fiber.Map{"status": "created"})
})
Without logging user creation events with context (IP address, user agent, request ID), organizations cannot investigate data breaches or meet compliance requirements. The GDPR's Article 30 specifically requires processing activity logs that include "the identification of the data subject and of the recipients."
Missing request ID correlation across distributed systems compounds the problem. Fiber applications often integrate with databases, external APIs, and microservices. Without consistent request ID propagation:
app.Use(func(c *fiber.Ctx) error {
// Missing request ID generation
return c.Next()
})
Security incidents become impossible to reconstruct. When a data breach occurs, investigators cannot trace the malicious request through the entire call chain.
Silent error handling creates another vulnerability class. Fiber's error handling can swallow exceptions without logging:
app.Use(func(c *fiber.Ctx) error {
defer func() {
if r := recover(); r != nil {
// Error swallowed without logging
return c.Status(fiber.StatusInternalServerError).SendString("Error")
}
}()
return c.Next()
})
This pattern allows attackers to trigger errors that reveal system information through timing or side channels while leaving no audit trail.
Fiber-Specific Detection
Detecting insufficient logging in Fiber applications requires both static analysis and runtime scanning. middleBrick's black-box scanning approach is particularly effective for identifying logging gaps that static analysis might miss.
middleBrick's authentication testing reveals missing login attempt logging by attempting to authenticate with invalid credentials and analyzing the responses. A Fiber application with insufficient logging typically shows:
- No variation in response times between valid and invalid credentials (indicating no backend logging)
- Generic error messages that don't distinguish between "invalid password" and "account locked"
- Consistent response codes regardless of authentication failure type
The scanner's BOLA (Broken Object Level Authorization) testing exposes missing authorization logging. middleBrick attempts to access resources across user boundaries and analyzes whether the application provides different responses that could indicate successful or failed authorization checks without proper logging.
For real-time detection, implement request logging middleware that captures Fiber's request lifecycle:
app.Use(func(c *fiber.Ctx) error {
start := time.Now()
// Generate unique request ID
reqID := uuid.New().String()
c.Locals("requestID", reqID)
c.Response().Header.Set("X-Request-ID", reqID)
// Log request start
log.WithFields(logrus.Fields{
"request_id": reqID,
"method": c.Method(),
"path": c.Path(),
"remote_addr": c.IP(),
"user_agent": c.Get("User-Agent"),
}).Info("request started")
err := c.Next()
// Calculate duration
duration := time.Since(start)
// Log request completion
log.WithFields(logrus.Fields{
"request_id": reqID,
"status": c.Response().StatusCode(),
"duration": duration.Milliseconds(),
"error": err != nil,
}).Info("request completed")
return err
})
This middleware provides the baseline observability that middleBrick expects when scanning for security issues. Applications without this level of logging typically receive lower security scores.
middleBrick's API specification analysis cross-references your OpenAPI/Swagger definitions with actual runtime behavior. Missing logging for documented endpoints triggers findings, as the spec implies certain operations should be auditable.
The scanner's rate limiting detection also reveals insufficient logging. Applications without proper request volume logging cannot implement effective rate limiting, making them vulnerable to DoS attacks and credential stuffing.
Fiber-Specific Remediation
Remediating insufficient logging in Fiber applications requires implementing comprehensive audit trails that capture security-relevant events. Start with structured logging using a consistent format:
package logging
import (
"time"
"github.com/gofiber/fiber"
"github.com/sirupsen/logrus"
)
func AuditLogger() fiber.Handler {
return func(c *fiber.Ctx) error {
reqID := c.Locals("requestID").(string)
// Authentication events
if c.Method() == "POST" && strings.Contains(c.Path(), "auth") {
user := c.FormValue("username")
success := c.Response().StatusCode() == fiber.StatusNoContent || c.Response().StatusCode() == fiber.StatusOK
logrus.WithFields(logrus.Fields{
"request_id": reqID,
"user": user,
"success": success,
"remote_addr": c.IP(),
"user_agent": c.Get("User-Agent"),
"timestamp": time.Now().UTC(),
}).Infof("authentication %s", map[bool]string{true: "success", false: "failure"}[success])
}
// Authorization events
if c.Response().StatusCode() == fiber.StatusForbidden || c.Response().StatusCode() == fiber.StatusUnauthorized {
logrus.WithFields(logrus.Fields{
"request_id": reqID,
"path": c.Path(),
"method": c.Method(),
"remote_addr": c.IP(),
"user_agent": c.Get("User-Agent"),
"timestamp": time.Now().UTC(),
}).Warn("authorization failure")
}
// Data modification events
if c.Method() == "POST" || c.Method() == "PUT" || c.Method() == "DELETE" {
logrus.WithFields(logrus.Fields{
"request_id": reqID,
"path": c.Path(),
"method": c.Method(),
"remote_addr": c.IP(),
"user_agent": c.Get("User-Agent"),
"timestamp": time.Now().UTC(),
}).Infof("%s operation performed", strings.ToUpper(c.Method()))
}
return c.Next()
}
}
Integrate this middleware early in your application stack:
app.Use(RequestIDMiddleware())
app.Use(AuditLogger())
app.Use(RecoveryMiddleware())
For structured logging output compatible with security information and event management (SIEM) systems:
import (
"time"
"github.com/gofiber/fiber"
"github.com/sirupsen/logrus"
"encoding/json"
)
type AuditEvent struct {
Timestamp time.Time `json:"timestamp"`
RequestID string `json:"request_id"`
UserID string `json:"user_id,omitempty"`
Action string `json:"action"`
Resource string `json:"resource"`
Method string `json:"method"`
Status int `json:"status"`
IPAddress string `json:"ip_address"`
UserAgent string `json:"user_agent"`
Success bool `json:"success"`
Details string `json:"details,omitempty"`
}
func StructuredAuditLogger() fiber.Handler {
return func(c *fiber.Ctx) error {
// Implementation that marshals AuditEvent to JSON
return c.Next()
}
}
middleBrick's continuous monitoring in Pro tier helps verify that logging implementations meet security standards. The scanner checks that audit logs capture:
- All authentication attempts with success/failure status
- Authorization failures with attempted resource paths
- Data modification operations with user context
- Application errors with stack traces (in non-production environments)
- Rate limiting events and blocked requests
Integrate logging with your CI/CD pipeline using middleBrick's GitHub Action. Configure it to fail builds if new endpoints lack proper audit logging:
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run middleBrick Scan
uses: middlebrick/middlebrick-action@v1
with:
url: http://localhost:3000
fail-on-severity: high
token: ${{ secrets.MIDDLEBRICK_TOKEN }}
# Fails if logging gaps are detected