Class: Scryer::Rules::JwtInsecureRule

Inherits:
Scryer::Rule show all
Defined in:
lib/scryer/rules/jwt_insecure_rule.rb

Overview

Flags insecure usage of the jwt gem's JWT.decode/JWT.encode:

- `JWT.decode(token, secret, false, ...)` — the third positional arg
literal `false` disables signature verification entirely, so any
caller can forge a token that decodes successfully.
- `algorithm: 'none'` / `'alg' => 'none'` — the "none" algorithm
means the token isn't signed at all.
- A plain string literal passed directly as the secret/key argument
— distinct from HardcodedSecretRule, which only matches
`x = "literal"` assignment targets, not a literal inline in a call
argument.

Constant Summary collapse

PLACEHOLDER_VALUES =
/\A(x+|0+|change-?me|your[_-]?(secret|key)|placeholder|example|dummy|fake|test|redacted|\*+)\z/i.freeze

Instance Attribute Summary

Attributes inherited from Scryer::Rule

#file, #sexp, #source

Instance Method Summary collapse

Methods inherited from Scryer::Rule

inherited, #initialize

Constructor Details

This class inherits a constructor from Scryer::Rule

Instance Method Details

#scanObject



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/scryer/rules/jwt_insecure_rule.rb', line 21

def scan
  findings = []

  Ast.each_node(sexp) do |node|
    next unless Ast.tagged?(node, :method_add_arg, :command, :command_call)

    inner = Ast.tagged?(node, :method_add_arg) ? node[1] : node
    receiver_and_name = Ast.call_name(inner)
    next unless receiver_and_name

    receiver, method_name = receiver_and_name
    next unless const_receiver_name(receiver) == "JWT" && %w[decode encode].include?(method_name)

    args = Ast.call_arguments(node)
    line = Ast.line_of(node)

    findings << verify_bypass_finding(line) if method_name == "decode" && Ast.false_literal?(args[2])
    findings << algorithm_none_finding(method_name, line) if algorithm_none?(node)
    findings.concat(inline_secret_finding(method_name, args, line))
  end

  findings
end