Under certain circumstances, the middleware isn't informed that the
response body has been fully closed which result in request state not
being fully reset before the next request.
[CVE-2022-23633]
Running the Action Pack tests outputs a warning:
./actionpack/test/controller/test_case_test.rb:1007: warning: instance variable @counter not initialized
Surrounding the line with silence_warnings cleans up the output.
This patch fixes the indentation of a nested bullet list in the
documentation of `ActionController::Parameters` that appeared as inside
a box in api.rubyonrails.org documentation website.
In previous versions of Rails, a dynamic regex was built to find templates.
After that, PathParser started to be used to both match and sort templates.
With the dynamic regex, templates with lowdash locales (es_AR) were
found properly. But the PathParser regex does not match locales with this
format, only allowing dash (es-AR) or no dash (es). Templates with lowdash
locales have a wrong virtual path and get filtered.
In this commit the PathParser regex is extended to support the lowdash.
`params` contains `@logging_context` in its instance to notify
unpermitted parameters including the context through Rails
Instrumentation API. However, the logging context disappeared when
`params` is updated with some methods, such as `require`, `slice`,
`merge`, etc, so the subscriber of `unpermitted_parameters` could not
get the information.
This patch tries to initialize `Parameters` with `@logging_context`
where it makes sense to pass the information. The following methods will
be affected with this patch:
* `require`
* `deep_dup`
* `slice`
* `except`
* `extract!`
* `transform_values`
* `transform_keys`
* `deep_transform_keys`
* `select`
* `reject`
* `compact`
* `merge`
* `reverse_merge`
When a host was an IP with a port, the IPAddr object comparisson was
raising an exception which was making the middleware reject the request.
Now we extract the hostname out of the host when comparing with IPAddr
objects.
Only "localhost" and ".localhost" were allowed by default in
development, but the port is also part of the header that is sent. It
is a bad idea to try parsing whatever stuff is in the HTTP header, so
this commit specifically adds localhost with a port in the "allowed
hosts" list in development.
Prior to this commit, it was possible to pass an unvalidated host
through the `X-Forwarded-Host` header. If the value of the header
was prefixed with a invalid domain character (for example a `/`),
it was always accepted as the actual host of that request.
Since this host is used for all url helpers, an attacker could change
generated links and redirects. If the header is set to
`X-Forwarded-Host: //evil.hacker`, a redirect will be send to
`https:////evil.hacker/`. Browsers will ignore these four slashes
and redirect the user.
[CVE-2021-44528]
When `before_action :callback, only: :action_name` is declared on a
controller that doesn't respond to `action_name`, raise an exception
at request time. This is a safety measure to ensure that typos or
forgetfulness don't prevent a crucial callback from being run when it
should.
Include names of filters for more useful error messages
The error message of the raised exception will be more useful if it
indicates the names of the callbacks that have the missing conditinoal
action.
The way the callbacks get shoehorned into `_normalize_callback_options`
options parameter is a little awkward, but done this way to avoid
changing the method's signature, since it is a publicly documented
method.
When `before_setup` fails, for example with fixture errors, the failure is stored, `setup` is skipped, and `take_failed_screenshot` is called. Taking a screenshot triggers starting the server which will probably fail since fixtures are not properly loaded. This generates another failure and makes it harder to debug the fixture failure.
If the server was not already started, it makes no sense to take a screenshot since it is not relevant.
This commit skips taking a failure screenshot if no browser session has been started.
`ActionController::TestCase` keeps a `@controller` instance variable, which represents the controller being tested. At the end of each request inside a test, its [params and format](https://github.com/rails/rails/blob/main/actionpack/lib/action_controller/metal/testing.rb) are reset. But any other instance variables set in the test aren't reset. This creates a problem if you do something like this:
```ruby
class UserController
def show
@user ||= User.find(params[:id])
render plain: @user.name
end
end
```
```ruby
test "gets the user" do
get :show, params: { id: users(:one).id }
assert "one", response.body
get :show, params: { id: users(:two).id }
assert "two", response.body
end
```
The second assertion will fail, because `@user` won't be re-assigned in the second test (due to `||=`). This example is a bit contrived, but it shows how instance variables persisting between requests can lead to surprising outcomes.
This PR fixes this by clearing all instance variables that were created on the controller while a request was processed.
It explicitly excludes instance variables that were created *before* any requests were run. And it leaves the instance variable around until the *next* request in the test. This means that you can still do this:
```ruby
test "gets the user" do
@controller.user = users(:one) # assuming `Controller#user` users an ivar internally, you can set the ivar here...
get :show_current
assert "one", response.body
assert_equal users(:one), @controller.user # and you can read the ivar here
end
```
Ruby 3.1 is going to introduce an [optimization][] that makes interpolation
of some types of objects faster, unless there is a custom implementation
of to_s. Since Rails is overriding `to_s` for a bunch of core classes it
means that this optimization in Rails applications will be disabled.
In order to allow Rails applications to use this optimization in
the future we are deprecating all the reasons we override `to_s` in
those core classes in favor of using `to_formatted_s`.
[optimization]: b08dacfea3
In 74cb9a6f3823cc64ef97ed6d9250a4d743abf426 a `#` was added to the
inspect of ActionController::Parameters.
This change adds `#` to the inspect output of
ActionController::Parameters in the documentation.