Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Mapping to a redirect route with a param can result in URI::InvalidURIError #5688

Closed
kylev opened this Issue · 8 comments

4 participants

@kylev

Assuming a paramaterized redirect route like this:

match 'foo/view/:id' => redirect("/foo/%{id}")

It is possible for an errant link to cause this to throw URI::InvalidURIError via HttpHelpers#redirect. If someone forgets their closing quote in a link and the incoming URL looks like "/foo/view/1234>" (with the greater-than) the unprotected URI.parse on mapper.rb:372 will throw this exception. This URL either shouldn't make it to the mapper or should not choke.

One suggestion would be transforming the URI exception to an ActionController::RoutingError and thus a 404:

begin
  uri = URI.parse(path_proc.call(*params))
rescue URI::InvalidURIError => e
  raise ActionController::RoutingError, e.message
end

This is in actionpack for 3-0-stable.

@kaiwren kaiwren referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@kaiwren kaiwren referenced this issue from a commit
Commit has since been removed from the repository and is no longer available.
@kaiwren

Doesn't seem like a test can easily be written for this - all the test helpers (lib/action_dispatch/testing/integration.rb in ActionPack and lib/rack/test.rb in rack-test) use URI.parse before making mock requests inadvertently validating the URI. Am I missing something?

@kaiwren kaiwren referenced this issue from a commit in c42engineering/rails
@kaiwren kaiwren Issue #5688:
* Fixed modulo based redirect to fail with a RoutingError rather than an InvalidURIError if the generated redirect URI is invalid because of a bad incoming URI
* Changed intgration test helper to not blow up on invalid URIs so that tests for invalid URIs can be written
* Still have a failing test because we still use URI.parse further down the testing stack in rack-test inadvertently validating the incoming URI for correctness
95aad8f
@kylev

Yeah, I was going to comment that the integration tests are specifically insulated from this type of test case (or any invalid URL test case) because of the use of URI.process in the process helper of integration.rb. mapper.rb has very few direct-call tests.

@pixeltrix
Owner

I'd consider this a bug in redirect as it should be url encoding any params that will get interpolated - needs fixing in master, 3-2-stable and 3-1-stable if someone wants to have a go. I'd % escape the subdelims from RFC 3986 even though they're valid in a path because they may be used in query context, e.g:

match 'foo/view/:id' => redirect("/foo?id=%{id}")

/cc @rohit

@kaiwren

@pixeltrix I'll take a stab at it just to get going if nothing else. I'll almost certainly come back with more questions, though, if that's ok.

@pixeltrix
Owner

@kaiwren thanks - questions are fine

@pixeltrix pixeltrix was assigned
@pixeltrix pixeltrix closed this in 958daaa
@pixeltrix pixeltrix referenced this issue in rails/journey
Closed

unicode urls and redirection #28

@pwim

This patch causes an issue when using the following redirection strategy

constraints(:host => "www.kanjidamage.com") do
  match '*source', to: redirect("http://kanjidamage.com/%{source}")
  root to: redirect("http://kanjidamage.com/")
end

If a user visits http://www.kanjidamage.com/kanji/51, he will now be redirected to http://kanjidamage.com/kanji%2F51.

@pixeltrix
Owner

@pwim this is intentional - the redirect interpolation may be used in a query argument where / needs escaping, e.g.

constraints(:host => "www.kanjidamage.com") do
  match '*source', to: redirect("http://kanjidamage.com/?page=%{source}")
  root to: redirect("http://kanjidamage.com/")
end

If you need something different just construct your own redirect proc, :e.g:

constraints(:host => "www.kanjidamage.com") do
  match '*source', to: redirect { |params, request| "http://kanjidamage.com/#{URI.escape(params[:source]}" }
  root to: redirect("http://kanjidamage.com/")
end

The URI.escape doesn't escape / unless you ask it to.

@pwim

@pixeltrix OK, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.