Open Redirect in Grape
How Open Redirect Manifests in Grape
Open Redirect vulnerabilities occur when an application redirects users to a URL supplied via user-controlled input without proper validation. In Grape, a Ruby micro-framework for building REST-like APIs, this often surfaces in endpoints that perform redirects after actions like authentication, logout, or form submissions. The core issue stems from Grape's redirect method (inherited from Rack), which can be misused when directly incorporating parameters from the request.
A typical vulnerable pattern in a Grape API looks like this:
class API < Grape::API
get '/logout' do
# Dangerous: directly using user-supplied redirect URL
redirect params[:redirect_to] || '/goodbye'
end
endHere, an attacker can craft a URL like https://api.example.com/logout?redirect_to=https://evil.com/phishing. If a logged-in user clicks this link, they'll be redirected to the attacker's site after logout, enabling phishing or session token theft. This is especially risky in OAuth callback endpoints or any API that handles authentication flows, where redirects are common. The vulnerability is categorized under OWASP API Top 10 2023 as part of A10:2023 – Server-Side Request Forgery (SSRF), as uncontrolled redirects can facilitate SSRF or be chained with other attacks.
Grape's flexibility with parameters and its Rack heritage mean developers might inadvertently trust params without sanitization. Unlike web applications that often redirect to HTML pages, API redirects typically use HTTP 3xx status codes with a Location header, making them equally susceptible to manipulation. Real-world examples include CVE-2020-26116 (a similar issue in Ruby on Rails) where unvalidated redirect parameters led to phishing.
Grape-Specific Detection
Detecting Open Redirect in Grape APIs requires both static code analysis and dynamic testing. Statically, search your codebase for uses of redirect that incorporate user input, such as params[:redirect_to], params[:next], or any instance where request parameters flow directly into the redirect call. Pay special attention to endpoints that handle authentication callbacks (e.g., OAuth /callback) or logout actions.
Dynamically, you can test by sending crafted requests with a malicious redirect URL and inspecting the response's Location header. For example, using curl:
curl -i "https://api.example.com/logout?redirect_to=https://attacker.com"If the response includes Location: https://attacker.com, the endpoint is vulnerable. However, manual testing is time-consuming and error-prone.
This is where middleBrick automates detection. As part of its 12 parallel security checks—specifically under SSRF and Input Validation—middleBrick probes your API's unauthenticated attack surface. It submits sequential payloads with attacker-controlled domains (e.g., ?redirect_to=https://scan.middlebrick.test) and analyzes whether the API returns a redirect to that domain. No credentials or configuration are needed; you simply provide the endpoint URL. The scan takes 5–15 seconds and returns a risk score (A–F) with per-category breakdowns. If an Open Redirect is found, it appears in the report with severity (typically High) and remediation guidance tailored to Grape. You can use the middleBrick CLI (middlebrick scan <url>) or the Web Dashboard to initiate scans and track findings over time.
Grape-Specific Remediation
Fixing Open Redirect in Grape involves strict validation of any redirect target. Never trust user-supplied URLs. The recommended approach is to implement a whitelist of allowed hosts or restrict redirects to relative paths within your domain.
Whitelist-Based Validation: Parse the supplied URL and check its host against a predefined list. Use Ruby's URI module to safely parse and extract components:
class API < Grape::API
ALLOWED_REDIRECT_HOSTS = ['example.com', 'www.example.com'].freeze
get '/logout' do
redirect_url = params[:redirect_to]
# Parse and validate
uri = URI.parse(redirect_url) rescue nil
if uri && ALLOWED_REDIRECT_HOSTS.include?(uri.host) && %w[http https].include?(uri.scheme)
redirect redirect_url
else
# Default to a safe location
redirect '/goodbye'
end
end
endThis ensures only URLs from trusted domains are followed. Note the use of rescue nil to handle malformed URLs gracefully.
Relative Path Restriction: If your API only needs to redirect within the same application, enforce that the redirect URL is a relative path (no scheme or host). You can use a regex to validate:
def safe_relative_path?(path)
!!(path =~ %r{^/([a-zA-Z0-9_\-\./]*)$})
end
get '/some_endpoint' do
redirect_path = params[:redirect_to]
if safe_relative_path?(redirect_path)
redirect redirect_path
else
error!('Invalid redirect path', 400)
end
endThis prevents open redirects by disallowing absolute URLs.
Additionally, consider using Grape's built-in parameter validation with params blocks to reject unexpected values early. For example:
params do
requires :redirect_to, type: String, regexp: /\A\/[a-zA-Z0-9_\-\.\/]*\z/
end
get '/logout' do
redirect params[:redirect_to]
endAfter remediation, re-scan with middleBrick to verify the issue is resolved. The Pro plan offers continuous monitoring, which can alert you if new redirect endpoints are introduced without validation. For CI/CD integration, the middleBrick GitHub Action can fail builds if Open Redirect risks exceed your threshold, ensuring vulnerabilities don't reach production.
Frequently Asked Questions
Why is Open Redirect particularly dangerous in API contexts?
How does middleBrick detect Open Redirect vulnerabilities in Grape applications without credentials?
?redirect_to=https://scan.middlebrick.test) to your API endpoints. It then analyzes the HTTP response for Location headers that point to the attacker-controlled domain. This is part of its SSRF and Input Validation checks, requiring no authentication or configuration—just the endpoint URL.