Safeguard
Security Guides•

Rails send_file, uploads and redirect_to with user input

Three Rails mistakes that turn a request parameter into a file read or an open redirect, and the fixes the Rails security guide recommends for each one.

Safeguard Security Team
3 min read

Three Rails patterns cause trouble when a request parameter reaches them: send_file with a user supplied name, file upload names, and redirect_to with a user supplied URL. The fix in each case is the same idea, check against what you expect rather than trying to strip what you fear.

send_file and path traversal

If you pass a user supplied name straight into send_file, a name like a relative path can reach files outside the intended folder. The Rails guide advises expanding the path with File.expand_path and confirming the result is still inside the expected directory.

base = Rails.root.join("private", "reports").to_s
path = File.expand_path(File.join(base, params[:name]))
head :forbidden and return unless path.start_with?(base + "/")
send_file path

A stronger design, also from the guide, is to store the uploaded file name in the database and name the file on disk by record ID. Then the user never controls a path at all.

File names on upload

The guide says to filter file names with a permitted list that accepts only known safe characters, rather than trying to strip dangerous parts. A blocklist of bad patterns always misses one. Related advice from the same guide:

  • Do not store uploads under /public if your Apache DocumentRoot points there.
  • Process media files asynchronously so heavy processing cannot be used to exhaust the server.

Open redirects

redirect_to params[:next] is the classic open redirect. An attacker sends a victim a link to your real domain that bounces to a phishing site, which borrows your reputation. The guide says not to pass user input directly to redirect_to, to check URLs against a permitted list or a strict regular expression, and not to allow data: URLs or other unsafe protocols as targets.

ALLOWED = %w[/dashboard /settings].freeze
target = ALLOWED.include?(params[:next]) ? params[:next] : root_path
redirect_to target

Pattern to remember

  • File path: Strip dots; Expand and confirm prefix, or use IDs
  • File name: Blocklist; Allowed characters only
  • Redirect target: None; Fixed list of destinations

Quick check

Is it enough to remove double dots from the file name?

No. Check the resolved path against the base directory instead of hunting for bad sequences.

Can I allow redirects to any path on my own site?

Use a strict allowlist or a strict check. Be careful that values beginning with two slashes or a scheme are not treated as local.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.