检测代码库中秘密的工具
项目描述
detect-secrets
关于
detect-secrets
是一个名字恰当的模块,用于(不出所料)在代码库中检测秘密。
然而,与其他仅关注查找秘密的类似包不同,这个包是针对企业客户设计的:提供一个 向下兼容 的、系统的
- 防止新秘密进入代码库的方法,
- 检测这些预防措施是否被明确绕过,
- 并提供一个秘密清单,以便滚动和迁移到一个更安全的存储。
这种方式,您可以创建一个关注点分离:接受在您的大型仓库中可能隐藏着秘密(这就是我们所说的基线),但防止这个问题变得更大,而不必处理将现有秘密移动开来的潜在巨大工作量。
它通过运行周期性的diff输出与启发式正则表达式语句,来识别是否有任何新的秘密被提交。这样,它避免了挖掘所有git历史的开销,以及每次都需要扫描整个仓库的需要。
有关最近更改的详细信息,请参阅CHANGELOG.md。
如果您想贡献,请参阅CONTRIBUTING.md。
有关更详细的文档,请参阅我们的其他文档。
示例
快速入门
创建一个基线,其中包含您git仓库中当前发现的潜在秘密。
$ detect-secrets scan > .secrets.baseline
或者,从不同的目录运行
$ detect-secrets -C /path/to/directory scan > /path/to/directory/.secrets.baseline
扫描非git跟踪文件
$ detect-secrets scan test_data/ --all-files > .secrets.baseline
将新秘密添加到基线
这将重新扫描您的代码库,并
- 更新/升级您的基线以兼容最新版本,
- 将找到的新秘密添加到基线,
- 删除不再在您的代码库中的秘密
这还将保留您标记的秘密。
$ detect-secrets scan --baseline .secrets.baseline
对于版本低于0.9的基线,只需重新创建即可。
对新增秘密进行警报
仅扫描暂存文件
$ git diff --staged --name-only -z | xargs -0 detect-secrets-hook --baseline .secrets.baseline
扫描所有跟踪文件
$ git ls-files -z | xargs -0 detect-secrets-hook --baseline .secrets.baseline
查看所有启用的插件
$ detect-secrets scan --list-all-plugins
ArtifactoryDetector
AWSKeyDetector
AzureStorageKeyDetector
BasicAuthDetector
CloudantDetector
DiscordBotTokenDetector
GitHubTokenDetector
GitLabTokenDetector
Base64HighEntropyString
HexHighEntropyString
IbmCloudIamDetector
IbmCosHmacDetector
IPPublicDetector
JwtTokenDetector
KeywordDetector
MailchimpDetector
NpmDetector
OpenAIDetector
PrivateKeyDetector
PypiTokenDetector
SendGridDetector
SlackDetector
SoftlayerDetector
SquareOAuthDetector
StripeDetector
TelegramBotTokenDetector
TwilioKeyDetector
禁用插件
$ detect-secrets scan --disable-plugin KeywordDetector --disable-plugin AWSKeyDetector
如果您只想运行特定的插件,可以这样操作
$ detect-secrets scan --list-all-plugins | \
grep -v 'BasicAuthDetector' | \
sed "s#^#--disable-plugin #g" | \
xargs detect-secrets scan test_data
审计基线
这是一个可选步骤,用于标记基线中的结果。它可以用来缩小需要迁移的秘密清单,或者更好地配置插件以提高其信噪比。
$ detect-secrets audit .secrets.baseline
在其他Python脚本中的使用
基本使用
from detect_secrets import SecretsCollection
from detect_secrets.settings import default_settings
secrets = SecretsCollection()
with default_settings():
secrets.scan_file('test_data/config.ini')
import json
print(json.dumps(secrets.json(), indent=2))
更高级的配置
from detect_secrets import SecretsCollection
from detect_secrets.settings import transient_settings
secrets = SecretsCollection()
with transient_settings({
# Only run scans with only these plugins.
# This format is the same as the one that is saved in the generated baseline.
'plugins_used': [
# Example of configuring a built-in plugin
{
'name': 'Base64HighEntropyString',
'limit': 5.0,
},
# Example of using a custom plugin
{
'name': 'HippoDetector',
'path': 'file:///Users/aaronloo/Documents/github/detect-secrets/testing/plugins.py',
},
],
# We can also specify whichever additional filters we want.
# This is an example of using the function `is_identified_by_ML_model` within the
# local file `./private-filters/example.py`.
'filters_used': [
{
'path': 'file://private-filters/example.py::is_identified_by_ML_model',
},
]
}) as settings:
# If we want to make any further adjustments to the created settings object (e.g.
# disabling default filters), we can do so as such.
settings.disable_filters(
'detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign',
'detect_secrets.filters.heuristic.is_likely_id_string',
)
secrets.scan_file('test_data/config.ini')
安装
$ pip install detect-secrets
✨🍰✨
通过brew安装
$ brew install detect-secrets
使用
detect-secrets
附带三个不同的工具,通常在使用上会有混淆。使用这个方便的清单可以帮助您决定
- 您想将秘密添加到基线吗?如果是这样,请使用
detect-secrets scan
。 - 您想对基线之外的新的秘密进行警报吗?如果是这样,请使用
detect-secrets-hook
。 - 您正在分析基线本身吗?如果是这样,请使用
detect-secrets audit
。
将秘密添加到基线
$ detect-secrets scan --help
usage: detect-secrets scan [-h] [--string [STRING]] [--only-allowlisted]
[--all-files] [--baseline FILENAME]
[--force-use-all-plugins] [--slim]
[--list-all-plugins] [-p PLUGIN]
[--base64-limit [BASE64_LIMIT]]
[--hex-limit [HEX_LIMIT]]
[--disable-plugin DISABLE_PLUGIN]
[-n | --only-verified]
[--exclude-lines EXCLUDE_LINES]
[--exclude-files EXCLUDE_FILES]
[--exclude-secrets EXCLUDE_SECRETS]
[--word-list WORD_LIST_FILE] [-f FILTER]
[--disable-filter DISABLE_FILTER]
[path [path ...]]
Scans a repository for secrets in code. The generated output is compatible
with `detect-secrets-hook --baseline`.
positional arguments:
path Scans the entire codebase and outputs a snapshot of
currently identified secrets.
optional arguments:
-h, --help show this help message and exit
--string [STRING] Scans an individual string, and displays configured
plugins' verdict.
--only-allowlisted Only scans the lines that are flagged with `allowlist
secret`. This helps verify that individual exceptions
are indeed non-secrets.
scan options:
--all-files Scan all files recursively (as compared to only
scanning git tracked files).
--baseline FILENAME If provided, will update existing baseline by
importing settings from it.
--force-use-all-plugins
If a baseline is provided, detect-secrets will default
to loading the plugins specified by that baseline.
However, this may also mean it doesn't perform the
scan with the latest plugins. If this flag is
provided, it will always use the latest plugins
--slim Slim baselines are created with the intention of
minimizing differences between commits. However, they
are not compatible with the `audit` functionality, and
slim baselines will need to be remade to be audited.
plugin options:
Configure settings for each secret scanning ruleset. By default, all
plugins are enabled unless explicitly disabled.
--list-all-plugins Lists all plugins that will be used for the scan.
-p PLUGIN, --plugin PLUGIN
Specify path to custom secret detector plugin.
--base64-limit [BASE64_LIMIT]
Sets the entropy limit for high entropy strings. Value
must be between 0.0 and 8.0, defaults to 4.5.
--hex-limit [HEX_LIMIT]
Sets the entropy limit for high entropy strings. Value
must be between 0.0 and 8.0, defaults to 3.0.
--disable-plugin DISABLE_PLUGIN
Plugin class names to disable. e.g.
Base64HighEntropyString
filter options:
Configure settings for filtering out secrets after they are flagged by the
engine.
-n, --no-verify Disables additional verification of secrets via
network call.
--only-verified Only flags secrets that can be verified.
--exclude-lines EXCLUDE_LINES
If lines match this regex, it will be ignored.
--exclude-files EXCLUDE_FILES
If filenames match this regex, it will be ignored.
--exclude-secrets EXCLUDE_SECRETS
If secrets match this regex, it will be ignored.
--word-list WORD_LIST_FILE
Text file with a list of words, if a secret contains a
word in the list we ignore it.
-f FILTER, --filter FILTER
Specify path to custom filter. May be a python module
path (e.g.
detect_secrets.filters.common.is_invalid_file) or a
local file path (e.g.
file://path/to/file.py::function_name).
--disable-filter DISABLE_FILTER
Specify filter to disable. e.g.
detect_secrets.filters.common.is_invalid_file
阻止基线之外的秘密
$ detect-secrets-hook --help
usage: detect-secrets-hook [-h] [-v] [--version] [--baseline FILENAME]
[--list-all-plugins] [-p PLUGIN]
[--base64-limit [BASE64_LIMIT]]
[--hex-limit [HEX_LIMIT]]
[--disable-plugin DISABLE_PLUGIN]
[-n | --only-verified]
[--exclude-lines EXCLUDE_LINES]
[--exclude-files EXCLUDE_FILES]
[--exclude-secrets EXCLUDE_SECRETS]
[--word-list WORD_LIST_FILE] [-f FILTER]
[--disable-filter DISABLE_FILTER]
[filenames [filenames ...]]
positional arguments:
filenames Filenames to check.
optional arguments:
-h, --help show this help message and exit
-v, --verbose Verbose mode.
--version Display version information.
--json Print detect-secrets-hook output as JSON
--baseline FILENAME Explicitly ignore secrets through a baseline generated
by `detect-secrets scan`
plugin options:
Configure settings for each secret scanning ruleset. By default, all
plugins are enabled unless explicitly disabled.
--list-all-plugins Lists all plugins that will be used for the scan.
-p PLUGIN, --plugin PLUGIN
Specify path to custom secret detector plugin.
--base64-limit [BASE64_LIMIT]
Sets the entropy limit for high entropy strings. Value
must be between 0.0 and 8.0, defaults to 4.5.
--hex-limit [HEX_LIMIT]
Sets the entropy limit for high entropy strings. Value
must be between 0.0 and 8.0, defaults to 3.0.
--disable-plugin DISABLE_PLUGIN
Plugin class names to disable. e.g.
Base64HighEntropyString
filter options:
Configure settings for filtering out secrets after they are flagged by the
engine.
-n, --no-verify Disables additional verification of secrets via
network call.
--only-verified Only flags secrets that can be verified.
--exclude-lines EXCLUDE_LINES
If lines match this regex, it will be ignored.
--exclude-files EXCLUDE_FILES
If filenames match this regex, it will be ignored.
--exclude-secrets EXCLUDE_SECRETS
If secrets match this regex, it will be ignored.
-f FILTER, --filter FILTER
Specify path to custom filter. May be a python module
path (e.g.
detect_secrets.filters.common.is_invalid_file) or a
local file path (e.g.
file://path/to/file.py::function_name).
--disable-filter DISABLE_FILTER
Specify filter to disable. e.g.
detect_secrets.filters.common.is_invalid_file
我们建议将其设置为预提交钩子。一种方法是使用pre-commit框架
# .pre-commit-config.yaml
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']
exclude: package.lock.json
内联允许列表
有时我们希望排除误报以阻止提交,而不创建基线来这样做。您可以通过添加如下注释来完成此操作
secret = "hunter2" # pragma: allowlist secret
或者
// pragma: allowlist nextline secret
const secret = "hunter2";
审计基线中的秘密
$ detect-secrets audit --help
usage: detect-secrets audit [-h] [--diff] [--stats]
[--report] [--only-real | --only-false]
[--json]
filename [filename ...]
Auditing a baseline allows analysts to label results, and optimize plugins for
the highest signal-to-noise ratio for their environment.
positional arguments:
filename Audit a given baseline file to distinguish the difference
between false and true positives.
optional arguments:
-h, --help show this help message and exit
--diff Allows the comparison of two baseline files, in order to
effectively distinguish the difference between various plugin
configurations.
--stats Displays the results of an interactive auditing session which
have been saved to a baseline file.
--report Displays a report with the secrets detected
reporting:
Display a summary with all the findings and the made decisions. To be used with the report mode (--report).
--only-real Only includes real secrets in the report
--only-false Only includes false positives in the report
analytics:
Quantify the success of your plugins based on the labelled results in your
baseline. To be used with the statistics mode (--stats).
--json Outputs results in a machine-readable format.
配置
此工具通过一套插件和过滤器系统来运行。
- 插件在代码中查找秘密
- 过滤器忽略误报以增加扫描精度
您可以根据精度/召回率需求调整这两者。
插件
我们采用了三种不同的策略来尝试在代码中找到秘密
-
基于正则表达式的规则
这是最常见的插件类型,与结构良好的秘密配合良好。这些秘密可以选择性地进行验证,这会增加扫描精度。然而,仅依赖于这些可能会对您扫描的召回率产生负面影响。
-
熵检测器
这通过多种启发式方法搜索“看起来像秘密”的字符串。这对于非结构化秘密来说很棒,但可能需要调整以调整扫描精度。
-
关键词检测器
此功能忽略保密值,并搜索通常与使用硬编码值分配保密值相关的变量名。这对于“看起来不像保密值”的字符串(例如,le3tc0de密码)非常适用,但可能需要调整过滤器以调整扫描精度。
想要找到我们目前无法捕获的保密值吗?您还可以(轻松地)开发自己的插件,并使用它与引擎一起使用!有关更多信息,请参阅插件文档。
过滤器
detect-secrets
附带几个内置过滤器,可能适合您的需求。
--exclude-lines
有时,您可能希望能够在扫描中全局允许某些与特定模式匹配的行。您可以指定正则表达式规则,如下所示
$ detect-secrets scan --exclude-lines 'password = (blah|fake)'
或者,您可以指定多个正则表达式规则,如下所示
$ detect-secrets scan --exclude-lines 'password = blah' --exclude-lines 'password = fake'
--exclude-files
有时,您可能希望能够在扫描中忽略某些文件。您可以指定正则表达式模式来做到这一点,如果文件名符合此正则表达式模式,则不会对其进行扫描
$ detect-secrets scan --exclude-files '.*\.signature$'
或者,您可以指定多个正则表达式模式,如下所示
$ detect-secrets scan --exclude-files '.*\.signature$' --exclude-files '.*/i18n/.*'
--exclude-secrets
有时,您可能希望能够在扫描中忽略某些保密值。您可以指定正则表达式规则,如下所示
$ detect-secrets scan --exclude-secrets '(fakesecret|\${.*})'
或者,您可以指定多个正则表达式规则,如下所示
$ detect-secrets scan --exclude-secrets 'fakesecret' --exclude-secrets '\${.*})'
内联允许列表
有时,您可能希望将排除应用于特定行,而不仅仅是全局排除。您可以使用以下内联允许列表来实现
API_KEY = 'this-will-ordinarily-be-detected-by-a-plugin' # pragma: allowlist secret
这些注释支持多种语言。例如
const GoogleCredentialPassword = "something-secret-here"; // pragma: allowlist secret
您还可以使用
# pragma: allowlist nextline secret
API_KEY = 'WillAlsoBeIgnored'
这可能是一种方便的方法,可以忽略保密值,而无需重新生成整个基线。如果需要明确搜索这些允许列表中的保密值,也可以这样做
$ detect-secrets scan --only-allowlisted
想要编写更多自定义逻辑以过滤掉假阳性?请参阅我们如何在过滤器文档中这样做。
扩展
wordlist
--exclude-secrets
标志允许您指定正则表达式规则来排除保密值。但是,如果您想指定大量单词,则可以使用--word-list
标志。
要使用此功能,请务必安装pyahocorasick
包,或者简单地使用
$ pip install detect-secrets[word_list]
然后,您可以使用它,如下所示
$ cat wordlist.txt
not-a-real-secret
$ cat sample.ini
password = not-a-real-secret
# Will show results
$ detect-secrets scan sample.ini
# No results found
$ detect-secrets scan --word-list wordlist.txt
乱码检测器
乱码检测器是一个简单的机器学习模型,它尝试确定一个保密值是否实际上是乱码,假设真实保密值不是类似单词的。
要使用此功能,请务必安装gibberish-detector
包,或者使用
$ pip install detect-secrets[gibberish]
有关如何训练模型的更多信息,请参阅gibberish-detector包。将包含一个预训练模型(由处理RFC生成),以便轻松使用。
您也可以指定自己的模型,如下所示
$ detect-secrets scan --gibberish-model custom.model
这不是一个默认的插件,因为这将忽略如password
之类的保密值。
注意事项
这并不是防止保密值进入代码库的万无一失的解决方案。只有正确的开发者教育才能真正做到这一点。此预提交钩子仅实现了几个启发式方法,以尝试防止明显的提交保密值的情况。
无法防止的事项
- 多行保密值
- 未触发
KeywordDetector
的默认密码(例如login = "hunter2"
)
常见问题解答(FAQ)
通用
-
即使我在git仓库中,也遇到了“未检测到git仓库”的警告。
检查您的
git
版本是否大于等于1.8.5。如果不是,请升级它然后重试。更多信息在这里。
Windows
-
detect-secrets audit
在创建基线后在创建基线后显示“不是有效的基线文件!”请确保基线文件的文件编码为UTF-8。更多信息在这里。
项目详情
下载文件
下载适用于您平台的文件。如果您不确定选择哪个,请了解有关安装包的更多信息。