Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #43 from benmanns/hotfix/jsonp-callback-for-json-only

Rack::JSONP checks the callback parameters on non-JSON response types
  • Loading branch information...
commit 551ae792bc8c3c0610e7f334bdc1c55de2fc2707 2 parents 42b92b7 + a80437b
@rkh rkh authored
Showing with 50 additions and 6 deletions.
  1. +4 −6 lib/rack/contrib/jsonp.rb
  2. +46 −0 test/spec_rack_jsonp.rb
View
10 lib/rack/contrib/jsonp.rb
@@ -35,16 +35,14 @@ def initialize(app)
def call(env)
request = Rack::Request.new(env)
- if has_callback?(request)
- callback = request.params['callback']
- return bad_request unless valid_callback?(callback)
- end
-
status, headers, response = @app.call(env)
headers = HeaderHash.new(headers)
- if is_json?(headers) && callback
+ if is_json?(headers) && has_callback?(request)
+ callback = request.params['callback']
+ return bad_request unless valid_callback?(callback)
+
response = pad(callback, response)
# No longer json, its javascript!
View
46 test/spec_rack_jsonp.rb
@@ -80,6 +80,52 @@
end
end
+ context 'but is invalid' do
+ context 'with content-type application/json' do
+ specify 'should return "Bad Request"' do
+ test_body = '{"bar":"foo"}'
+ callback = '*'
+ content_type = 'application/json'
+ app = lambda { |env| [200, {'Content-Type' => content_type}, [test_body]] }
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
+ body = Rack::JSONP.new(app).call(request).last
+ body.should.equal ['Bad Request']
+ end
+
+ specify 'should return set the response code to 400' do
+ test_body = '{"bar":"foo"}'
+ callback = '*'
+ content_type = 'application/json'
+ app = lambda { |env| [200, {'Content-Type' => content_type}, [test_body]] }
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
+ response_code = Rack::JSONP.new(app).call(request).first
+ response_code.should.equal 400
+ end
+ end
+
+ context 'with content-type text/plain' do
+ specify 'should return "Good Request"' do
+ test_body = 'Good Request'
+ callback = '*'
+ content_type = 'text/plain'
+ app = lambda { |env| [200, {'Content-Type' => content_type}, [test_body]] }
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
+ body = Rack::JSONP.new(app).call(request).last
+ body.should.equal ['Good Request']
+ end
+
+ specify 'should not change the response code from 200' do
+ test_body = '{"bar":"foo"}'
+ callback = '*'
+ content_type = 'text/plain'
+ app = lambda { |env| [200, {'Content-Type' => content_type}, [test_body]] }
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
+ response_code = Rack::JSONP.new(app).call(request).first
+ response_code.should.equal 200
+ end
+ end
+ end
+
context "with XSS vulnerability attempts" do
def request(callback, body = '{"bar":"foo"}')
app = lambda { |env| [200, {'Content-Type' => 'application/json'}, [body]] }
Please sign in to comment.
Something went wrong with that request. Please try again.