From 5fdbbdea7996d95aa9cf071827305039f9d37eb5 Mon Sep 17 00:00:00 2001 From: Sakshis Date: Thu, 12 Dec 2024 05:24:52 +0000 Subject: [PATCH 1/3] ruby-excon-hardcoded-secret-ruby --- .../ruby-excon-hardcoded-secret-ruby.yml | 244 ++++++++++++++++++ ...y-excon-hardcoded-secret-ruby-snapshot.yml | 190 ++++++++++++++ .../ruby-excon-hardcoded-secret-ruby-test.yml | 16 ++ 3 files changed, 450 insertions(+) create mode 100644 rules/ruby/security/ruby-excon-hardcoded-secret-ruby.yml create mode 100644 tests/__snapshots__/ruby-excon-hardcoded-secret-ruby-snapshot.yml create mode 100644 tests/ruby/ruby-excon-hardcoded-secret-ruby-test.yml diff --git a/rules/ruby/security/ruby-excon-hardcoded-secret-ruby.yml b/rules/ruby/security/ruby-excon-hardcoded-secret-ruby.yml new file mode 100644 index 00000000..ef49d7cf --- /dev/null +++ b/rules/ruby/security/ruby-excon-hardcoded-secret-ruby.yml @@ -0,0 +1,244 @@ +id: ruby-excon-hardcoded-secret-ruby +language: ruby +severity: warning +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. Use + environment variables to securely provide credentials and other secrets or + retrieve them from a secure vault or Hardware Security Module (HSM). +note: >- + [CWE-798] Use of Hard-coded Credentials. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + Excon.new(..., :password => "...", ...): + # Excon.new(..., :password => "...", ...) + kind: call + all: + - has: + stopBy: neighbor + kind: constant + regex: ^Excon$ + - has: + stopBy: neighbor + regex: ^.$ + - has: + stopBy: neighbor + kind: identifier + regex: ^new$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: pair + all: + - has: + stopBy: neighbor + kind: simple_symbol + regex: ^:password$ + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_content + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: call + pattern: require 'excon' + Excon.new(..., :password => "...", ...)_with_instance: + # Excon.new(..., :password => "...", ...) + kind: call + all: + - has: + stopBy: neighbor + kind: constant + regex: ^Excon$ + - has: + stopBy: neighbor + regex: ^.$ + - has: + stopBy: neighbor + kind: identifier + regex: ^new$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: pair + all: + - has: + stopBy: neighbor + kind: simple_symbol + regex: ^:password$ + - has: + stopBy: neighbor + kind: identifier + pattern: $PSWD + - inside: + stopBy: end + kind: assignment + follows: + stopBy: end + kind: assignment + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $PSWD + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_content + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: call + pattern: require 'excon' + Excon.new(..., :password => Excon::Utils.escape_uri("..."), ...): + # Excon.new(..., :password => Excon::Utils.escape_uri("..."), ...) + kind: call + all: + - has: + stopBy: neighbor + kind: constant + regex: ^Excon$ + - has: + stopBy: neighbor + regex: ^.$ + - has: + stopBy: neighbor + kind: identifier + regex: ^new$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: pair + all: + - has: + stopBy: neighbor + kind: simple_symbol + regex: ^:password$ + - has: + stopBy: neighbor + kind: call + all: + - has: + stopBy: neighbor + kind: scope_resolution + regex: ^Excon::Utils$ + - has: + stopBy: neighbor + regex: ^.$ + - has: + stopBy: neighbor + kind: identifier + regex: ^escape_uri$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_content + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: call + pattern: require 'excon' + Excon.new(..., :password => Excon::Utils.escape_uri("..."), ...)_with_instance: + # Excon.new(..., :password => Excon::Utils.escape_uri("..."), ...) + kind: call + all: + - has: + stopBy: neighbor + kind: constant + regex: ^Excon$ + - has: + stopBy: neighbor + regex: ^.$ + - has: + stopBy: neighbor + kind: identifier + regex: ^new$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: pair + all: + - has: + stopBy: neighbor + kind: simple_symbol + regex: ^:password$ + - has: + stopBy: neighbor + kind: call + all: + - has: + stopBy: neighbor + kind: scope_resolution + regex: ^Excon::Utils$ + - has: + stopBy: neighbor + regex: ^.$ + - has: + stopBy: neighbor + kind: identifier + regex: ^escape_uri$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: neighbor + kind: identifier + pattern: $PASS + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: call + pattern: require 'excon' + - inside: + stopBy: end + kind: assignment + follows: + stopBy: end + kind: assignment + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $PASS + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_content + +rule: + kind: call + any: + - matches: Excon.new(..., :password => "...", ...) + - matches: Excon.new(..., :password => "...", ...)_with_instance + - matches: Excon.new(..., :password => Excon::Utils.escape_uri("..."), ...) + - matches: Excon.new(..., :password => Excon::Utils.escape_uri("..."), ...)_with_instance diff --git a/tests/__snapshots__/ruby-excon-hardcoded-secret-ruby-snapshot.yml b/tests/__snapshots__/ruby-excon-hardcoded-secret-ruby-snapshot.yml new file mode 100644 index 00000000..5dde2d20 --- /dev/null +++ b/tests/__snapshots__/ruby-excon-hardcoded-secret-ruby-snapshot.yml @@ -0,0 +1,190 @@ +id: ruby-excon-hardcoded-secret-ruby +snapshots: + ? | + require 'excon' + connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => 'pa%%word') + : labels: + - source: Excon.new('http://secure.geemus.com', :user => 'username', :password => 'pa%%word') + style: primary + start: 29 + end: 112 + - source: Excon + style: secondary + start: 29 + end: 34 + - source: . + style: secondary + start: 34 + end: 35 + - source: new + style: secondary + start: 35 + end: 38 + - source: :password + style: secondary + start: 88 + end: 97 + - source: pa%%word + style: secondary + start: 102 + end: 110 + - source: '''pa%%word''' + style: secondary + start: 101 + end: 111 + - source: :password => 'pa%%word' + style: secondary + start: 88 + end: 111 + - source: ('http://secure.geemus.com', :user => 'username', :password => 'pa%%word') + style: secondary + start: 38 + end: 112 + - source: require 'excon' + style: secondary + start: 0 + end: 15 + - source: | + require 'excon' + connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => 'pa%%word') + style: secondary + start: 0 + end: 113 + ? | + require 'excon' + connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => Excon::Utils.escape_uri('pa%%word')) + : labels: + - source: Excon.new('http://secure.geemus.com', :user => 'username', :password => Excon::Utils.escape_uri('pa%%word')) + style: primary + start: 29 + end: 137 + - source: Excon + style: secondary + start: 29 + end: 34 + - source: . + style: secondary + start: 34 + end: 35 + - source: new + style: secondary + start: 35 + end: 38 + - source: :password + style: secondary + start: 88 + end: 97 + - source: Excon::Utils + style: secondary + start: 101 + end: 113 + - source: . + style: secondary + start: 113 + end: 114 + - source: escape_uri + style: secondary + start: 114 + end: 124 + - source: pa%%word + style: secondary + start: 126 + end: 134 + - source: '''pa%%word''' + style: secondary + start: 125 + end: 135 + - source: ('pa%%word') + style: secondary + start: 124 + end: 136 + - source: Excon::Utils.escape_uri('pa%%word') + style: secondary + start: 101 + end: 136 + - source: :password => Excon::Utils.escape_uri('pa%%word') + style: secondary + start: 88 + end: 136 + - source: ('http://secure.geemus.com', :user => 'username', :password => Excon::Utils.escape_uri('pa%%word')) + style: secondary + start: 38 + end: 137 + - source: require 'excon' + style: secondary + start: 0 + end: 15 + - source: | + require 'excon' + connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => Excon::Utils.escape_uri('pa%%word')) + style: secondary + start: 0 + end: 138 + ? | + require 'excon' + pw = 'password' + connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => pw) + : labels: + - source: Excon.new('http://secure.geemus.com', :user => 'username', :password => pw) + style: primary + start: 45 + end: 120 + - source: Excon + style: secondary + start: 45 + end: 50 + - source: . + style: secondary + start: 50 + end: 51 + - source: new + style: secondary + start: 51 + end: 54 + - source: :password + style: secondary + start: 104 + end: 113 + - source: pw + style: secondary + start: 117 + end: 119 + - source: :password => pw + style: secondary + start: 104 + end: 119 + - source: ('http://secure.geemus.com', :user => 'username', :password => pw) + style: secondary + start: 54 + end: 120 + - source: pw + style: secondary + start: 16 + end: 18 + - source: password + style: secondary + start: 22 + end: 30 + - source: '''password''' + style: secondary + start: 21 + end: 31 + - source: pw = 'password' + style: secondary + start: 16 + end: 31 + - source: connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => pw) + style: secondary + start: 32 + end: 120 + - source: require 'excon' + style: secondary + start: 0 + end: 15 + - source: | + require 'excon' + pw = 'password' + connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => pw) + style: secondary + start: 0 + end: 121 diff --git a/tests/ruby/ruby-excon-hardcoded-secret-ruby-test.yml b/tests/ruby/ruby-excon-hardcoded-secret-ruby-test.yml new file mode 100644 index 00000000..014baff5 --- /dev/null +++ b/tests/ruby/ruby-excon-hardcoded-secret-ruby-test.yml @@ -0,0 +1,16 @@ +id: ruby-excon-hardcoded-secret-ruby +valid: + - | + cluster = Cassandra.cluster(username: 'user',password: '')pw2 = Excon::Utils.escape_uri('pa%%word') + connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => pw2) +invalid: + - | + require 'excon' + pw = 'password' + connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => pw) + - | + require 'excon' + connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => Excon::Utils.escape_uri('pa%%word')) + - | + require 'excon' + connection = Excon.new('http://secure.geemus.com', :user => 'username', :password => 'pa%%word') From e773b571f2f28754f36440062eb96583b1c1b242 Mon Sep 17 00:00:00 2001 From: Sakshis Date: Thu, 12 Dec 2024 05:26:59 +0000 Subject: [PATCH 2/3] ruby-octokit-hardcoded-secret-ruby --- .../ruby-octokit-hardcoded-secret-ruby.yml | 103 +++++++ ...octokit-hardcoded-secret-ruby-snapshot.yml | 270 ++++++++++++++++++ ...uby-octokit-hardcoded-secret-ruby-test.yml | 25 ++ 3 files changed, 398 insertions(+) create mode 100644 rules/ruby/security/ruby-octokit-hardcoded-secret-ruby.yml create mode 100644 tests/__snapshots__/ruby-octokit-hardcoded-secret-ruby-snapshot.yml create mode 100644 tests/ruby/ruby-octokit-hardcoded-secret-ruby-test.yml diff --git a/rules/ruby/security/ruby-octokit-hardcoded-secret-ruby.yml b/rules/ruby/security/ruby-octokit-hardcoded-secret-ruby.yml new file mode 100644 index 00000000..878b5ee3 --- /dev/null +++ b/rules/ruby/security/ruby-octokit-hardcoded-secret-ruby.yml @@ -0,0 +1,103 @@ +id: ruby-octokit-hardcoded-secret-ruby +language: ruby +severity: warning +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. Use + environment variables to securely provide credentials and other secrets or + retrieve them from a secure vault or Hardware Security Module (HSM). +note: >- + [CWE-798] Use of Hard-coded Credentials. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + Octokit::Client.new(password:""): + # Octokit::Client.new(..., password: "", ...) + kind: call + all: + - has: + stopBy: neighbor + kind: scope_resolution + regex: ^Octokit::Client$ + - has: + stopBy: neighbor + regex: ^.$ + - has: + stopBy: neighbor + kind: identifier + regex: ^new$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: pair + all: + - has: + stopBy: neighbor + regex: ^:password|:access_token|:client_secret|password|access_token|client_secret$ + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_content + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: call + pattern: require 'octokit' + Octokit::Client.new(password:"")with_instance: + # Octokit::Client.new(..., password: "", ...) + kind: assignment + all: + - has: + stopBy: end + kind: call + all: + - has: + stopBy: neighbor + kind: scope_resolution + regex: ^Octokit::Client$ + - has: + stopBy: neighbor + regex: ^.$ + - has: + stopBy: neighbor + kind: identifier + regex: ^new$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: pair + all: + - has: + stopBy: neighbor + regex: ^:password|:access_token|:client_secret|password|access_token|client_secret$ + - has: + stopBy: neighbor + kind: identifier + nthChild: 2 + pattern: $PASS + - follows: + stopBy: end + kind: assignment + pattern: $PASS = '$$$' + - inside: + stopBy: end + kind: program + has: + stopBy: end + kind: call + pattern: require 'octokit' +rule: + any: + - kind: call + matches: Octokit::Client.new(password:"") + - kind: assignment + matches: Octokit::Client.new(password:"")with_instance diff --git a/tests/__snapshots__/ruby-octokit-hardcoded-secret-ruby-snapshot.yml b/tests/__snapshots__/ruby-octokit-hardcoded-secret-ruby-snapshot.yml new file mode 100644 index 00000000..d236a34b --- /dev/null +++ b/tests/__snapshots__/ruby-octokit-hardcoded-secret-ruby-snapshot.yml @@ -0,0 +1,270 @@ +id: ruby-octokit-hardcoded-secret-ruby +snapshots: + ? | + require 'octokit' + Octokit::Client.new(access_token: "", per_page: 100) + : labels: + - source: 'Octokit::Client.new(access_token: "", per_page: 100)' + style: primary + start: 18 + end: 90 + - source: Octokit::Client + style: secondary + start: 18 + end: 33 + - source: . + style: secondary + start: 33 + end: 34 + - source: new + style: secondary + start: 34 + end: 37 + - source: access_token + style: secondary + start: 38 + end: 50 + - source: + style: secondary + start: 53 + end: 73 + - source: '""' + style: secondary + start: 52 + end: 74 + - source: 'access_token: ""' + style: secondary + start: 38 + end: 74 + - source: '(access_token: "", per_page: 100)' + style: secondary + start: 37 + end: 90 + - source: require 'octokit' + style: secondary + start: 0 + end: 17 + - source: | + require 'octokit' + Octokit::Client.new(access_token: "", per_page: 100) + style: secondary + start: 0 + end: 91 + ? | + require 'octokit' + client = Octokit::Client.new \ + :client_id => "", + :client_secret => "" + : labels: + - source: |- + Octokit::Client.new \ + :client_id => "", + :client_secret => "" + style: primary + start: 27 + end: 129 + - source: Octokit::Client + style: secondary + start: 27 + end: 42 + - source: . + style: secondary + start: 42 + end: 43 + - source: new + style: secondary + start: 43 + end: 46 + - source: :client_secret + style: secondary + start: 88 + end: 102 + - source: + style: secondary + start: 107 + end: 128 + - source: '""' + style: secondary + start: 106 + end: 129 + - source: :client_secret => "" + style: secondary + start: 88 + end: 129 + - source: |- + :client_id => "", + :client_secret => "" + style: secondary + start: 49 + end: 129 + - source: require 'octokit' + style: secondary + start: 0 + end: 17 + - source: | + require 'octokit' + client = Octokit::Client.new \ + :client_id => "", + :client_secret => "" + style: secondary + start: 0 + end: 130 + ? | + require 'octokit' + client = Octokit::Client.new \ + :login => 'defunkt', + :password => 'c0d3b4ssssss!' + : labels: + - source: |- + Octokit::Client.new \ + :login => 'defunkt', + :password => 'c0d3b4ssssss!' + style: primary + start: 27 + end: 101 + - source: Octokit::Client + style: secondary + start: 27 + end: 42 + - source: . + style: secondary + start: 42 + end: 43 + - source: new + style: secondary + start: 43 + end: 46 + - source: :password + style: secondary + start: 73 + end: 82 + - source: c0d3b4ssssss! + style: secondary + start: 87 + end: 100 + - source: '''c0d3b4ssssss!''' + style: secondary + start: 86 + end: 101 + - source: :password => 'c0d3b4ssssss!' + style: secondary + start: 73 + end: 101 + - source: |- + :login => 'defunkt', + :password => 'c0d3b4ssssss!' + style: secondary + start: 49 + end: 101 + - source: require 'octokit' + style: secondary + start: 0 + end: 17 + - source: | + require 'octokit' + client = Octokit::Client.new \ + :login => 'defunkt', + :password => 'c0d3b4ssssss!' + style: secondary + start: 0 + end: 102 + ? | + require 'octokit' + client = Octokit::Client.new(:access_token => "") + : labels: + - source: Octokit::Client.new(:access_token => "") + style: primary + start: 27 + end: 87 + - source: Octokit::Client + style: secondary + start: 27 + end: 42 + - source: . + style: secondary + start: 42 + end: 43 + - source: new + style: secondary + start: 43 + end: 46 + - source: :access_token + style: secondary + start: 47 + end: 60 + - source: + style: secondary + start: 65 + end: 85 + - source: '""' + style: secondary + start: 64 + end: 86 + - source: :access_token => "" + style: secondary + start: 47 + end: 86 + - source: (:access_token => "") + style: secondary + start: 46 + end: 87 + - source: require 'octokit' + style: secondary + start: 0 + end: 17 + - source: | + require 'octokit' + client = Octokit::Client.new(:access_token => "") + style: secondary + start: 0 + end: 88 + ? | + require 'octokit' + client = Octokit::Client.new(:login => 'defunkt', :password => 'c0d3b4ssssss!') + : labels: + - source: Octokit::Client.new(:login => 'defunkt', :password => 'c0d3b4ssssss!') + style: primary + start: 27 + end: 97 + - source: Octokit::Client + style: secondary + start: 27 + end: 42 + - source: . + style: secondary + start: 42 + end: 43 + - source: new + style: secondary + start: 43 + end: 46 + - source: :password + style: secondary + start: 68 + end: 77 + - source: c0d3b4ssssss! + style: secondary + start: 82 + end: 95 + - source: '''c0d3b4ssssss!''' + style: secondary + start: 81 + end: 96 + - source: :password => 'c0d3b4ssssss!' + style: secondary + start: 68 + end: 96 + - source: (:login => 'defunkt', :password => 'c0d3b4ssssss!') + style: secondary + start: 46 + end: 97 + - source: require 'octokit' + style: secondary + start: 0 + end: 17 + - source: | + require 'octokit' + client = Octokit::Client.new(:login => 'defunkt', :password => 'c0d3b4ssssss!') + style: secondary + start: 0 + end: 98 diff --git a/tests/ruby/ruby-octokit-hardcoded-secret-ruby-test.yml b/tests/ruby/ruby-octokit-hardcoded-secret-ruby-test.yml new file mode 100644 index 00000000..7f899608 --- /dev/null +++ b/tests/ruby/ruby-octokit-hardcoded-secret-ruby-test.yml @@ -0,0 +1,25 @@ +id: ruby-octokit-hardcoded-secret-ruby +valid: + - | + require 'octokit' + Octokit::Client.new(access_token: token, per_page: 100) +invalid: + - | + require 'octokit' + Octokit::Client.new(access_token: "", per_page: 100) + - | + require 'octokit' + client = Octokit::Client.new \ + :client_id => "", + :client_secret => "" + - | + require 'octokit' + client = Octokit::Client.new \ + :login => 'defunkt', + :password => 'c0d3b4ssssss!' + - | + require 'octokit' + client = Octokit::Client.new(:login => 'defunkt', :password => 'c0d3b4ssssss!') + - | + require 'octokit' + client = Octokit::Client.new(:access_token => "") From 87d0093b100bc2699dffd4553523458fd7f8179b Mon Sep 17 00:00:00 2001 From: Sakshis Date: Thu, 12 Dec 2024 05:29:34 +0000 Subject: [PATCH 3/3] python-psycopg2-hardcoded-secret-python --- ...ython-psycopg2-hardcoded-secret-python.yml | 86 ++++++++++++++++++ ...copg2-hardcoded-secret-python-snapshot.yml | 87 +++++++++++++++++++ ...-psycopg2-hardcoded-secret-python-test.yml | 13 +++ 3 files changed, 186 insertions(+) create mode 100644 rules/python/security/python-psycopg2-hardcoded-secret-python.yml create mode 100644 tests/__snapshots__/python-psycopg2-hardcoded-secret-python-snapshot.yml create mode 100644 tests/python/python-psycopg2-hardcoded-secret-python-test.yml diff --git a/rules/python/security/python-psycopg2-hardcoded-secret-python.yml b/rules/python/security/python-psycopg2-hardcoded-secret-python.yml new file mode 100644 index 00000000..0aee3745 --- /dev/null +++ b/rules/python/security/python-psycopg2-hardcoded-secret-python.yml @@ -0,0 +1,86 @@ +id: python-psycopg2-hardcoded-secret-python +severity: warning +language: python +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. Use + environment variables to securely provide credentials and other secrets or + retrieve them from a secure vault or Hardware Security Module (HSM). +note: >- + [CWE-798] Use of Hard-coded Credentials. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + psycopg2.connect(..., password="",...): + kind: call + all: + - has: + stopBy: neighbor + kind: attribute + regex: ^psycopg2.connect$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^password$ + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_content + psycopg2.connect(..., password=$VAR,...)_with_instance: + kind: call + all: + - has: + stopBy: neighbor + kind: attribute + regex: ^psycopg2.connect$ + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^password$ + - has: + stopBy: neighbor + kind: identifier + pattern: $PSWD + nthChild: 2 + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $PSWD + - has: + stopBy: neighbor + kind: string + has: + stopBy: neighbor + kind: string_content +rule: + kind: call + any: + - matches: psycopg2.connect(..., password="",...) + - matches: psycopg2.connect(..., password=$VAR,...)_with_instance diff --git a/tests/__snapshots__/python-psycopg2-hardcoded-secret-python-snapshot.yml b/tests/__snapshots__/python-psycopg2-hardcoded-secret-python-snapshot.yml new file mode 100644 index 00000000..a3ac3fd5 --- /dev/null +++ b/tests/__snapshots__/python-psycopg2-hardcoded-secret-python-snapshot.yml @@ -0,0 +1,87 @@ +id: python-psycopg2-hardcoded-secret-python +snapshots: + ? | + import psycopg2 + PASSWORD = "123" + psycopg2.connect(password=PASSWORD) + : labels: + - source: psycopg2.connect(password=PASSWORD) + style: primary + start: 33 + end: 68 + - source: psycopg2.connect + style: secondary + start: 33 + end: 49 + - source: password + style: secondary + start: 50 + end: 58 + - source: PASSWORD + style: secondary + start: 59 + end: 67 + - source: password=PASSWORD + style: secondary + start: 50 + end: 67 + - source: (password=PASSWORD) + style: secondary + start: 49 + end: 68 + - source: PASSWORD + style: secondary + start: 16 + end: 24 + - source: '123' + style: secondary + start: 28 + end: 31 + - source: '"123"' + style: secondary + start: 27 + end: 32 + - source: PASSWORD = "123" + style: secondary + start: 16 + end: 32 + - source: PASSWORD = "123" + style: secondary + start: 16 + end: 32 + - source: psycopg2.connect(password=PASSWORD) + style: secondary + start: 33 + end: 68 + ? | + import psycopg2 + psycopg2.connect(password="PASSWORD") + : labels: + - source: psycopg2.connect(password="PASSWORD") + style: primary + start: 16 + end: 53 + - source: psycopg2.connect + style: secondary + start: 16 + end: 32 + - source: password + style: secondary + start: 33 + end: 41 + - source: PASSWORD + style: secondary + start: 43 + end: 51 + - source: '"PASSWORD"' + style: secondary + start: 42 + end: 52 + - source: password="PASSWORD" + style: secondary + start: 33 + end: 52 + - source: (password="PASSWORD") + style: secondary + start: 32 + end: 53 diff --git a/tests/python/python-psycopg2-hardcoded-secret-python-test.yml b/tests/python/python-psycopg2-hardcoded-secret-python-test.yml new file mode 100644 index 00000000..487f150a --- /dev/null +++ b/tests/python/python-psycopg2-hardcoded-secret-python-test.yml @@ -0,0 +1,13 @@ +id: python-psycopg2-hardcoded-secret-python +valid: + - | + import psycopg2 + psycopg2.connect(password=PASSWORD) +invalid: + - | + import psycopg2 + PASSWORD = "123" + psycopg2.connect(password=PASSWORD) + - | + import psycopg2 + psycopg2.connect(password="PASSWORD")