GuardAPI Logo
GuardAPI
Automated Security Protocol

How to fix Insufficient Logging & Monitoring
in Plug

Executive Summary

Insufficient logging in Elixir/Plug stacks creates a massive blind spot for incident response. If your pipeline doesn't explicitly track authentication failures, authorization bypass attempts, and high-impact state changes, you are effectively flying blind while an attacker maps your attack surface. Default Plug logging is for debugging, not security auditing.

The Vulnerable Pattern

VULNERABLE CODE
defmodule MyApp.Router do
  use Plug.Router
  plug :match
  plug :dispatch

post “/api/v1/login” do # VULNERABLE: Fails silently. No audit trail for failed attempts. case MyApp.Auth.verify(conn.params[“user”], conn.params[“pass”]) do {:ok, user} -> send_resp(conn, 200, “OK”) {:error, _reason} -> send_resp(conn, 401, “Unauthorized”) end end end

The Secure Implementation

The secure implementation introduces structured security logging. By using Logger.metadata/1, we ensure all subsequent logs in the process lifecycle are tagged with the user's identity. The custom log_event/3 helper captures critical forensic data: the remote IP (converted from tuple to string), the request path, and the specific failure reason. This allows security teams to set up automated alerts for credential stuffing (high volume of LOGIN_FAILURE) and provides a clear audit trail for post-compromise analysis.

SECURE CODE
defmodule MyApp.SecurityLogger do
  require Logger

def log_event(conn, event_type, metadata \ []) do # Structured logging for SIEM ingestion Logger.warning(“Security Event: #{event_type}”, Keyword.merge([ path: conn.request_path, remote_ip: :inet.ntoa(conn.remote_ip), user_agent: get_req_header(conn, “user-agent”), security: true ], metadata) ) end end

defmodule MyApp.Router do use Plug.Router import MyApp.SecurityLogger

post “/api/v1/login” do case MyApp.Auth.verify(conn.params[“user”], conn.params[“pass”]) do {:ok, user} -> Logger.metadata(user_id: user.id) send_resp(conn, 200, “OK”) {:error, reason} -> # SECURE: Explicitly log the failure with context for brute-force detection log_event(conn, “LOGIN_FAILURE”, [user: conn.params[“user”], reason: reason]) send_resp(conn, 401, “Unauthorized”) end end end

System Alert • ID: 6286
Target: Plug API
Potential Vulnerability

Your Plug API might be exposed to Insufficient Logging & Monitoring

74% of Plug apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.