Skip to content

Commit d584a71

Browse files
justineysterXianjun Zhu
authored and
Xianjun Zhu
committed
SoftLayerDetector (Yelp#169)
* SoftLayerDetector Detects Softlayer API Keys Supports git-defenders/detect-secrets-discuss#120 * Lines were too long * Address PR comments 1 * Address PR comments 2
1 parent 5706eb1 commit d584a71

File tree

2 files changed

+116
-0
lines changed

2 files changed

+116
-0
lines changed

Diff for: softlayer.py

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from __future__ import absolute_import
2+
3+
import re
4+
5+
from .base import RegexBasedDetector
6+
7+
8+
class SoftLayerDetector(RegexBasedDetector):
9+
10+
secret_type = 'SoftLayer Credentials'
11+
12+
# opt means optional
13+
opt_quote = r'(?:"|)'
14+
opt_dashes = r'(?:--|)'
15+
sl = r'(?:softlayer|sl)'
16+
opt_dash_undrscr = r'(?:_|-|)'
17+
opt_api = r'(?:api|)'
18+
key = r'key'
19+
opt_space = r'(?: |)'
20+
opt_equals = r'(?:=|:|:=|)'
21+
secret = r'([a-z0-9]{64})'
22+
denylist = [
23+
re.compile(
24+
r'{opt_quote}{opt_dashes}{sl}{opt_dash_undrscr}{opt_api}{opt_dash_undrscr}{key}'
25+
'{opt_quote}{opt_space}{opt_equals}{opt_space}{opt_quote}{secret}{opt_quote}'.format(
26+
opt_quote=opt_quote,
27+
opt_dashes=opt_dashes,
28+
sl=sl,
29+
opt_dash_undrscr=opt_dash_undrscr,
30+
opt_api=opt_api,
31+
key=key,
32+
opt_space=opt_space,
33+
opt_equals=opt_equals,
34+
secret=secret,
35+
), flags=re.IGNORECASE,
36+
),
37+
re.compile(
38+
r'(?:http|https)://api.softlayer.com/soap/(?:v3|v3.1)/([a-z0-9]{64})',
39+
flags=re.IGNORECASE,
40+
),
41+
]

Diff for: softlayer_test.py

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
from __future__ import absolute_import
2+
3+
import pytest
4+
5+
from detect_secrets.plugins.softlayer import SoftLayerDetector
6+
7+
8+
class TestSoftLayerDetector(object):
9+
10+
sl_token = 'abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234'
11+
12+
@pytest.mark.parametrize(
13+
'payload, should_flag',
14+
[
15+
('--softlayer-api-key "{sl_token}"'.format(sl_token=sl_token), True,),
16+
('--softlayer-api-key="{sl_token}"'.format(sl_token=sl_token), True,),
17+
('--softlayer-api-key {sl_token}'.format(sl_token=sl_token), True,),
18+
('--softlayer-api-key={sl_token}'.format(sl_token=sl_token), True,),
19+
('http://api.softlayer.com/soap/v3/{sl_token}'.format(sl_token=sl_token), True,),
20+
('http://api.softlayer.com/soap/v3.1/{sl_token}'.format(sl_token=sl_token), True,),
21+
('softlayer_api_key: {sl_token}'.format(sl_token=sl_token), True,),
22+
('softlayer-key : {sl_token}'.format(sl_token=sl_token), True,),
23+
('SOFTLAYER-API-KEY : "{sl_token}"'.format(sl_token=sl_token), True,),
24+
('"softlayer_api_key" : "{sl_token}"'.format(sl_token=sl_token), True,),
25+
('softlayer-api-key: "{sl_token}"'.format(sl_token=sl_token), True,),
26+
('"softlayer_api_key": "{sl_token}"'.format(sl_token=sl_token), True,),
27+
('SOFTLAYER_API_KEY:"{sl_token}"'.format(sl_token=sl_token), True,),
28+
('softlayer-key:{sl_token}'.format(sl_token=sl_token), True,),
29+
('softlayer_key:"{sl_token}"'.format(sl_token=sl_token), True,),
30+
('"softlayer_api_key":"{sl_token}"'.format(sl_token=sl_token), True,),
31+
('softlayerapikey= {sl_token}'.format(sl_token=sl_token), True,),
32+
('softlayer_api_key= "{sl_token}"'.format(sl_token=sl_token), True,),
33+
('SOFTLAYERAPIKEY={sl_token}'.format(sl_token=sl_token), True,),
34+
('softlayer_api_key="{sl_token}"'.format(sl_token=sl_token), True,),
35+
('sl_api_key: {sl_token}'.format(sl_token=sl_token), True,),
36+
('SLAPIKEY : {sl_token}'.format(sl_token=sl_token), True,),
37+
('sl_apikey : "{sl_token}"'.format(sl_token=sl_token), True,),
38+
('"sl_api_key" : "{sl_token}"'.format(sl_token=sl_token), True,),
39+
('sl-key: "{sl_token}"'.format(sl_token=sl_token), True,),
40+
('"sl_api_key": "{sl_token}"'.format(sl_token=sl_token), True,),
41+
('sl_api_key:"{sl_token}"'.format(sl_token=sl_token), True,),
42+
('sl_api_key:{sl_token}'.format(sl_token=sl_token), True,),
43+
('sl-api-key:"{sl_token}"'.format(sl_token=sl_token), True,),
44+
('"sl_api_key":"{sl_token}"'.format(sl_token=sl_token), True,),
45+
('sl_key= {sl_token}'.format(sl_token=sl_token), True,),
46+
('sl_api_key= "{sl_token}"'.format(sl_token=sl_token), True,),
47+
('sl-api-key={sl_token}'.format(sl_token=sl_token), True,),
48+
('slapi_key="{sl_token}"'.format(sl_token=sl_token), True,),
49+
('slapikey:= {sl_token}'.format(sl_token=sl_token), True,),
50+
('softlayer_api_key := {sl_token}'.format(sl_token=sl_token), True,),
51+
('sl_api_key := "{sl_token}"'.format(sl_token=sl_token), True,),
52+
('"softlayer_key" := "{sl_token}"'.format(sl_token=sl_token), True,),
53+
('sl_api_key: "{sl_token}"'.format(sl_token=sl_token), True,),
54+
('"softlayer_api_key":= "{sl_token}"'.format(sl_token=sl_token), True,),
55+
('sl-api-key:="{sl_token}"'.format(sl_token=sl_token), True,),
56+
('softlayer_api_key:={sl_token}'.format(sl_token=sl_token), True,),
57+
('slapikey:"{sl_token}"'.format(sl_token=sl_token), True,),
58+
('"softlayer_api_key":="{sl_token}"'.format(sl_token=sl_token), True,),
59+
('sl-api-key:= {sl_token}'.format(sl_token=sl_token), True,),
60+
('softlayer_key:= "{sl_token}"'.format(sl_token=sl_token), True,),
61+
('sl_api_key={sl_token}'.format(sl_token=sl_token), True),
62+
('softlayer_api_key:="{sl_token}"'.format(sl_token=sl_token), True),
63+
('softlayer_api_key="%s" % SL_API_KEY_ENV', False),
64+
('sl_api_key: "%s" % <softlayer_api_key>', False),
65+
('SOFTLAYER_APIKEY: "insert_key_here"', False),
66+
('sl-apikey: "insert_key_here"', False),
67+
('softlayer-key:=afakekey', False),
68+
('fake-softlayer-key= "not_long_enough"', False),
69+
],
70+
)
71+
def test_analyze_string(self, payload, should_flag):
72+
logic = SoftLayerDetector()
73+
74+
output = logic.analyze_string(payload, 1, 'mock_filename')
75+
assert len(output) == (1 if should_flag else 0)

0 commit comments

Comments
 (0)