Fix check bypass via square brackets Issue #857#860
Fix check bypass via square brackets Issue #857#860tsigouris007 wants to merge 2 commits intoYelp:masterfrom
Conversation
lorenzodb1
left a comment
There was a problem hiding this comment.
Hi @tsigouris007, thank you for your PR!
Could you explain what the bug was?
Hi, |
|
Hi @tsigouris007, #857 describes the issue, I was looking for an explanation around what's causing said issue in the code |
I haven't quite had the time to find the exact location that brakes this. For example I got I am taking wild a guess here and I most probably think the problem is how the checked file lines are fetched (and that's why I thought of "escaping" the square brackets earlier). if _is_filtered_out(
required_filter_parameters=['line'],
filename=filename,
line=line,
context=code_snippet,
):If you remove it or add a I can take a closer look but it will take me at least a couple of days. |
|
Understanding what exactly is causing the bug will help us finding a good solution moving forward rather than a workaround that could potentially add another set of issues, hence why I'm asking this. Take your time and please let me know what you'll find! |
It's understandable. |
|
Hi @lorenzodb1 , return re.compile(r'([^\v=!:]*)\s*(:=?|[!=]{1,3})\s*([\w.-]+[\[\(][^\v]*[\]\)])')So the choice is to either change this regex a bit or escape earlier the square brackets. def is_indirect_reference(line: str) -> bool:
"""
Filters secrets that take the form of:
secret = get_secret_key()
or
secret = request.headers['apikey']
"""
# Constrain line length as the heuristic's intention is to target lines that resemble
# function calls. The constraint avoids catastrophic backtracking failures of the regex.
if len(line) > 1000:
return False
line = line.replace('[', '\[').replace(']', '\]')
return bool(_get_indirect_reference_regex().search(line))This produces the correct results. After playing around with the regex I came up with the following that seems to be working (tested on a huge repo with ~1.2k secrets): def _get_indirect_reference_regex() -> Pattern:
# Regex details:
# ([^\v=!:]*) -> Something before the assignment or comparison
# \s* -> Some optional whitespaces
# (:=?|[!=]{1,3}) -> Assignment or comparison: :=, =, ==, ===, !=, !==
# \s* -> Some optional whitespaces
# (
# [\w.-]+ -> Some alphanumeric character, dot or -
# [\[\(] -> Start of indirect reference: [ or (
# [^\v]* -> Something except line breaks
# [\]\)] -> End of indirect reference: ] or )
# )
# return re.compile(r'([^\v=!:]*)\s*(:=?|[!=]{1,3})\s*([\w.-]+[\[\(][^\v]*[\]\)])') # Left the old one for reference
return re.compile(r'([^\v=!:"<%>]*)\s*(:=?|[!=]{1,3})\s*([\w.-]+[\[\(][^\v]*[\]\)])')How do you want to go through with this? |
|
Hi @tsigouris007, sorry for the delay in replying. I personally prefer the second option. Thanks for investigating this and coming up with a solution! |
f5be7c0 to
23e5097
Compare
Hi @lorenzodb1 , |
| # [\]\)] -> End of indirect reference: ] or ) | ||
| # ) | ||
| return re.compile(r'([^\v=!:]*)\s*(:=?|[!=]{1,3})\s*([\w.-]+[\[\(][^\v]*[\]\)])') | ||
| return re.compile(r'([^\v=!:"<%>]*)\s*(:=?|[!=]{1,3})\s*([\w.-]+[\[\(][^\v]*[\]\)])') |
There was a problem hiding this comment.
@tsigouris007 could you add a test for this change?
There was a problem hiding this comment.
Sorry for the delay.
I added two test cases for this change.
Are we good to go?
There was a problem hiding this comment.
Isn't that what you were trying to fix with this PR?
There was a problem hiding this comment.
I was catching the first case as that was my initial issue as described above.
So, I beefed up the regex and now it catches both cases (broke it in multiple lines for readability, it's not that far from the original one).
I also added a few more test cases that should be caught following this logic and added a brief explanation for each case.
Let me know if this works for you now.
b7c79e0 to
c4210a1
Compare
|
Hi @lorenzodb1 , |
|
Hi @tsigouris007, I'm sorry for the late reply. I'm no longer involved in this project as a maintainer, but I'll tag @jpdakran so he can take a look when it's most convenient for him. Changes do lgtm anyway 👍🏼 |
Thank you very much! |
c4210a1 to
74b7a92
Compare
Docs have been added / updatedFixes behavior on missed secrets that have square brackets before their default value.
Example:
Issue: #857
Escapes the square brackets and catches secrets properly.
No breaking changes.