Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security/JSONLoad autocorrect potential runtime error #3521

Closed
savef opened this issue Sep 21, 2016 · 6 comments
Closed

Security/JSONLoad autocorrect potential runtime error #3521

savef opened this issue Sep 21, 2016 · 6 comments

Comments

@savef
Copy link
Contributor

savef commented Sep 21, 2016

The autocorrect on Security/JSONLoad will replace JSON.load(request) with JSON.parse(request). One difference between these two methods is that JSON.load works with any object that responds to the #read method, such as an OpenURI HTTP request or a file handler. Here's an example:

request = open("http://localhost:3000/output.json")
result = JSON.load(request)

This will crash if replaced with JSON.parse.


The above is the exact issue I experienced, however I think there are other potential issues with this autocorrect. For example, consider the following difference between JSON.load and JSON.parse:

irb(main):001:0> JSON.load('false')
=> false
irb(main):002:0> JSON.parse('false')
JSON::ParserError: 784: unexpected token at 'false'
irb(main):003:0> JSON.parse('false', quirks_mode: true)
=> false

JSON.load allows primitives to be parsed, without requiring them to be in an actual JSON object. JSON.parse requires the :quirks_mode option to be true for this to work. So this type of use could also cause runtime errors in applications.


I think that the solution is to remove autocorrect for this cop.


RuboCop version

$ rubocop -V
0.43.0 (using Parser 2.3.1.3, running on ruby 2.3.1 x86_64-linux)
@bbatsov
Copy link
Collaborator

bbatsov commented Oct 2, 2016

I think that the solution is to remove autocorrect for this cop.

Or just disable it by default. After all the auto-correct is not reliable, because the cop is not reliable. I'd also extend the cop's description a bit.

@savef
Copy link
Contributor Author

savef commented Oct 5, 2016

Or just disable it by default. After all the auto-correct is not reliable, because the cop is not reliable.

I disagree. The cop's position that JSON.load(x) is potentially dangerous seems a fair one.

Forcing the author to change their code to either JSON.parse(stream.read) or JSON.parse(value, quirks_mode: true) when necessary both lead to more explicit code, so readability is improved in these edge case scenarios. And the improved security provided by JSON.parse that the cop originally intended to provide still applies when passing in a full JSON string.

@bbatsov
Copy link
Collaborator

bbatsov commented Oct 5, 2016

Fair enough. Let's agree that the solution is to extend the cop's description and disable its auto-correct by default.

@savef
Copy link
Contributor Author

savef commented Oct 5, 2016

disable its auto-correct by default

Just to clarify this, you're talking about removing the Security::JSONLoad#autocorrect method, right? If not I'm not sure I understand the distinction. I don't know what it means for the autocorrect to be disabled by default, without the whole cop being disabled. I don't know what it'd mean to be enabled by default either since the autocorrect code (AFAIK) always requires the --auto-correct switch.

I'll try to put in a PR for this within the next week though.

@bbatsov
Copy link
Collaborator

bbatsov commented Oct 5, 2016

All cops have an autocorrect attribute that can be set to false. :-) This enables/disable autocorrection for the particular cop. Some people might be perfectly fine with the autocorrect shortcomings.

@savef
Copy link
Contributor Author

savef commented Oct 5, 2016

Right, think I've got it, the AutoCorrect cop config. Thanks.

savef added a commit to savef/rubocop that referenced this issue Oct 7, 2016
…ult.

The autocorrect on this cop is dangerous for at least two reasons depending on the value being passed to the `JSON` class method, so this disabled it by default. One known reason is where we pass in a stream such as `JSON.load(open('file'))`, this cannot be swapped out for `JSON.parse` without calling `#read` on the stream. Another known reason is where the JSON string is a single value, rather than a full JSON object, such as `JSON.load('false')`, this cannot be swapped out for `JSON.parse` without adding the `quirks_mode: true` option.

Also slightly improve the description in the cop and `enabled.yml`.

Also fix the offence message.
@bbatsov bbatsov closed this as completed in 745f077 Oct 7, 2016
Neodelf pushed a commit to Neodelf/rubocop that referenced this issue Oct 15, 2016
…ult (rubocop#3584)

The autocorrect on this cop is dangerous for at least two reasons depending on the value being passed to the `JSON` class method, so this disabled it by default. One known reason is where we pass in a stream such as `JSON.load(open('file'))`, this cannot be swapped out for `JSON.parse` without calling `#read` on the stream. Another known reason is where the JSON string is a single value, rather than a full JSON object, such as `JSON.load('false')`, this cannot be swapped out for `JSON.parse` without adding the `quirks_mode: true` option.

Also slightly improve the description in the cop and `enabled.yml`.

Also fix the offence message.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants