Files
Claper/lib/claper_web/plugs/rate_limit_plug.ex
Alexandre Lion 8f46837900 Fix critical security vulnerabilities (#211)
* Fix critical security vulnerabilities

Address 5 critical findings from security audit:
- Sanitize custom embed HTML to prevent stored XSS (strip all non-iframe content)
- Escape URLs in format_body/1 to prevent reflected XSS via post messages
- Add authorization check to form export endpoint (IDOR fix)
- Replace String.to_atom/1 on user input with explicit whitelists (8 locations)
- Add IP-based rate limiting on authentication endpoints via Hammer

* Start rate limiter before endpoint in supervision tree

* Update CHANGELOG
2026-02-09 19:18:14 +01:00

35 lines
924 B
Elixir

defmodule ClaperWeb.Plugs.RateLimitPlug do
@moduledoc """
Plug for rate limiting requests based on client IP address.
## Usage
plug ClaperWeb.Plugs.RateLimitPlug, max_requests: 10, interval_ms: 60_000, prefix: "login"
"""
import Plug.Conn
def init(opts) do
%{
max_requests: Keyword.get(opts, :max_requests, 10),
interval_ms: Keyword.get(opts, :interval_ms, 60_000),
prefix: Keyword.get(opts, :prefix, "default")
}
end
def call(conn, %{max_requests: max_requests, interval_ms: interval_ms, prefix: prefix}) do
ip = conn.remote_ip |> :inet.ntoa() |> to_string()
key = "#{prefix}:#{ip}"
case Claper.RateLimit.hit(key, interval_ms, max_requests) do
{:allow, _count} ->
conn
{:deny, _retry_after} ->
conn
|> put_resp_content_type("text/plain")
|> send_resp(429, "Too Many Requests")
|> halt()
end
end
end