|
1 | 1 | import contextlib |
2 | | -import threading |
3 | 2 | from contextlib import contextmanager |
4 | 3 | from copy import deepcopy |
5 | 4 | from functools import lru_cache |
|
14 | 13 | from .util.importlib import import_file_as_module |
15 | 14 |
|
16 | 15 |
|
17 | | -# Lock to protect transient_settings from concurrent access. |
18 | | -# On macOS, checkov's ParallelRunner uses ThreadPoolExecutor, |
19 | | -# so all scanners share the same process and global state. Without this lock, |
20 | | -# concurrent calls to transient_settings() can corrupt the LRU-cached singletons |
21 | | -# (get_settings, get_plugins, get_mapping_from_secret_type_to_class), causing |
22 | | -# the secrets scanner to silently produce 0 findings. |
23 | | -_settings_lock = threading.Lock() |
24 | | - |
25 | | - |
26 | 16 | @lru_cache(maxsize=1) |
27 | 17 | def get_settings() -> 'Settings': |
28 | 18 | """ |
@@ -87,33 +77,21 @@ def default_settings() -> Generator['Settings', None, None]: |
87 | 77 |
|
88 | 78 | @contextmanager |
89 | 79 | def transient_settings(config: Dict[str, Any]) -> Generator['Settings', None, None]: |
90 | | - """Allows the customizability of non-global settings per invocation. |
91 | | -
|
92 | | - Protected by _settings_lock to prevent race conditions when |
93 | | - multiple threads call this concurrently (e.g., IAC + SECRETS scanners |
94 | | - running in parallel via ThreadPoolExecutor on macOS). |
95 | | - """ |
96 | | - with _settings_lock: |
97 | | - original_settings = get_settings().json() |
| 80 | + """Allows the customizability of non-global settings per invocation.""" |
| 81 | + original_settings = get_settings().json() |
98 | 82 |
|
| 83 | + cache_bust() |
| 84 | + try: |
| 85 | + yield configure_settings_from_baseline(config) |
| 86 | + finally: |
99 | 87 | cache_bust() |
100 | | - try: |
101 | | - yield configure_settings_from_baseline(config) |
102 | | - finally: |
103 | | - cache_bust() |
104 | | - configure_settings_from_baseline(original_settings) |
| 88 | + configure_settings_from_baseline(original_settings) |
105 | 89 |
|
106 | 90 |
|
107 | 91 | def cache_bust() -> None: |
108 | 92 | get_plugins.cache_clear() |
109 | 93 |
|
110 | 94 | get_filters.cache_clear() |
111 | | - |
112 | | - # BCE-56937: Clear the plugin-type mapping cache to prevent stale mappings |
113 | | - # built from empty settings during a race window. |
114 | | - from .core.plugins.util import get_mapping_from_secret_type_to_class |
115 | | - get_mapping_from_secret_type_to_class.cache_clear() |
116 | | - |
117 | 95 | for path in get_settings().filters: |
118 | 96 | # Need to also clear the individual caches (e.g. cached regex patterns). |
119 | 97 | parts = urlparse(path) |
|
0 commit comments