detect-secrets
是一个恰当命名的模块,用于(惊喜,惊喜)检测代码库中的秘密。
然而,与其他仅专注于寻找秘密的类似软件包不同,该软件包在设计时考虑到了企业客户:提供向后兼容的系统化方法:
防止新的秘密进入代码库,
检测此类预防措施是否被明确绕过,以及
提供要滚动的秘密清单,并迁移到更安全的存储。
通过这种方式,您可以创建关注点分离:接受您的大型存储库中当前可能隐藏着秘密(这就是我们所说的基线),但防止此问题变得更大,而无需处理潜在的巨大努力移走现有的秘密。
它通过针对启发式制作的正则表达式语句运行定期 diff 输出来识别是否已提交任何新机密来实现此目的。这样,它就避免了挖掘所有 git 历史记录的开销,以及每次都需要扫描整个存储库的需要。
要查看最近的更改,请参阅 CHANGELOG.md。
如果您想做出贡献,请参阅 CONTRIBUTING.md。
有关更详细的文档,请查看我们的其他文档。
创建当前在 git 存储库中找到的潜在秘密的基线。
$ 检测秘密扫描 > .secrets.baseline
或者,从不同的目录运行它:
$ 检测秘密 -C /path/to/directory 扫描 > /path/to/directory/.secrets.baseline
扫描非 git 跟踪的文件:
$ 检测秘密扫描 test_data/ --all-files > .secrets.baseline
这将重新扫描您的代码库,并且:
更新/升级您的基线以与最新版本兼容,
将它发现的任何新秘密添加到您的基线中,
删除代码库中不再存在的所有机密
这也将保留您拥有的任何标记的秘密。
$ 检测秘密扫描 --baseline .secrets.baseline
对于版本 0.9 之前的基线,只需重新创建它。
仅扫描暂存文件:
$ git diff --staged --name-only -z | git diff --staged --name-only -z | xargs -0 检测秘密钩子 --baseline .secrets.baseline
扫描所有跟踪的文件:
$ git ls 文件-z | xargs -0 检测秘密钩子 --baseline .secrets.baseline
$ 检测秘密扫描 --list-all-plugins Artifactory探测器 AWSKeyDetector Azure存储密钥检测器 基本验证检测器 云检测器 DiscordBotTokenDetector GitHubTokenDetector GitLabTokenDetector Base64高熵字符串 十六进制高熵字符串 IbmCloudIamDetector IbmCosHmacDetector IP公共探测器 JwtTokenDetector 关键词检测器 邮件黑猩猩探测器 Npm检测器 OpenAI检测器 私钥检测器 PypiTokenDetector 发送网格检测器 松弛检测器 软层检测器 SquareOAuth检测器 条纹探测器 TelegramBotTokenDetector TwilioKeyDetector
$ 检测秘密扫描 --disable-plugin KeywordDetector --disable-plugin AWSKeyDetector
如果您只想运行特定插件,您可以执行以下操作:
$ 检测秘密扫描 --list-all-plugins | grep -v 'BasicAuthDetector' | grep -v 'BasicAuthDetector' | grep -v 'BasicAuthDetector' sed "s#^#--禁用插件 #g" | xargs 检测秘密扫描 test_data
这是在基线中标记结果的可选步骤。它可用于缩小要迁移的机密清单,或更好地配置您的插件以提高其信噪比。
$ 检测秘密审计 .secrets.baseline
基本用途:
from detector_secrets import SecretsCollectionfrom detector_secrets.settings import default_settingssecrets = SecretsCollection()with default_settings():secrets.scan_file('test_data/config.ini')import jsonprint(json.dumps(secrets.json(), indent=2))
更高级的配置:
from detector_secrets import SecretsCollectionfrom detector_secrets.settings importtransient_settingssecrets = SecretsCollection()withtransient_settings({# 仅使用这些插件运行扫描。# 此格式与生成的基线中保存的格式相同。'plugins_used': [# 示例配置内置插件{'name': 'Base64HighEntropyString','limit': 5.0, },# 使用自定义插件的示例{'name': 'HippoDetector','path': 'file:///Users/aaronloo/Documents/github/detect-secrets/testing/plugins.py', }, ],# 我们还可以指定我们想要的任何附加过滤器。# 这是在 # 本地文件 `./private-filters/example.py` 中使用函数 `is_identified_by_ML_model` 的示例。'filters_used': [ {'path': 'file://private-filters/example.py::is_identified_by_ML_model', }, ] }) as settings:# 如果我们想对创建的设置对象进行任何进一步的调整(例如#禁用默认过滤器),我们可以这样做。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 检测秘密 ?
通过brew安装:
$brew安装检测秘密
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-config.yamlrepos: - 仓库:https://github.com/Yelp/detect-secretsrev:v1.5.0hooks: - id:检测secretsargs:['--baseline','.secrets.baseline']排除:package.lock.json
有时,我们希望排除误报阻止提交,而不创建基线来执行此操作。您可以通过添加评论来做到这一点:
Secret = "hunter2" # pragma: 白名单秘密
或者
// 编译指示:白名单下一行 Secretconst Secret = "hunter2";
$ 检测秘密审计 --help 用法:检测秘密审计 [-h] [--diff] [--stats] [--报告] [--仅真实 | --仅-假] [--json] 文件名 [文件名...] 审核基线允许分析师标记结果,并优化插件以获得适合其环境的最高信噪比。 位置参数: 文件名 审核给定的基线文件以区分差异 假阳性和真阳性之间。 可选参数: -h, --help 显示此帮助消息并退出 --diff 允许比较两个基线文件,以便 有效区分各种插件的区别 配置。 --stats 显示交互式审计会话的结果 已保存到基线文件中。 --report 显示包含检测到的机密的报告 报告: 显示包含所有调查结果和做出的决定的摘要。与报告模式(--report)一起使用。 --only-real 只在报告中包含真正的秘密 --only-false 仅在报告中包含误报 分析: 根据您的插件中的标记结果来量化您的插件的成功 基线。与统计模式(--stats)一起使用。 --json 以机器可读的格式输出结果。
该工具通过插件和过滤器系统运行。
插件在代码中发现秘密
过滤器忽略误报以提高扫描精度
您可以调整两者以满足您的精确度/召回率需求。
我们采用三种不同的策略来尝试在代码中寻找秘密:
基于正则表达式的规则
这些是最常见的插件类型,并且可以很好地处理结构良好的秘密。可以选择验证这些秘密,从而提高扫描精度。然而,仅仅依赖这些可能会对扫描的回忆产生负面影响。
熵探测器
这通过各种启发式方法搜索“看起来秘密”的字符串。这对于非结构化秘密来说非常有用,但可能需要进行调整来调整扫描精度。
关键词检测器
这会忽略秘密值,并搜索通常与使用硬编码值分配秘密相关的变量名称。这对于“非秘密”字符串(例如 le3tc0de 密码)非常有用,但可能需要调整过滤器来调整扫描精度。
想找到我们目前尚未发现的秘密吗?您还可以(轻松)开发自己的插件,并将其与引擎一起使用!有关更多信息,请查看插件文档。
detect-secrets
附带了几种不同的内置过滤器,可以满足您的需求。
有时,您希望能够在扫描中全局允许某些行(如果它们与特定模式匹配)。您可以指定正则表达式规则,如下所示:
$检测秘密扫描--排除行'密码=(blah |假)'
或者您可以指定多个正则表达式规则,如下所示:
$检测秘密扫描--排除行'密码= blah'--排除行'密码=假'
有时,您希望能够忽略扫描中的某些文件。您可以指定一个正则表达式模式来执行此操作,如果文件名满足此正则表达式模式,则不会扫描它:
$检测秘密扫描--排除文件'.*.signature$'
或者您可以指定多个正则表达式模式,如下所示:
$检测秘密扫描--排除文件'.*.signature$'--排除文件'.*/i18n/.*'
有时,您希望能够忽略扫描中的某些秘密值。您可以指定正则表达式规则,如下所示:
$ 检测秘密扫描 --排除秘密 '(fakesecret|${.*})'
或者您可以指定多个正则表达式规则,如下所示:
$ 检测秘密扫描 --排除秘密 'fakesecret' --排除秘密 '${.*})'
有时,您希望将排除应用于特定行,而不是全局排除它。您可以通过内联允许列表来执行此操作,如下所示:
API_KEY = '这通常会被插件检测到' # pragma: 白名单秘密
这些评论支持多种语言。例如
const GoogleCredentialPassword = "这里有秘密"; // 编译指示:白名单秘密
您还可以使用:
# pragma: 白名单下一行 SecretAPI_KEY = 'WillAlsoBeIgnored'
这可能是您忽略秘密的便捷方法,而无需再次重新生成整个基线。如果您需要显式搜索这些列入白名单的机密,您还可以执行以下操作:
$ 检测秘密扫描 --only-allowlisted
想要编写更多自定义逻辑来过滤误报吗?在我们的过滤器文档中查看如何执行此操作。
--exclude-secrets
标志允许您指定正则表达式规则以排除秘密值。但是,如果您想指定一个大的单词列表,则可以使用--word-list
标志。
要使用此功能,请务必安装pyahocorasick
软件包,或者简单地使用:
$ pip install detector-secrets[word_list]
然后,您可以这样使用它:
$ 猫 wordlist.txt 不是真正的秘密 $ 猫样本.ini 密码 = not-a-real-secret# 将显示结果$ detector-secrets scan sample.ini# 未找到结果$ detector-secrets scan --word-list wordlist.txt
乱码检测器是一个简单的 ML 模型,它尝试确定秘密值是否实际上是乱码,并假设真正的秘密值不是类似单词的。
要使用此功能,请务必安装gibberish-detector
软件包,或使用:
$ pip install detector-secrets[乱码]
查看乱码检测器包以获取有关如何训练模型的更多信息。为了方便使用,将包含一个预先训练的模型(通过处理 RFC 进行播种)。
您还可以指定自己的模型,如下所示:
$ 检测秘密扫描 --乱码模型 custom.model
这不是默认插件,因为这会忽略password
等秘密。
这并不意味着是防止秘密进入代码库的万无一失的解决方案。只有适当的开发人员教育才能真正做到这一点。这个预提交钩子仅仅实现了一些启发式方法来尝试并防止明显的提交秘密的情况。
无法阻止的事情:
多行秘密
不会触发KeywordDetector
默认密码(例如login = "hunter2"
)
“没有检测到 git 存储库。”遇到警告,即使我在 git 存储库中。
检查您的git
版本是否 >= 1.8.5。如果没有,请升级然后重试。更多详细信息请参见此处。
detect-secrets audit
显示“不是有效的基线文件!”创建基线后。
确保基线文件的文件编码为 UTF-8。更多详细信息请参见此处。