Skip to content
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 whitelist directive regexes to match against inline comment syntaxes in more languages #105

Merged
merged 5 commits into from
Dec 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 9 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ either the client-side pre-commit hook, or the server-side secret scanner.
3. **Secrets Baseline**, to whitelist pre-existing secrets in the repository,
so that they won't be continuously caught through scan iterations.

### Client-side Pre-commit Hook
### Client-side `pre-commit` Hook

See [pre-commit](https://github.com/pre-commit/pre-commit) for instructions
to install the pre-commit framework. The example usage above has a sample
Expand All @@ -119,26 +119,21 @@ as your pre-commit hook, and server-side secret scanner!

#### Inline Whitelisting

Another way of whitelisting secrets is through the inline comment
`# pragma: whitelist secret`.

For example:
To tell `detect-secrets` to ignore a particular line of code, simply append an
inline `pragma: whitelist secret` comment. For example:

```python
API_KEY = "blah-blah-but-actually-not-secret" # pragma: whitelist secret
print('hello world')
```
API_KEY = "blah-blah-but-actually-not-secret" # pragma: whitelist secret

def main():
print('hello world')

if __name__ == '__main__'
main()
```
Inline commenting syntax for a multitude of languages is supported.

This may be a convenient way for you to whitelist secrets, without having to
regenerate the entire baseline again. Furthermore, this makes the whitelisted
secrets easily searchable, auditable, and maintainable.

## Current Supported Plugins
## Currently Supported Plugins

The current heuristic searches we implement out of the box include:

Expand All @@ -158,7 +153,7 @@ See [detect_secrets/
plugins](https://github.com/Yelp/detect-secrets/tree/master/detect_secrets/plugins)
for more details.

## A Few Caveats
## Caveats

This is not meant to be a sure-fire solution to prevent secrets from entering
the codebase. Only proper developer education can truly do that. This pre-commit
Expand Down
4 changes: 2 additions & 2 deletions detect_secrets/plugins/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from abc import abstractproperty

from detect_secrets.core.potential_secret import PotentialSecret
from detect_secrets.plugins.core.constants import WHITELIST_REGEX
from detect_secrets.plugins.core.constants import WHITELIST_REGEXES


class BasePlugin(object):
Expand All @@ -27,7 +27,7 @@ def analyze(self, file, filename):
"""
potential_secrets = {}
for line_num, line in enumerate(file.readlines(), start=1):
if WHITELIST_REGEX.search(line):
if any(regex.search(line) for regex in WHITELIST_REGEXES):
continue
secrets = self.analyze_string(line, line_num, filename)
potential_secrets.update(secrets)
Expand Down
17 changes: 15 additions & 2 deletions detect_secrets/plugins/core/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
import re

# TODO: Update for not just python comments?
WHITELIST_REGEX = re.compile(r'# ?pragma: ?whitelist[ -]secret')
WHITELIST_REGEXES = [
re.compile(r)
for r in [
r'[ \t]+{} ?pragma: ?whitelist[ -]secret{}[ \t]*$'.format(start, end)
for start, end in (
('#', ''), # e.g. python
('//', ''), # e.g. golang
(r'/\*', r' ?\*/'), # e.g. c
('\'', ''), # e.g. visual basic .net
('--', ''), # e.g. sql
# many other inline comment syntaxes are not included,
# because we want to be performant for the common case
)
]
]
4 changes: 2 additions & 2 deletions detect_secrets/plugins/core/yaml_file_parser.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import yaml

from detect_secrets.plugins.core.constants import WHITELIST_REGEX
from detect_secrets.plugins.core.constants import WHITELIST_REGEXES


class YamlFileParser(object):
Expand Down Expand Up @@ -127,7 +127,7 @@ def get_ignored_lines(self):
ignored_lines = set()

for line_number, line in enumerate(self.content.split('\n'), 1):
if WHITELIST_REGEX.search(line):
if any(regex.search(line) for regex in WHITELIST_REGEXES):
ignored_lines.add(line_number)

return ignored_lines
4 changes: 0 additions & 4 deletions detect_secrets/plugins/high_entropy_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

from .base import BasePlugin
from detect_secrets.core.potential_secret import PotentialSecret
from detect_secrets.plugins.core.constants import WHITELIST_REGEX
from detect_secrets.plugins.core.ini_file_parser import IniFileParser
from detect_secrets.plugins.core.yaml_file_parser import YamlFileParser

Expand Down Expand Up @@ -96,9 +95,6 @@ def analyze_string(self, string, line_num, filename):
"""
output = {}

if WHITELIST_REGEX.search(string):
return output

for result in self.secret_generator(string):
if self.is_sequential_string(result):
continue
Expand Down
4 changes: 2 additions & 2 deletions detect_secrets/pre_commit_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def pretty_print_diagnostics(secrets):
def _print_warning_header():
message = (
'Potential secrets about to be committed to git repo! Please rectify '
'or explicitly ignore with `pragma: whitelist secret` comment.'
'or explicitly ignore with an inline `pragma: whitelist secret` comment.'
)

log.error(textwrap.fill(message))
Expand All @@ -191,7 +191,7 @@ def _print_secrets_found(secrets):
def _print_mitigation_suggestions():
suggestions = [
'For information about putting your secrets in a safer place, please ask in #security',
'Mark false positives with `# pragma: whitelist secret`',
'Mark false positives with an inline `pragma: whitelist secret` comment',
'Commit with `--no-verify` if this is a one-time false positive',
]

Expand Down
7 changes: 5 additions & 2 deletions tests/plugins/high_entropy_strings_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,11 @@ def test_analyze_multiple_strings_same_line(self, content_to_format, expected_re
'content_to_format',
[
# Test inline annotation for whitelisting
"'{secret}' # pragma: whitelist secret",

"'{secret}' # pragma: whitelist secret",
"'{secret}' // pragma: whitelist secret",
"'{secret}' /* pragma: whitelist secret */",
"'{secret}' ' pragma: whitelist secret",
"'{secret}' -- pragma: whitelist secret",
# Not a string
"{secret}",
],
Expand Down