detect-secrets
detect-secrets copied to clipboard
audit fails with custom plugin
When running detect-secrets audit against a baseline created with a custom filter, I get a python error
@ detect-secrets audit .secrets.baseline
Traceback (most recent call last):
File "/home/matthewh/.local/lib/python3.10/site-packages/detect_secrets/core/plugins/initialize.py", line 19, in from_secret_type
plugin_type = get_mapping_from_secret_type_to_class()[secret_type]
KeyError: 'IP Addresses'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/matthewh/.local/bin/detect-secrets", line 8, in <module>
sys.exit(main())
File "/home/matthewh/.local/lib/python3.10/site-packages/detect_secrets/main.py", line 32, in main
handle_audit_action(args)
File "/home/matthewh/.local/lib/python3.10/site-packages/detect_secrets/main.py", line 152, in handle_audit_action
audit.audit_baseline(args.filename[0])
File "/home/matthewh/.local/lib/python3.10/site-packages/detect_secrets/audit/audit.py", line 25, in audit_baseline
if _classify_secrets(get_secret_iterator(secrets)):
File "/home/matthewh/.local/lib/python3.10/site-packages/detect_secrets/audit/audit.py", line 40, in _classify_secrets
secret.secret_value = get_raw_secret_from_file(secret)
File "/home/matthewh/.local/lib/python3.10/site-packages/detect_secrets/audit/common.py", line 59, in get_raw_secret_from_file
for item in get_raw_secrets_from_file(secret, line_getter_factory):
File "/home/matthewh/.local/lib/python3.10/site-packages/detect_secrets/audit/common.py", line 78, in get_raw_secrets_from_file
plugin = cast(BasePlugin, plugins.initialize.from_secret_type(secret.type))
File "/home/matthewh/.local/lib/python3.10/site-packages/detect_secrets/core/plugins/initialize.py", line 21, in from_secret_type
raise TypeError
TypeError
Return 1
$ detect-secrets --version
1.3.0
Relevant sections of .secrets-baseline
{
"version": "1.3.0",
"plugins_used": [
...
{
"name": "IPAddressDetector",
"path": "file:///home/matthewh/no-snap/mvfiler_body/ip_detector.py"
},
...
],
"results": {
...
"OPTIONS.txt": [
{
"type": "IP Addresses",
"filename": "OPTIONS.txt",
"hashed_secret": ...,
"is_verified": false,
"line_number": 20
}
],
...
},
"generated_at": "2022-09-09T18:36:27Z"
}
This appears to be a problem with the lru_cache on "get_mapping_from_secret_type_to_class" in detect_secrets.core.plugins.util. Removing the lru_cache allows this to work, but slowly
Hi @steamraven, thank you for bringing up this issue you encountered. Since it seems to be related to a custom plugin you created, could you provide us with more info about it? This would help us debug and understand what the underlying problem is.
I have replicated with a minimal plugin:
minimal.py:
from detect_secrets.plugins.base import BasePlugin
class Nothing(BasePlugin):
secret_type = 'Nothing'
def analyze_string(self, string: str) -> Generator[str, None, None]:
yield string
With just this file in a directory:
$ detect-secrets scan --all-files --no-verify --plugin minimal.py | tee .baseline
Then
$ detect-secrets audit .baseline --report
Also, with my more useful plugin. This does not seem to be plugin specific, but a race condition in the code to search for plugins themselves.
ip_detector.py:
import re
from detect_secrets.plugins.base import RegexBasedDetector
class IPAddressDetector(RegexBasedDetector):
secret_type = 'IP Addresses'
denylist = [
re.compile(
r'(?:[0-9]{1,3}\.){3}[0-9]{1,3}'
)
]
@steamraven Hello. I do not think this is a race condition - however I do think there is a bug related to some recent changes. Can you tell me if in your baseline file that you are auditing has any of the following secret types:
- AWS Access Key
- Cloudant Credentials
- IBM COS HMAC Credentials
- SoftLayer Credentials
That pr does not fix it.
I generated a baseline using the minimal.py plugin on a folder containing just the plugin itself. The only secrets are "Secret Keyword" and "Nothing".
Specifically, the plugins secret type IS in the baseline. It appears audit will fail with ANY external plugin secret type.
As I said above, commenting out the lru_cache at https://github.com/Yelp/detect-secrets/blob/57cc31909cb61a6a457a1b709bd432ff355cae3b/detect_secrets/core/plugins/util.py#L23
resolves the issue. Unfortunately, it slows down secret detection a lot.
I can get you more detailed tracing but it appears that get_mapping_from_secret_type_to_class is called during parameter setup with a generic settings object that has no plugins. Because the lru_cache, this get_mapping_from_secret_type_to_class does not return any external plugins
If the lru_cache is removed, it is eventually called with a settings object that has the external plugin
Here is my baseline:
https://gist.github.com/steamraven/8005a93f539ebb9fa25ece4ac9d7a878
main.parse_args
calls ParserBuilder.add_console_use_arguments
add_console_use_arguments
adds baseline.parse_args
to self._post_processors
main.parse_args
calls ParserBuilder.parse_args
ParserBuilder.parse_args** calls all the
self._post_processors, which includes
baseline.parse_args`
-- Note that baseline.add_baseline_option
is called on the "scan" subparser, but the baseline.parse_args
is added to the parent, so there is no way to add a "--baseline" option to the audit invocation as far as I can tell
baseline.parse_args
does not see a "--baseline" option and calls common.initialize_plugin_settings
common.initialize_plugin_settings
calls settings.default_settings
settings.default_settings
calls core.plugins.util.get_mapping_from_secret_type_to_class
within a settings.transient_settings
It appears there is a cache_bust
in settings.transient_settings
that should clear some caches. Maybe it needs to clear the lru_cache
edited for clarity
Encountered the same issue. I used my customized plugins to generate a baseline file,
detect-secrets scan ./ \
--all-files \
--baseline .detect-secrets/.secrets.baseline \
--exclude-files '^\.git(/.*)?$' \
--exclude-files '^\.detect-secrets(/.*)?$' \
-p .detect-secrets/plugins/absolute_filepath.py \
-p .detect-secrets/plugins/aws_sensitive_info.py \
-p .detect-secrets/plugins/email_address.py \
-p .detect-secrets/plugins/ip_address.py
But the newly generated baseline file can not be used for audit
due to KeyError:
throw by python
If I don't use the -p argument but directly put my plugins into the plugins
folder of detect-secrets
, then there is no such issue.