Description of the issue 📄
Rollbar shows recurring ActionDispatch::Http::MimeNegotiation::InvalidType errors, e.g.:
"../../../../../../../../../../etc/services{{" is not a valid MIME type
(Rollbar #549)
These are automated scanner probes that send path-traversal strings in the Accept header. Rails 8.1 raises InvalidType during MIME negotiation, and the class is not in the default rescue_responses map (verified in actionpack 8.1.3.1's exception_wrapper.rb), so each probe becomes a 500 and a Rollbar notification. There is nothing for the application to do with these requests — they should never reach it, or at worst return 4xx.
Options
1. Nginx edge block — config/nginx.conf.erb gets a map on the Accept/Content-Type headers and returns 406 when either contains ../:
map "$http_accept $content_type" $bad_mime {
default 0;
~"\.\./" 1;
}
if ($bad_mime) { return 406; }
Pros: stops these requests before Rails, no app code. Cons: nginx config is baked into the dyno, so it's awkward to test locally; the rule only covers ../ patterns in those two headers.
2. App-level rescue — map the exception to 406 in config/application.rb:
config.action_dispatch.rescue_responses[
"ActionDispatch::Http::MimeNegotiation::InvalidType"
] = :not_acceptable
Pros: one line, testable, uses the same mechanism Rails already uses for ActionController::UnknownFormat. Cons: the request still reaches the app (and its access logs), though Rollbar goes quiet.
3. Both — nginx rule as the primary block, rescue_responses as the safety net for anything nginx misses (other probe shapes hitting the same code path).
Recommendation
Option 3. The nginx rule blocks the current probe pattern cheaply, and the rescue mapping guarantees no 500 for this class of malformed request regardless of what pattern the bots use next.
Comments on the approach welcome — happy to open a PR once agreed.
Description of the issue 📄
Rollbar shows recurring
ActionDispatch::Http::MimeNegotiation::InvalidTypeerrors, e.g.:"../../../../../../../../../../etc/services{{" is not a valid MIME type(Rollbar #549)
These are automated scanner probes that send path-traversal strings in the
Acceptheader. Rails 8.1 raisesInvalidTypeduring MIME negotiation, and the class is not in the defaultrescue_responsesmap (verified in actionpack 8.1.3.1'sexception_wrapper.rb), so each probe becomes a 500 and a Rollbar notification. There is nothing for the application to do with these requests — they should never reach it, or at worst return 4xx.Options
1. Nginx edge block —
config/nginx.conf.erbgets amapon the Accept/Content-Type headers and returns 406 when either contains../:Pros: stops these requests before Rails, no app code. Cons: nginx config is baked into the dyno, so it's awkward to test locally; the rule only covers
../patterns in those two headers.2. App-level rescue — map the exception to 406 in
config/application.rb:Pros: one line, testable, uses the same mechanism Rails already uses for
ActionController::UnknownFormat. Cons: the request still reaches the app (and its access logs), though Rollbar goes quiet.3. Both — nginx rule as the primary block,
rescue_responsesas the safety net for anything nginx misses (other probe shapes hitting the same code path).Recommendation
Option 3. The nginx rule blocks the current probe pattern cheaply, and the rescue mapping guarantees no 500 for this class of malformed request regardless of what pattern the bots use next.
Comments on the approach welcome — happy to open a PR once agreed.