Api Rate Abuse on Supabase
How Api Rate Abuse Manifests in Supabase
Rate abuse in Supabase APIs typically exploits the platform's default open access model. Since Supabase automatically generates REST APIs for your database tables, attackers can discover these endpoints and flood them with requests, causing database overload, increased costs, and potential service disruption.
The most common attack pattern involves enumerating auto-generated endpoints like https://your-project.supabase.co/rest/v1/ and discovering tables that lack proper row-level security (RLS). Once identified, attackers can use tools like hey, ab, or custom scripts to send thousands of requests per second, overwhelming both the API gateway and your PostgreSQL database.
# Example of rate abuse targeting Supabase endpoints
curl -X POST https://your-project.supabase.co/rest/v1/users \
-H "apikey: your-anon-key" \
-H "Content-Type: application/json" \
-d '{"email": "test@example.com", "name": "Test User"}'Without proper rate limiting, a single IP address can create millions of records in minutes. The abuse becomes more severe when attackers use distributed networks (botnets) to rotate IP addresses, making traditional IP-based rate limiting ineffective. Supabase's default configuration allows unlimited requests to unauthenticated endpoints, creating a perfect target for credential stuffing, enumeration attacks, and denial-of-service attempts.
Another manifestation occurs through webhook abuse. Supabase Edge Functions can be triggered by external services, and without rate limiting, attackers can flood these endpoints with webhook requests, causing function execution costs to skyrocket and potentially exhausting your project's execution time limits.
Supabase-Specific Detection
Detecting rate abuse in Supabase requires monitoring both API gateway metrics and database performance indicators. The first sign is often unusual patterns in your Supabase dashboard's API metrics section, where you'll see spikes in request volume, particularly to specific endpoints.
Enable Supabase's built-in audit logs to track API access patterns. Look for these indicators:
-- Query to detect unusual API patterns
SELECT
timestamp,
user_agent,
ip_address,
endpoint,
COUNT(*) as request_count
FROM supabase_logs
WHERE timestamp > NOW() - INTERVAL '1 hour'
GROUP BY timestamp, user_agent, ip_address, endpoint
HAVING COUNT(*) > 100
ORDER BY request_count DESC;For comprehensive detection, middleBrick's API security scanner specifically tests Supabase endpoints for rate abuse vulnerabilities. The scanner identifies auto-generated REST API endpoints and tests them against rate limiting controls, providing a security score and specific findings about exposed endpoints.
middleBrick's scanning process for Supabase includes:
- Discovery of auto-generated REST API endpoints
- Testing for missing rate limiting controls
- Identification of endpoints without authentication requirements
- Analysis of webhook endpoints for abuse potential
- Detection of excessive data exposure through unrestricted queries
The scanner provides actionable findings with severity levels and remediation guidance specific to Supabase's architecture, helping you understand which endpoints are most vulnerable to rate abuse attacks.
Supabase-Specific Remediation
Remediating rate abuse in Supabase requires a multi-layered approach using Supabase's native features. Start with Row Level Security (RLS) to restrict access to your data tables. Enable RLS on all tables and create policies that limit what unauthenticated users can access.
-- Enable RLS on all tables
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;
ALTER TABLE comments ENABLE ROW LEVEL SECURITY;
-- Create restrictive policies for unauthenticated users
CREATE POLICY "Public can view posts" ON posts
FOR SELECT USING (true)
WITH CHECK (false); -- Prevent inserts/updates by unauthenticated usersImplement API rate limiting using Supabase Edge Functions with the @supabase/rate-limiter library. This provides distributed rate limiting across your functions.
// rate-limit.js
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts';
import { createRateLimiter } from 'https://raw.githubusercontent.com/supabase/rate-limiter/main/mod.ts';
const rateLimiter = createRateLimiter({
redisUrl: Deno.env.get('REDIS_URL'),
maxRequests: 100,
window: '1m',
});
const handler = async (req) => {
const { allowed, resetTime } = await rateLimiter.consume(req.headers.get('x-forwarded-for'));
if (!allowed) {
return new Response(
JSON.stringify({ error: 'Rate limit exceeded' }),
{ status: 429, headers: { 'Retry-After': resetTime } }
);
}
// Your API logic here
return new Response('OK', { status: 200 });
};
serve(handler);For database-level rate limiting, use PostgreSQL's built-in features with RLS policies that track request counts per user or IP address.
-- Create a table to track request counts
CREATE TABLE api_rate_limits (
ip_address TEXT PRIMARY KEY,
request_count INTEGER DEFAULT 0,
window_start TIMESTAMP DEFAULT NOW()
);
-- RLS policy to enforce rate limits
CREATE POLICY "Rate limit policy" ON users
FOR ALL USING (
(SELECT request_count FROM api_rate_limits
WHERE ip_address = current_setting('request.ip', true)) < 100
);
-- Function to update rate limits
CREATE OR REPLACE FUNCTION update_rate_limit()
RETURNS TRIGGER AS $$
BEGIN
-- Increment request count for the IP
INSERT INTO api_rate_limits (ip_address, request_count)
VALUES (current_setting('request.ip', true), 1)
ON CONFLICT (ip_address) DO UPDATE
SET request_count = api_rate_limits.request_count + 1,
window_start = CASE
WHEN api_rate_limits.window_start < NOW() - INTERVAL '1 minute'
THEN NOW()
ELSE api_rate_limits.window_start
END
WHERE api_rate_limits.ip_address = current_setting('request.ip', true);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;Configure Supabase Edge Functions to reject requests from known bad actors using IP reputation lists and implement exponential backoff for repeated violations.