Class: RuboCop::Cop::GitlabSecurity::JsonSerialization

Inherits:
Cop
  • Object
show all
Defined in:
lib/rubocop/cop/gitlab_security/json_serialization.rb

Overview

Checks for ‘to_json` / `as_json` without allowing via `only`.

Either method called on an instance of a ‘Serializer` class will be ignored. Associations included via `include` are subject to the same rules.

See gitlab.com/gitlab-org/gitlab-ce/issues/29661

Examples:


# bad
render json: @user.to_json
render json: @user.to_json(except: %i[password])
render json: @user.to_json(
  only: %i[username],
  include: [:identities]
)

# acceptable
render json: UserSerializer.new.to_json

# good
render json: @user.to_json(only: %i[name username])
render json: @user.to_json(
  only: %i[username],
  include: { identities: { only: %i[provider] } }
)

Constant Summary collapse

MSG =
"Don't use `%s` without specifying `only`"

Instance Method Summary collapse

Instance Method Details

#constant_init(node) ⇒ Object

Check for ‘SomeConstant.new`



63
64
65
# File 'lib/rubocop/cop/gitlab_security/json_serialization.rb', line 63

def_node_search :constant_init, <<~PATTERN
  (send (const nil? $_) :new ...)
PATTERN

#contains_only?(node) ⇒ Object

Check for a ‘only: […]` pair anywhere in the node



57
58
59
# File 'lib/rubocop/cop/gitlab_security/json_serialization.rb', line 57

def_node_search :contains_only?, <<~PATTERN
  (pair (sym :only) (array ...))
PATTERN

#include_pair?(node) ⇒ Object

Check if node is a ‘include: …` pair



51
52
53
# File 'lib/rubocop/cop/gitlab_security/json_serialization.rb', line 51

def_node_matcher :include_pair?, <<~PATTERN
  (pair (sym :include) (hash $...))
PATTERN

#json_serialization?(node) ⇒ Object

Check for ‘to_json` sent to any object that’s not a Hash literal or Serializer instance



39
40
41
# File 'lib/rubocop/cop/gitlab_security/json_serialization.rb', line 39

def_node_matcher :json_serialization?, <<~PATTERN
  (send !{nil? hash #serializer?} ${:to_json :as_json} $...)
PATTERN

#on_send(node) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rubocop/cop/gitlab_security/json_serialization.rb', line 67

def on_send(node)
  matched = json_serialization?(node)
  return unless matched

  @_has_top_level_only = false
  @method = matched.first

  if matched.last.nil? || matched.last.empty?
    # Empty `to_json` call
    add_offense(node, location: :selector, message: format_message)
  else
    check_arguments(node, matched)
  end
end

#only_pair?(node) ⇒ Object

Check if node is a ‘only: …` pair



45
46
47
# File 'lib/rubocop/cop/gitlab_security/json_serialization.rb', line 45

def_node_matcher :only_pair?, <<~PATTERN
  (pair (sym :only) ...)
PATTERN