-
Notifications
You must be signed in to change notification settings - Fork 482
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
Add Detector for Softlayer tokens #254
Add Detector for Softlayer tokens #254
Conversation
* SoftLayerDetector Detects Softlayer API Keys Supports git-defenders/detect-secrets-discuss#120 * Lines were too long * Address PR comments 1 * Address PR comments 2
* Strengthen SoftLayer regex by including "password" keywords Noticed the legacy crawler searched for the words `password`, `pwd`, `pass` in addition to `key`. Adapted our solution to follow. * Var name update * Add additional assign operator from crawler, too
* get_username function * Adapt regex * Add username regex * Complete 'get_username()' function * Softlayer verify function * First attempt at tests * Finished writing tests * Address @edwarj2 PR comments * Address PR comments 1 * Address PR comments 2 * Address PR comments 3 * Valid if status_code=200
* feat: use assign regex in cloudant * feat: use assign regex in db2 * feat: use assign regex in gh * feat: use assign regex in iam * feat: use assign regex in sl * address comments * address comments * address comments
0378f90
to
8b8b9d7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the late review 👍
begin = r'(?:(?<=\W)|(?<=^))' | ||
opt_quote = r'(?:"|\'|)' | ||
opt_open_square_bracket = r'(?:\[|)' | ||
opt_close_square_bracket = r'(?:\]|)' | ||
opt_dash_undrscr = r'(?:_|-|)' | ||
opt_space = r'(?: *)' | ||
assignment = r'(?:=|:|:=|=>| +|::)' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++, great use of non-capturing groups! (https://stackoverflow.com/questions/3512471/what-is-a-non-capturing-group-in-regular-expressions)
I should refactor some of our existing code to use those
detect_secrets/plugins/base.py
Outdated
@staticmethod | ||
def assign_regex_generator(prefix_regex, password_keyword_regex, password_regex): | ||
"""Generate assignment regex | ||
It read 3 input parameters, each stands for regex. The return regex would look for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It read 3 input parameters, each stands for regex. The return regex would look for | |
It reads 3 input parameters, each stands for regex. The return regex would look for |
detect_secrets/plugins/base.py
Outdated
@@ -260,6 +260,39 @@ class FooDetector(RegexBasedDetector): | |||
def denylist(self): | |||
raise NotImplementedError | |||
|
|||
@staticmethod | |||
def assign_regex_generator(prefix_regex, password_keyword_regex, password_regex): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nit: Maybe a more genericized naming could be keyword_regex
(/secret_keyword_regex
) and secret_regex
, for cases like e.g. password_regex=username
vs. secret_regex=username
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I renamed password_keyword_regex
-> secret_keyword_regex
, password_regex
-> secret_regex
. I have left out the prefix_regex
. Let me know if that's what you mean.
detect_secrets/plugins/softlayer.py
Outdated
def find_username(content): | ||
# opt means optional | ||
username_keyword = r'(?:username|id|user|userid|user-id|user-name|' + \ | ||
r'name|user_id|user_name|uname)' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
r'name|user_id|user_name|uname)' | |
r'(?:' | |
r'username|id|user|userid|user-id|user-name|' | |
r'name|user_id|user_name|uname' | |
r')' | |
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, GitHub suggestions merged my line 46 and 47 suggestions :/ Mainly meant to say I prefer parenthesis over Oh wait never mind, it is below.\
, feel free to ignore though.
detect_secrets/plugins/softlayer.py
Outdated
|
||
def find_username(content): | ||
# opt means optional | ||
username_keyword = r'(?:username|id|user|userid|user-id|user-name|' + \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
username_keyword = r'(?:username|id|user|userid|user-id|user-name|' + \ | |
username_keyword = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Nit: Just like to do ()
over \
, other people don't, feel free to ignore.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using ()
looks good. I will update.
detect_secrets/plugins/softlayer.py
Outdated
return VerifiedResult.VERIFIED_TRUE | ||
else: | ||
return VerifiedResult.VERIFIED_FALSE | ||
except Exception: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can make this more specific, like a tuple of specific exceptions the requests.get
call can throw, or just requests.exceptions.RequestException
. (Up to you if you want to try retrying on e.g. requests.exceptions.Timeout
)
To improve readability, since other lines won't raise exceptions, maybe we can only wrap the requests.get
call with try/except
.
For posterity, this made me think about if we want to do this for other plugins like Slack Stripe etc. 🤔 , I think I'm okay with, on the off-chance the Slack API is down when someone runs detect-secrets
, that they get an exception and try running d-s later. (or having the user knowingly choose --no-verify, if the API is down). Just so there are not verifiability false-negatives in very rare cases.
On the other hand, we may have horrible luck if one hard-coded endpoint in d-s changes and always causes a requests exception, I'm kind of okay with taking that risk as it seems quite unlikely things wouldn't just 404 in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
call can throw, or just requests.exceptions.RequestException.
Good point.
(Up to you if you want to try retrying on e.g. requests.exceptions.Timeout)
I will leave retry out.
For posterity, this made me think about if we want to do this for other plugins like Slack Stripe etc
Wrapping some exception would be necessary, otherwise with current code, if Slack, Stripe or AWS verification endpoint is down or unreachable for whatever reason, we will throw exception instead of gracefully report unverified. As you said, it can force user to use --no-verify
to keep using d-s.
requirements-dev.txt
Outdated
@@ -9,3 +9,4 @@ pyyaml | |||
tox>=3.8 | |||
tox-pip-extensions | |||
unidiff | |||
responses |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe put after pyyaml
to keep the requirements alphabetical.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted.
), | ||
), | ||
) | ||
def test_find_username(self, content, expected_output): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just in case you find that this type of secret is used in function calls, the following commit may help you add detection for that. (Code still in review -- c6037d9)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestions. @KevinHock. Unlike AWS tokens which has a specific format, the Softlayer username here is almost free format. It might be hard to match them in function calls. I will prefer to leave them out for now.
@KevinHock all comments addressed. |
Add Detector for Softlayer tokens, it supports looking for 2 factors: username and password. It also supports verification.