diffsense 2.2.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. adapters/__init__.py +0 -0
  2. adapters/base.py +27 -0
  3. adapters/github_adapter.py +164 -0
  4. adapters/gitlab_adapter.py +207 -0
  5. adapters/local_adapter.py +136 -0
  6. banner.py +71 -0
  7. cli.py +606 -0
  8. config/__init__.py +1 -0
  9. config/rules.yaml +371 -0
  10. core/__init__.py +235 -0
  11. core/ast_detector.py +853 -0
  12. core/change.py +46 -0
  13. core/composer.py +93 -0
  14. core/evaluator.py +15 -0
  15. core/ignore_manager.py +71 -0
  16. core/knowledge.py +77 -0
  17. core/parser.py +181 -0
  18. core/parser_manager.py +104 -0
  19. core/quality_manager.py +117 -0
  20. core/renderer.py +197 -0
  21. core/rule_base.py +98 -0
  22. core/rule_runtime.py +103 -0
  23. core/rules.py +718 -0
  24. core/run_config.py +85 -0
  25. core/semantic_diff.py +359 -0
  26. core/signal_model.py +21 -0
  27. core/signals_registry.py +62 -0
  28. diffsense-2.2.12.dist-info/METADATA +18 -0
  29. diffsense-2.2.12.dist-info/RECORD +58 -0
  30. diffsense-2.2.12.dist-info/WHEEL +5 -0
  31. diffsense-2.2.12.dist-info/entry_points.txt +3 -0
  32. diffsense-2.2.12.dist-info/licenses/LICENSE +176 -0
  33. diffsense-2.2.12.dist-info/top_level.txt +11 -0
  34. diffsense_mcp/__init__.py +1 -0
  35. diffsense_mcp/launcher.py +28 -0
  36. diffsense_mcp/server.py +687 -0
  37. governance/lifecycle.py +54 -0
  38. main.py +318 -0
  39. rules/__init__.py +246 -0
  40. rules/api_compatibility.py +372 -0
  41. rules/collection_handling.py +349 -0
  42. rules/concurrency.py +194 -0
  43. rules/concurrency_adapter.py +250 -0
  44. rules/cross_language_adapter.py +444 -0
  45. rules/exception_handling.py +320 -0
  46. rules/go_rules.py +401 -0
  47. rules/null_safety.py +301 -0
  48. rules/resource_management.py +222 -0
  49. rules/yaml_adapter.py +195 -0
  50. run_audit.py +478 -0
  51. sdk/cpp_adapter.py +238 -0
  52. sdk/go_adapter.py +199 -0
  53. sdk/java_adapter.py +199 -0
  54. sdk/javascript_adapter.py +229 -0
  55. sdk/language_adapter.py +313 -0
  56. sdk/python_adapter.py +195 -0
  57. sdk/rule.py +63 -0
  58. sdk/signal.py +14 -0
sdk/cpp_adapter.py ADDED
@@ -0,0 +1,238 @@
1
+ """
2
+ C++ Language Adapter for DiffSense
3
+
4
+ Provides C++-specific patterns and constructs for rule development.
5
+ """
6
+
7
+ import re
8
+ from typing import List, Set, Pattern, Dict
9
+ from .language_adapter import LanguageAdapter
10
+
11
+
12
+ class CppAdapter(LanguageAdapter):
13
+ """
14
+ Language adapter for C++.
15
+
16
+ Provides C++-specific patterns for resource management, memory safety,
17
+ concurrency, and other language constructs.
18
+ """
19
+
20
+ def __init__(self):
21
+ super().__init__("cpp")
22
+ self._compile_patterns()
23
+
24
+ def _compile_patterns(self):
25
+ """Pre-compile commonly used patterns."""
26
+ # Thread Safety / Concurrency Patterns
27
+ self._lock_patterns = [
28
+ re.compile(r'std::lock_guard\s*<'),
29
+ re.compile(r'std::unique_lock\s*<'),
30
+ re.compile(r'std::shared_lock\s*<'),
31
+ re.compile(r'pthread_mutex_lock\s*\('),
32
+ re.compile(r'boost::mutex'),
33
+ re.compile(r'std::mutex'),
34
+ ]
35
+
36
+ self._unlock_patterns = [
37
+ re.compile(r'std::lock_guard.*release\('),
38
+ re.compile(r'std::unique_lock.*release\('),
39
+ re.compile(r'pthread_mutex_unlock\s*\('),
40
+ re.compile(r'\.unlock\(\)'),
41
+ ]
42
+
43
+ self._volatile_patterns = [
44
+ re.compile(r'std::atomic<'),
45
+ re.compile(r'volatile\s+\w+'),
46
+ re.compile(r'atomic_\w+\s*\('),
47
+ ]
48
+
49
+ # Resource Management Patterns (RAII)
50
+ self._resource_creation = [
51
+ re.compile(r'new\s+\w+'),
52
+ re.compile(r'fopen\s*\('),
53
+ re.compile(r'ifstream\s*\('),
54
+ re.compile(r'ofstream\s*\('),
55
+ re.compile(r'socket\s*\('),
56
+ re.compile(r'connect\s*\('),
57
+ re.compile(r'std::make_unique'),
58
+ re.compile(r'std::make_shared'),
59
+ re.compile(r'std::move'),
60
+ ]
61
+
62
+ # Error Handling Patterns
63
+ self._error_check = [
64
+ re.compile(r'catch\s*\(\s*\w+.*\)\s*\{'),
65
+ re.compile(r'if\s*\(\s*errno'),
66
+ re.compile(r'if\s*\(\s*!'),
67
+ re.compile(r'if\s*\(\s*nullptr'),
68
+ re.compile(r'if\s*\(\s*\w+\s*==\s*NULL'),
69
+ ]
70
+
71
+ self._error_ignore = [
72
+ re.compile(r'catch\s*\([^)]*\)\s*\{\s*\}'),
73
+ re.compile(r'catch\s*\(\s*\w+\s*&\s*\w+\s*\)\s*\{\s*\}'),
74
+ ]
75
+
76
+ # Memory Management Patterns
77
+ self._memory_patterns = [
78
+ re.compile(r'delete\s+\w+'),
79
+ re.compile(r'delete\[\]\s+\w+'),
80
+ re.compile(r'free\s*\('),
81
+ re.compile(r'malloc\s*\('),
82
+ re.compile(r'realloc\s*\('),
83
+ re.compile(r'std::unique_ptr'),
84
+ re.compile(r'std::shared_ptr'),
85
+ re.compile(r'std::weak_ptr'),
86
+ ]
87
+
88
+ # Security Patterns
89
+ self._security = {
90
+ 'buffer_overflow': [
91
+ re.compile(r'strcpy\s*\('),
92
+ re.compile(r'strcat\s*\('),
93
+ re.compile(r'sprintf\s*\('),
94
+ re.compile(r'gets\s*\('),
95
+ re.compile(r'scanf\s*\([^)]*%s'),
96
+ ],
97
+ 'hardcoded_secret': [
98
+ re.compile(r'password\s*=\s*["\'][^"\']+["\']'),
99
+ re.compile(r'api[_-]?key\s*=\s*["\'][^"\']+["\']'),
100
+ re.compile(r'secret\s*=\s*["\'][^"\']+["\']'),
101
+ re.compile(r'token\s*=\s*["\'][^"\']+["\']'),
102
+ ],
103
+ 'command_injection': [
104
+ re.compile(r'system\s*\('),
105
+ re.compile(r'exec\s*\('),
106
+ re.compile(r'popen\s*\('),
107
+ re.compile(r'shell_exec\s*\('),
108
+ ],
109
+ 'format_string': [
110
+ re.compile(r'printf\s*\([^,]+%s'),
111
+ re.compile(r'sprintf\s*\([^,]+%s'),
112
+ ],
113
+ 'unsafe_pointer': [
114
+ re.compile(r'new\s+\w+\s*\(\s*\)'),
115
+ re.compile(r'\*\s*\w+\s*='),
116
+ re.compile(r'&(?!\w)'),
117
+ ],
118
+ }
119
+
120
+ # ==================== Thread Safety ====================
121
+
122
+ def get_thread_safe_types(self) -> Set[str]:
123
+ return {
124
+ 'std::mutex', 'std::recursive_mutex', 'std::shared_mutex',
125
+ 'std::lock_guard', 'std::unique_lock', 'std::shared_lock',
126
+ 'std::atomic', 'std::atomic_flag',
127
+ 'pthread_mutex_t', 'pthread_rwlock_t',
128
+ 'concurrent_queue', 'thread',
129
+ }
130
+
131
+ def get_unsafe_types(self) -> Set[str]:
132
+ return {
133
+ 'raw pointer', 'char*', 'void*', 'int*',
134
+ 'std::vector', 'std::list', 'std::map', 'std::set',
135
+ }
136
+
137
+ def get_lock_patterns(self) -> List[Pattern]:
138
+ return self._lock_patterns
139
+
140
+ def get_unlock_patterns(self) -> List[Pattern]:
141
+ return self._unlock_patterns
142
+
143
+ def get_volatile_patterns(self) -> List[Pattern]:
144
+ return self._volatile_patterns
145
+
146
+ # ==================== Resource Management ====================
147
+
148
+ def get_cleanup_keywords(self) -> Set[str]:
149
+ return {
150
+ 'delete', 'delete[]', 'free', 'close',
151
+ 'fclose', 'shutdown', 'disconnect',
152
+ 'std::unique_ptr', 'std::shared_ptr',
153
+ 'RAII', 'destructor', '~'
154
+ }
155
+
156
+ def get_resource_creation_patterns(self) -> List[Pattern]:
157
+ return self._resource_creation
158
+
159
+ # ==================== Error Handling ====================
160
+
161
+ def get_error_types(self) -> Set[str]:
162
+ return {
163
+ 'std::exception', 'std::runtime_error', 'std::logic_error',
164
+ 'std::bad_alloc', 'std::bad_cast', 'std::out_of_range',
165
+ 'std::invalid_argument', 'errno', 'NULL', 'nullptr'
166
+ }
167
+
168
+ def get_error_check_patterns(self) -> List[Pattern]:
169
+ return self._error_check
170
+
171
+ def get_error_ignore_patterns(self) -> List[Pattern]:
172
+ return self._error_ignore
173
+
174
+ # ==================== Null Safety ====================
175
+
176
+ def get_null_checks(self) -> Set[str]:
177
+ return {
178
+ '== nullptr', '!= nullptr', '!ptr',
179
+ 'if (ptr)', 'if (!ptr)', 'if (ptr == nullptr)',
180
+ 'NULL', 'nullptr', 'assert()'
181
+ }
182
+
183
+ def get_null_pointer_types(self) -> Set[str]:
184
+ return {
185
+ 'nullptr', 'NULL', 'void*', 'char*', 'T*'
186
+ }
187
+
188
+ # ==================== Concurrency Primitives ====================
189
+
190
+ def get_concurrency_primitives(self) -> Set[str]:
191
+ return {
192
+ 'std::thread', 'std::mutex', 'std::lock_guard',
193
+ 'std::atomic', 'std::future', 'std::promise',
194
+ 'pthread', 'pthread_mutex', 'pthread_cond',
195
+ 'boost::thread', 'boost::mutex'
196
+ }
197
+
198
+ def get_thread_creation_patterns(self) -> List[Pattern]:
199
+ return [
200
+ re.compile(r'std::thread\s*\('),
201
+ re.compile(r'pthread_create\s*\('),
202
+ re.compile(r'boost::thread\s*\('),
203
+ ]
204
+
205
+ # ==================== Security ====================
206
+
207
+ def get_dangerous_patterns(self) -> Dict[str, List[Pattern]]:
208
+ return self._security
209
+
210
+ # ==================== Additional C++ specific ====================
211
+
212
+ def get_memory_management_patterns(self) -> List[Pattern]:
213
+ """Get patterns for memory management (smart vs raw pointers)."""
214
+ return self._memory_patterns
215
+
216
+ def get_raii_patterns(self) -> List[Pattern]:
217
+ """Get patterns for RAII (Resource Acquisition Is Initialization)."""
218
+ return [
219
+ re.compile(r'class\s+\w+.*\{'),
220
+ re.compile(r'~?\w+\s*\(\s*\).*\{'),
221
+ re.compile(r'std::unique_ptr'),
222
+ re.compile(r'std::shared_ptr'),
223
+ ]
224
+
225
+ def get_smart_pointer_patterns(self) -> List[Pattern]:
226
+ """Get patterns for smart pointers (preferred over raw)."""
227
+ return [
228
+ re.compile(r'std::unique_ptr'),
229
+ re.compile(r'std::shared_ptr'),
230
+ re.compile(r'std::weak_ptr'),
231
+ re.compile(r'std::make_unique'),
232
+ re.compile(r'std::make_shared'),
233
+ ]
234
+
235
+
236
+ def get_adapter():
237
+ """Get C++ adapter instance."""
238
+ return CppAdapter()
sdk/go_adapter.py ADDED
@@ -0,0 +1,199 @@
1
+ """
2
+ Go Language Adapter for DiffSense
3
+
4
+ Provides Go-specific patterns and constructs for rule development.
5
+ """
6
+
7
+ import re
8
+ from typing import List, Set, Pattern, Dict
9
+ from .language_adapter import LanguageAdapter
10
+
11
+
12
+ class GoAdapter(LanguageAdapter):
13
+ """
14
+ Language adapter for Go.
15
+
16
+ Provides Go-specific patterns for concurrency, channel management,
17
+ error handling, and other language constructs.
18
+ """
19
+
20
+ def __init__(self):
21
+ super().__init__("go")
22
+ self._compile_patterns()
23
+
24
+ def _compile_patterns(self):
25
+ """Pre-compile commonly used patterns."""
26
+ # Thread Safety / Concurrency Patterns
27
+ self._lock_patterns = [
28
+ re.compile(r'\.Lock\(\)'),
29
+ re.compile(r'\.RLock\(\)'),
30
+ re.compile(r'sync\.Mutex'),
31
+ re.compile(r'sync\.RWMutex'),
32
+ re.compile(r'sync\.Once\.Do'),
33
+ ]
34
+
35
+ self._unlock_patterns = [
36
+ re.compile(r'\.Unlock\(\)'),
37
+ re.compile(r'\.RUnlock\(\)'),
38
+ ]
39
+
40
+ self._volatile_patterns = [
41
+ re.compile(r'atomic\.(?:Load|Store|Add|Swap|CompareAndSwap)'),
42
+ re.compile(r'sync\/atomic\.'),
43
+ ]
44
+
45
+ # Resource Management Patterns
46
+ self._resource_creation = [
47
+ re.compile(r'make\('),
48
+ re.compile(r'os\.Open\('),
49
+ re.compile(r'os\.Create\('),
50
+ re.compile(r'http\.(?:ListenAndServe|NewRequest)'),
51
+ re.compile(r'database\.Open\('),
52
+ re.compile(r'grpc\.Dial'),
53
+ re.compile(r'conn\.Open\('),
54
+ ]
55
+
56
+ # Error Handling Patterns
57
+ self._error_check = [
58
+ re.compile(r'if\s+err\s*!=\s*nil'),
59
+ re.compile(r'if\s+err\s*==\s*nil'),
60
+ ]
61
+
62
+ self._error_ignore = [
63
+ re.compile(r'_\s*=\s*\w+'), # _ = function()
64
+ re.compile(r'_\s*:='), # _ := function()
65
+ ]
66
+
67
+ # Goroutine/Thread Creation Patterns
68
+ self._thread_creation = [
69
+ re.compile(r'\bgo\s+(?:func|\w+)'),
70
+ re.compile(r'go\s+\w+\('),
71
+ re.compile(r'go\s+func\('),
72
+ ]
73
+
74
+ # Security Patterns
75
+ self._security = {
76
+ 'command_injection': [
77
+ re.compile(r'exec\.Command'),
78
+ re.compile(r'syscall\.Exec'),
79
+ re.compile(r'syscall\.Spawn'),
80
+ re.compile(r'os\.Exec'),
81
+ ],
82
+ 'hardcoded_secret': [
83
+ re.compile(r'password\s*:=\s*"[^"]+"'),
84
+ re.compile(r'api[_-]?key\s*:=\s*"[^"]+"'),
85
+ re.compile(r'secret\s*:=\s*"[^"]+"'),
86
+ re.compile(r'token\s*:=\s*"[^"]+"'),
87
+ re.compile(r'aws[_-]?secret'),
88
+ ],
89
+ 'sql_injection': [
90
+ re.compile(r'Query\([^)]*\+[^)]*\)'),
91
+ re.compile(r'Exec\([^)]*\+[^)]*\)'),
92
+ re.compile(r'\.QueryRow\([^)]*\+'),
93
+ ],
94
+ 'deserialization': [
95
+ re.compile(r'gob\.Decode'),
96
+ re.compile(r'gob\.NewDecoder'),
97
+ re.compile(r'json\.Unmarshal'),
98
+ re.compile(r'xml\.Unmarshal'),
99
+ ],
100
+ 'unsafe_usage': [
101
+ re.compile(r'unsafe\.Pointer'),
102
+ re.compile(r'unsafe\.Sizeof'),
103
+ re.compile(r'unsafe\.Alignof'),
104
+ re.compile(r'unsafe\.Offsetof'),
105
+ ],
106
+ 'path_traversal': [
107
+ re.compile(r'http\.(?:Get|Post)\s*\([^)]*\+[^)]*\)'),
108
+ re.compile(r'ioutil\.ReadFile\([^)]*\+[^)]*\)'),
109
+ ],
110
+ }
111
+
112
+ # ==================== Thread Safety ====================
113
+
114
+ def get_thread_safe_types(self) -> Set[str]:
115
+ return {
116
+ 'sync.Mutex', 'sync.RWMutex', 'sync.WaitGroup', 'sync.Once',
117
+ 'sync.Cond', 'sync.Pool', 'sync.Map', 'sync.Locker',
118
+ 'chan', 'sync.AtomicInt32', 'sync.AtomicInt64',
119
+ 'atomic.Int32', 'atomic.Int64', 'atomic.Uint32', 'atomic.Uint64',
120
+ 'atomic.Pointer', 'context.Context', 'errgroup.Group'
121
+ }
122
+
123
+ def get_unsafe_types(self) -> Set[str]:
124
+ return {
125
+ 'map', 'slice', '[]',
126
+ 'interface{}', # empty interface
127
+ 'string', # but safe for read
128
+ }
129
+
130
+ def get_lock_patterns(self) -> List[Pattern]:
131
+ return self._lock_patterns
132
+
133
+ def get_unlock_patterns(self) -> List[Pattern]:
134
+ return self._unlock_patterns
135
+
136
+ def get_volatile_patterns(self) -> List[Pattern]:
137
+ return self._volatile_patterns
138
+
139
+ # ==================== Resource Management ====================
140
+
141
+ def get_cleanup_keywords(self) -> Set[str]:
142
+ return {
143
+ 'defer', 'close()', 'defer close()',
144
+ 'defer func()', 'defer wg.Done()',
145
+ 'defer cancel()' # context cancellation
146
+ }
147
+
148
+ def get_resource_creation_patterns(self) -> List[Pattern]:
149
+ return self._resource_creation
150
+
151
+ # ==================== Error Handling ====================
152
+
153
+ def get_error_types(self) -> Set[str]:
154
+ return {
155
+ 'error', 'error interface',
156
+ 'io.EOF', 'io.ErrUnexpectedEOF',
157
+ 'syscall.Errno'
158
+ }
159
+
160
+ def get_error_check_patterns(self) -> List[Pattern]:
161
+ return self._error_check
162
+
163
+ def get_error_ignore_patterns(self) -> List[Pattern]:
164
+ return self._error_ignore
165
+
166
+ # ==================== Null Safety ====================
167
+
168
+ def get_null_checks(self) -> Set[str]:
169
+ return {
170
+ '== nil', '!= nil', 'if err != nil', 'if err == nil',
171
+ 'if ctx == nil', 'if ch == nil', 'if m == nil',
172
+ }
173
+
174
+ def get_null_pointer_types(self) -> Set[str]:
175
+ return {
176
+ 'pointer', 'interface', 'slice', 'map', 'chan', 'func',
177
+ 'error' # error is nil-checkable
178
+ }
179
+
180
+ # ==================== Concurrency Primitives ====================
181
+
182
+ def get_concurrency_primitives(self) -> Set[str]:
183
+ return {
184
+ 'go', 'chan', 'select', 'defer',
185
+ 'sync.Mutex', 'sync.RWMutex', 'sync.WaitGroup',
186
+ 'sync.Once', 'sync.Cond', 'sync.Pool', 'sync.Map',
187
+ 'context.Context', 'context.WithCancel',
188
+ 'context.WithTimeout', 'context.WithDeadline',
189
+ 'errgroup.Group', 'golang.org/x/sync/errgroup',
190
+ 'atomic', 'runtime.GOMAXPROCS'
191
+ }
192
+
193
+ def get_thread_creation_patterns(self) -> List[Pattern]:
194
+ return self._thread_creation
195
+
196
+ # ==================== Security ====================
197
+
198
+ def get_dangerous_patterns(self) -> Dict[str, List[Pattern]]:
199
+ return self._security
sdk/java_adapter.py ADDED
@@ -0,0 +1,199 @@
1
+ """
2
+ Java Language Adapter for DiffSense
3
+
4
+ Provides Java-specific patterns and constructs for rule development.
5
+ """
6
+
7
+ import re
8
+ from typing import List, Set, Pattern, Dict
9
+ from .language_adapter import LanguageAdapter
10
+
11
+
12
+ class JavaAdapter(LanguageAdapter):
13
+ """
14
+ Language adapter for Java.
15
+
16
+ Provides Java-specific patterns for thread safety, resource management,
17
+ error handling, and other language constructs.
18
+ """
19
+
20
+ def __init__(self):
21
+ super().__init__("java")
22
+ self._compile_patterns()
23
+
24
+ def _compile_patterns(self):
25
+ """Pre-compile commonly used patterns."""
26
+ # Thread Safety Patterns
27
+ self._lock_patterns = [
28
+ re.compile(r'synchronized'),
29
+ re.compile(r'\.lock\(\)'),
30
+ re.compile(r'\.tryLock\(\)'),
31
+ re.compile(r'\.wait\(\)'),
32
+ ]
33
+
34
+ self._unlock_patterns = [
35
+ re.compile(r'\.unlock\(\)'),
36
+ re.compile(r'\.notify\(\)'),
37
+ re.compile(r'\.notifyAll\(\)'),
38
+ ]
39
+
40
+ self._volatile_patterns = [
41
+ re.compile(r'\bvolatile\b'),
42
+ re.compile(r'AtomicInteger'),
43
+ re.compile(r'AtomicLong'),
44
+ re.compile(r'AtomicBoolean'),
45
+ re.compile(r'AtomicReference'),
46
+ ]
47
+
48
+ # Resource Management Patterns
49
+ self._resource_creation = [
50
+ re.compile(r'new\s+(?:File|Input|Output)?Stream\('),
51
+ re.compile(r'new\s+Connection\('),
52
+ re.compile(r'DriverManager\.getConnection'),
53
+ re.compile(r'new\s+(?:Socket|ServerSocket)\('),
54
+ re.compile(r'new\s+Thread\('),
55
+ re.compile(r'Executors\.new'),
56
+ ]
57
+
58
+ # Error Handling Patterns
59
+ self._error_check = [
60
+ re.compile(r'catch\s*\(\s*(\w+\s+)?\w+Exception'),
61
+ re.compile(r'if\s+\w+\s*==\s*null'),
62
+ re.compile(r'if\s+\w+\s*!=\s*null'),
63
+ re.compile(r'Objects\.isNull'),
64
+ re.compile(r'Objects\.nonNull'),
65
+ ]
66
+
67
+ self._error_ignore = [
68
+ re.compile(r'catch\s*\(\s*Exception\s*\)'),
69
+ re.compile(r'catch\s*\(\s*\s*\)'),
70
+ re.compile(r'catch\s*\(\s*Throwable\s*\)'),
71
+ ]
72
+
73
+ # Thread Creation Patterns
74
+ self._thread_creation = [
75
+ re.compile(r'new\s+Thread\('),
76
+ re.compile(r'executor\.submit'),
77
+ re.compile(r'CompletableFuture\.runAsync'),
78
+ re.compile(r'CompletableFuture\.supplyAsync'),
79
+ re.compile(r'new\s+(?:Fixed|Cached|Single)ThreadPool'),
80
+ ]
81
+
82
+ # Security Patterns
83
+ self._security = {
84
+ 'sql_injection': [
85
+ re.compile(r'Statement.*\+'),
86
+ re.compile(r'executeQuery.*\+'),
87
+ re.compile(r'createStatement\(\).*\+'),
88
+ ],
89
+ 'hardcoded_secret': [
90
+ re.compile(r'password\s*=\s*"[^"]+"'),
91
+ re.compile(r'api[_-]?key\s*=\s*"[^"]+"'),
92
+ re.compile(r'secret\s*=\s*"[^"]+"'),
93
+ re.compile(r'token\s*=\s*"[^"]+"'),
94
+ ],
95
+ 'command_injection': [
96
+ re.compile(r'Runtime\.getRuntime\(\)\.exec'),
97
+ re.compile(r'ProcessBuilder'),
98
+ ],
99
+ 'deserialization': [
100
+ re.compile(r'ObjectInputStream'),
101
+ re.compile(r'XMLDecoder'),
102
+ re.compile(r'YAML\.load'),
103
+ ],
104
+ }
105
+
106
+ # ==================== Thread Safety ====================
107
+
108
+ def get_thread_safe_types(self) -> Set[str]:
109
+ return {
110
+ 'ConcurrentHashMap', 'ConcurrentMap', 'ConcurrentLinkedQueue',
111
+ 'ConcurrentLinkedDeque', 'ConcurrentSkipListMap', 'ConcurrentSkipListSet',
112
+ 'CopyOnWriteArrayList', 'CopyOnWriteArraySet',
113
+ 'AtomicInteger', 'AtomicLong', 'AtomicBoolean', 'AtomicReference',
114
+ 'AtomicIntegerArray', 'AtomicLongArray',
115
+ 'Collections.synchronizedMap', 'Collections.synchronizedList',
116
+ 'Collections.synchronizedSet', 'Vector', 'Stack', 'Hashtable',
117
+ 'BlockingQueue', 'BlockingDeque', 'LinkedBlockingQueue',
118
+ 'Semaphore', 'CountDownLatch', 'CyclicBarrier', 'Exchanger'
119
+ }
120
+
121
+ def get_unsafe_types(self) -> Set[str]:
122
+ return {
123
+ 'HashMap', 'ArrayList', 'HashSet', 'LinkedList',
124
+ 'LinkedHashMap', 'LinkedHashSet', 'TreeMap', 'TreeSet',
125
+ 'Map', 'List', 'Set', 'Collection',
126
+ 'StringBuilder', 'StringBuffer', # when shared across threads
127
+ }
128
+
129
+ def get_lock_patterns(self) -> List[Pattern]:
130
+ return self._lock_patterns
131
+
132
+ def get_unlock_patterns(self) -> List[Pattern]:
133
+ return self._unlock_patterns
134
+
135
+ def get_volatile_patterns(self) -> List[Pattern]:
136
+ return self._volatile_patterns
137
+
138
+ # ==================== Resource Management ====================
139
+
140
+ def get_cleanup_keywords(self) -> Set[str]:
141
+ return {
142
+ 'close()', 'finally', 'try-with-resources',
143
+ 'closeQuietly', 'IOUtils.closeQuietly'
144
+ }
145
+
146
+ def get_resource_creation_patterns(self) -> List[Pattern]:
147
+ return self._resource_creation
148
+
149
+ # ==================== Error Handling ====================
150
+
151
+ def get_error_types(self) -> Set[str]:
152
+ return {
153
+ 'Exception', 'RuntimeException', 'Throwable',
154
+ 'Error', 'IOException', 'SQLException',
155
+ 'NullPointerException', 'IllegalArgumentException',
156
+ 'IllegalStateException', 'ConcurrentModificationException'
157
+ }
158
+
159
+ def get_error_check_patterns(self) -> List[Pattern]:
160
+ return self._error_check
161
+
162
+ def get_error_ignore_patterns(self) -> List[Pattern]:
163
+ return self._error_ignore
164
+
165
+ # ==================== Null Safety ====================
166
+
167
+ def get_null_checks(self) -> Set[str]:
168
+ return {
169
+ '== null', '!= null', 'Objects.isNull', 'Objects.nonNull',
170
+ 'Optional.ofNullable', 'Optional.empty', 'isPresent',
171
+ 'if (obj == null)', 'if (obj != null)'
172
+ }
173
+
174
+ def get_null_pointer_types(self) -> Set[str]:
175
+ return {
176
+ 'Object', 'String', 'List', 'Map', 'Set', 'Collection',
177
+ 'Array', 'Integer', 'Long', 'Double', 'Float', 'Boolean',
178
+ 'Date', 'BigDecimal', 'Optional'
179
+ }
180
+
181
+ # ==================== Concurrency Primitives ====================
182
+
183
+ def get_concurrency_primitives(self) -> Set[str]:
184
+ return {
185
+ 'synchronized', 'volatile', 'Thread', 'Runnable', 'Callable',
186
+ 'ExecutorService', 'Executor', 'ThreadPoolExecutor',
187
+ 'Future', 'CompletableFuture', 'CountDownLatch',
188
+ 'CyclicBarrier', 'Semaphore', 'ReentrantLock', 'ReentrantReadWriteLock',
189
+ 'AtomicInteger', 'AtomicLong', 'AtomicBoolean', 'AtomicReference',
190
+ 'ConcurrentHashMap', 'ConcurrentMap', 'Collections.synchronizedMap'
191
+ }
192
+
193
+ def get_thread_creation_patterns(self) -> List[Pattern]:
194
+ return self._thread_creation
195
+
196
+ # ==================== Security ====================
197
+
198
+ def get_dangerous_patterns(self) -> Dict[str, List[Pattern]]:
199
+ return self._security