GuardAPI Logo
GuardAPI
Automated Security Protocol

How to fix Lack of Resources & Rate Limiting
in Phoenix

Executive Summary

Phoenix applications on the BEAM are resilient, but they aren't invincible. Without explicit rate limiting, an attacker can saturate your database pool, exhaust memory with large payloads, or spike CPU cycles by spamming expensive password-hashing algorithms like Argon2 or Bcrypt. To stop DoS and brute-force attacks, you must intercept the request at the Plug level before it hits your business logic.

The Vulnerable Pattern

VULNERABLE CODE
defmodule MyAppWeb.AuthController do
  use MyAppWeb, :controller

def login(conn, %{“user” => user_params}) do # VULNERABLE: No rate limiting present. # An attacker can automate 10,000 requests per second. # This will exhaust the DB connection pool and spike CPU via password hashing. case Accounts.authenticate_user(user_params) do {:ok, user} -> render(conn, “success.json”, user: user) {:error, _} -> conn |> put_status(:unauthorized) |> json(%{error: “Invalid credentials”}) end end end

The Secure Implementation

The vulnerable code allows unbounded access to the 'authenticate_user' function, which is a prime target for resource exhaustion. The secure implementation introduces a custom Plug that leverages the 'Hammer' library. By checking the rate limit against the user's IP address (or session token) before the controller logic is reached, we can return a 429 'Too Many Requests' status. Calling 'halt/1' is essential; it prevents the connection from proceeding to the expensive hashing and database operations, effectively shielding the system resources from the attack.

SECURE CODE
defmodule MyAppWeb.Plugs.RateLimit do
  import Plug.Conn
  import Phoenix.Controller

@doc """ Intercepts requests to check rate limits using Hammer (ETS/Redis backend). Usage: plug MyAppWeb.Plugs.RateLimit when action in [:login] """ def init(opts), do: opts

def call(conn, _opts) do # Define a unique key (IP or User ID) key = “login:#{conn.remote_ip}”

# Limit: 5 attempts per 60 seconds
case Hammer.check_rate(key, 60_000, 5) do
  {:allow, _count} -> 
    conn
  {:deny, _limit} ->
    conn
    |> put_status(:too_many_requests)
    |> json(%{error: "Rate limit exceeded. Try again in a minute."})
    |> halt() # CRITICAL: Stop the pipeline here
end

end end

System Alert • ID: 9904
Target: Phoenix API
Potential Vulnerability

Your Phoenix API might be exposed to Lack of Resources & Rate Limiting

74% of Phoenix 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.