pinata-security-cli 0.1.1 → 0.1.2

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 (46) hide show
  1. package/package.json +2 -1
  2. package/src/categories/definitions/concurrency/deadlock.yml +426 -0
  3. package/src/categories/definitions/concurrency/idempotency-missing.yml +465 -0
  4. package/src/categories/definitions/concurrency/race-condition.yml +423 -0
  5. package/src/categories/definitions/concurrency/retry-storm.yml +490 -0
  6. package/src/categories/definitions/concurrency/thread-safety.yml +395 -0
  7. package/src/categories/definitions/concurrency/timeout-missing.yml +479 -0
  8. package/src/categories/definitions/data/bulk-operation.yml +267 -0
  9. package/src/categories/definitions/data/data-race.yml +489 -0
  10. package/src/categories/definitions/data/data-truncation.yml +425 -0
  11. package/src/categories/definitions/data/data-validation.yml +279 -0
  12. package/src/categories/definitions/data/encoding-mismatch.yml +404 -0
  13. package/src/categories/definitions/data/null-handling.yml +411 -0
  14. package/src/categories/definitions/data/precision-loss.yml +418 -0
  15. package/src/categories/definitions/data/schema-migration.yml +441 -0
  16. package/src/categories/definitions/input/boundary-testing.yml +421 -0
  17. package/src/categories/definitions/input/injection-fuzzing.yml +403 -0
  18. package/src/categories/definitions/input/null-undefined.yml +386 -0
  19. package/src/categories/definitions/network/connection-failure.yml +432 -0
  20. package/src/categories/definitions/network/high-latency.yml +529 -0
  21. package/src/categories/definitions/network/network-partition.yml +475 -0
  22. package/src/categories/definitions/network/network-timeout.yml +433 -0
  23. package/src/categories/definitions/network/packet-loss.yml +513 -0
  24. package/src/categories/definitions/network/thundering-herd.yml +508 -0
  25. package/src/categories/definitions/performance/blocking-io.yml +495 -0
  26. package/src/categories/definitions/performance/cpu-spin.yml +506 -0
  27. package/src/categories/definitions/performance/memory-bloat.yml +501 -0
  28. package/src/categories/definitions/resource/connection-pool-exhaustion.yml +481 -0
  29. package/src/categories/definitions/resource/file-handle-leak.yml +437 -0
  30. package/src/categories/definitions/resource/memory-leak.yml +443 -0
  31. package/src/categories/definitions/security/auth-failures.yml +514 -0
  32. package/src/categories/definitions/security/command-injection.yml +462 -0
  33. package/src/categories/definitions/security/csrf.yml +408 -0
  34. package/src/categories/definitions/security/data-exposure.yml +450 -0
  35. package/src/categories/definitions/security/dependency-risks.yml +472 -0
  36. package/src/categories/definitions/security/deserialization.yml +419 -0
  37. package/src/categories/definitions/security/file-upload.yml +495 -0
  38. package/src/categories/definitions/security/hardcoded-secrets.yml +447 -0
  39. package/src/categories/definitions/security/ldap-injection.yml +412 -0
  40. package/src/categories/definitions/security/path-traversal.yml +500 -0
  41. package/src/categories/definitions/security/rate-limiting.yml +441 -0
  42. package/src/categories/definitions/security/sql-injection.yml +448 -0
  43. package/src/categories/definitions/security/ssrf.yml +477 -0
  44. package/src/categories/definitions/security/timing-attack.yml +489 -0
  45. package/src/categories/definitions/security/xss.yml +463 -0
  46. package/src/categories/definitions/security/xxe.yml +416 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinata-security-cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "AI-powered test coverage analysis and generation tool. Find security blind spots before attackers do.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -19,6 +19,7 @@
19
19
  "files": [
20
20
  "dist",
21
21
  "wasm",
22
+ "src/categories/definitions",
22
23
  "README.md",
23
24
  "LICENSE"
24
25
  ],
@@ -0,0 +1,426 @@
1
+ id: deadlock
2
+ version: 1
3
+ name: Deadlock
4
+ description: |
5
+ Detects deadlock vulnerabilities where threads or processes wait indefinitely
6
+ for resources held by each other. Includes lock ordering issues, nested lock
7
+ acquisition, and database transaction deadlocks. Deadlocks cause application
8
+ hangs and require careful lock ordering or timeout mechanisms.
9
+ domain: concurrency
10
+ level: integration
11
+ priority: P0
12
+ severity: critical
13
+ applicableLanguages:
14
+ - python
15
+ - typescript
16
+ - javascript
17
+
18
+ references:
19
+ - https://cwe.mitre.org/data/definitions/833.html
20
+ - https://en.wikipedia.org/wiki/Deadlock
21
+ - https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html
22
+
23
+ detectionPatterns:
24
+ - id: python-nested-locks
25
+ type: regex
26
+ language: python
27
+ pattern: "with\\s+\\w+lock.*:.*with\\s+\\w+lock"
28
+ confidence: high
29
+ description: Detects nested lock acquisition
30
+
31
+ - id: python-multiple-acquire
32
+ type: regex
33
+ language: python
34
+ pattern: "\\.acquire\\(\\).*\\.acquire\\(\\)"
35
+ confidence: high
36
+ description: Detects multiple lock acquisitions
37
+
38
+ - id: python-lock-no-timeout
39
+ type: regex
40
+ language: python
41
+ pattern: "\\.acquire\\(\\)(?!.*timeout)"
42
+ confidence: medium
43
+ description: Detects lock acquire without timeout
44
+
45
+ - id: python-rlock-missing
46
+ type: regex
47
+ language: python
48
+ pattern: "Lock\\(\\)(?!.*RLock)"
49
+ confidence: low
50
+ description: Detects Lock usage (consider RLock for reentrant)
51
+
52
+ - id: ts-async-mutex-nested
53
+ type: regex
54
+ language: typescript
55
+ pattern: "await\\s+\\w+\\.acquire.*await\\s+\\w+\\.acquire"
56
+ confidence: high
57
+ description: Detects nested async mutex acquisition
58
+
59
+ - id: ts-promise-circular
60
+ type: regex
61
+ language: typescript
62
+ pattern: "await\\s+\\w+\\s*;.*await\\s+\\w+"
63
+ confidence: low
64
+ description: Detects multiple awaits (verify no circular deps)
65
+
66
+ - id: ts-database-transaction
67
+ type: regex
68
+ language: typescript
69
+ pattern: "transaction.*transaction|BEGIN.*BEGIN"
70
+ confidence: high
71
+ description: Detects nested database transactions
72
+
73
+ testTemplates:
74
+ - id: pytest-deadlock
75
+ language: python
76
+ framework: pytest
77
+ template: |
78
+ import pytest
79
+ import threading
80
+ import time
81
+
82
+ class Test{{className}}Deadlock:
83
+ """Deadlock tests for {{functionName}}"""
84
+
85
+ def test_no_deadlock_under_contention(self, {{fixtures}}):
86
+ """Test no deadlock with concurrent lock acquisition"""
87
+ completed = []
88
+ errors = []
89
+ timeout = 5
90
+
91
+ def worker(worker_id):
92
+ try:
93
+ result = {{functionCall}}(worker_id)
94
+ completed.append(worker_id)
95
+ except Exception as e:
96
+ errors.append(str(e))
97
+
98
+ threads = [threading.Thread(target=worker, args=(i,)) for i in range(10)]
99
+ start = time.time()
100
+
101
+ for t in threads:
102
+ t.start()
103
+ for t in threads:
104
+ t.join(timeout=timeout)
105
+
106
+ elapsed = time.time() - start
107
+
108
+ # All should complete without deadlock
109
+ assert len(completed) == 10, f"Possible deadlock: only {len(completed)}/10 completed"
110
+ assert elapsed < timeout, f"Timeout suggests deadlock"
111
+
112
+ def test_lock_ordering(self, {{fixtures}}):
113
+ """Test consistent lock ordering prevents deadlock"""
114
+ results = []
115
+
116
+ def task_a():
117
+ {{lockAFirstCall}}()
118
+ results.append('A')
119
+
120
+ def task_b():
121
+ {{lockBFirstCall}}()
122
+ results.append('B')
123
+
124
+ t1 = threading.Thread(target=task_a)
125
+ t2 = threading.Thread(target=task_b)
126
+
127
+ t1.start()
128
+ t2.start()
129
+
130
+ t1.join(timeout=2)
131
+ t2.join(timeout=2)
132
+
133
+ assert len(results) == 2, "Deadlock detected in lock ordering"
134
+
135
+ def test_lock_timeout(self, {{fixtures}}):
136
+ """Test lock acquisition has timeout"""
137
+ lock_held = threading.Event()
138
+
139
+ def holder():
140
+ {{acquireLockCall}}()
141
+ lock_held.set()
142
+ time.sleep(10)
143
+ {{releaseLockCall}}()
144
+
145
+ holder_thread = threading.Thread(target=holder)
146
+ holder_thread.start()
147
+ lock_held.wait()
148
+
149
+ # Should timeout, not block forever
150
+ start = time.time()
151
+ result = {{tryAcquireCall}}(timeout=1)
152
+ elapsed = time.time() - start
153
+
154
+ assert elapsed < 2, "Lock should timeout, not block"
155
+ assert result is False, "Should return False on timeout"
156
+
157
+ def test_reentrant_safe(self, {{fixtures}}):
158
+ """Test reentrant lock acquisition is safe"""
159
+ def recursive_function(depth=3):
160
+ {{acquireLockCall}}()
161
+ if depth > 0:
162
+ recursive_function(depth - 1)
163
+ {{releaseLockCall}}()
164
+
165
+ # Should not deadlock on reentrant acquisition
166
+ recursive_function()
167
+ variables:
168
+ - name: className
169
+ type: string
170
+ description: Class name
171
+ required: true
172
+ - name: functionName
173
+ type: string
174
+ description: Function name
175
+ required: true
176
+ - name: functionCall
177
+ type: string
178
+ description: Main function call
179
+ required: true
180
+ - name: lockAFirstCall
181
+ type: string
182
+ description: Lock A first function
183
+ required: true
184
+ - name: lockBFirstCall
185
+ type: string
186
+ description: Lock B first function
187
+ required: true
188
+ - name: acquireLockCall
189
+ type: string
190
+ description: Acquire lock function
191
+ required: true
192
+ - name: releaseLockCall
193
+ type: string
194
+ description: Release lock function
195
+ required: true
196
+ - name: tryAcquireCall
197
+ type: string
198
+ description: Try acquire with timeout
199
+ required: true
200
+ - name: fixtures
201
+ type: string
202
+ description: pytest fixtures
203
+ required: false
204
+ defaultValue: ""
205
+
206
+ - id: jest-deadlock
207
+ language: typescript
208
+ framework: jest
209
+ template: |
210
+ import { {{functionName}} } from '{{modulePath}}';
211
+
212
+ describe('{{className}} Deadlock', () => {
213
+ jest.setTimeout(10000);
214
+
215
+ describe('contention handling', () => {
216
+ it('completes all operations under contention', async () => {
217
+ const promises = Array(10).fill(null).map((_, i) =>
218
+ {{functionCall}}(i)
219
+ );
220
+
221
+ const results = await Promise.race([
222
+ Promise.all(promises),
223
+ new Promise((_, reject) =>
224
+ setTimeout(() => reject(new Error('Deadlock timeout')), 5000)
225
+ ),
226
+ ]);
227
+
228
+ expect(results).toHaveLength(10);
229
+ });
230
+ });
231
+
232
+ describe('lock timeout', () => {
233
+ it('returns error on lock timeout instead of hanging', async () => {
234
+ // First acquire should succeed
235
+ const lock = await {{acquireLockCall}}();
236
+
237
+ // Second acquire should timeout, not hang
238
+ await expect(
239
+ {{acquireLockWithTimeoutCall}}(100)
240
+ ).rejects.toThrow('timeout');
241
+
242
+ await {{releaseLockCall}}(lock);
243
+ });
244
+ });
245
+
246
+ describe('database transactions', () => {
247
+ it('handles transaction deadlock gracefully', async () => {
248
+ const results = await Promise.allSettled([
249
+ {{transactionACall}}(),
250
+ {{transactionBCall}}(),
251
+ ]);
252
+
253
+ // At least one should succeed, failed one should retry
254
+ const successes = results.filter(r => r.status === 'fulfilled');
255
+ expect(successes.length).toBeGreaterThanOrEqual(1);
256
+ });
257
+
258
+ it('uses consistent lock ordering', async () => {
259
+ // Both functions should acquire locks in same order
260
+ const [r1, r2] = await Promise.all([
261
+ {{orderedLockCall}}(['A', 'B']),
262
+ {{orderedLockCall}}(['A', 'B']),
263
+ ]);
264
+
265
+ expect(r1).toBeDefined();
266
+ expect(r2).toBeDefined();
267
+ });
268
+ });
269
+ });
270
+ variables:
271
+ - name: className
272
+ type: string
273
+ description: Class name
274
+ required: true
275
+ - name: functionName
276
+ type: string
277
+ description: Function name
278
+ required: true
279
+ - name: functionCall
280
+ type: string
281
+ description: Main function call
282
+ required: true
283
+ - name: acquireLockCall
284
+ type: string
285
+ description: Acquire lock function
286
+ required: true
287
+ - name: acquireLockWithTimeoutCall
288
+ type: string
289
+ description: Acquire with timeout
290
+ required: true
291
+ - name: releaseLockCall
292
+ type: string
293
+ description: Release lock function
294
+ required: true
295
+ - name: transactionACall
296
+ type: string
297
+ description: Transaction A function
298
+ required: true
299
+ - name: transactionBCall
300
+ type: string
301
+ description: Transaction B function
302
+ required: true
303
+ - name: orderedLockCall
304
+ type: string
305
+ description: Ordered lock function
306
+ required: true
307
+ - name: modulePath
308
+ type: string
309
+ description: Module path
310
+ required: true
311
+
312
+ examples:
313
+ - name: python-lock-ordering
314
+ concept: |
315
+ Deadlock from inconsistent lock ordering. Thread A acquires lock1 then lock2,
316
+ while Thread B acquires lock2 then lock1. If both acquire their first lock
317
+ simultaneously, deadlock occurs. Always acquire locks in consistent order.
318
+ vulnerableCode: |
319
+ lock1 = threading.Lock()
320
+ lock2 = threading.Lock()
321
+
322
+ def task_a():
323
+ with lock1: # Gets lock1
324
+ time.sleep(0.1)
325
+ with lock2: # Waits for lock2
326
+ pass
327
+
328
+ def task_b():
329
+ with lock2: # Gets lock2
330
+ time.sleep(0.1)
331
+ with lock1: # Waits for lock1 - DEADLOCK
332
+ pass
333
+ testCode: |
334
+ import threading
335
+
336
+ def test_no_deadlock():
337
+ completed = []
338
+
339
+ t1 = threading.Thread(target=task_a)
340
+ t2 = threading.Thread(target=task_b)
341
+
342
+ t1.start()
343
+ t2.start()
344
+
345
+ t1.join(timeout=2)
346
+ t2.join(timeout=2)
347
+
348
+ assert not t1.is_alive() and not t2.is_alive()
349
+ language: python
350
+ severity: critical
351
+
352
+ - name: database-transaction-deadlock
353
+ concept: |
354
+ Database deadlock from conflicting row locks. Two transactions update rows
355
+ in opposite order. Transaction A locks row 1, Transaction B locks row 2,
356
+ then each tries to lock the other's row. Use consistent ordering or retry.
357
+ vulnerableCode: |
358
+ async function transferA() {
359
+ await db.transaction(async (tx) => {
360
+ await tx.update('accounts', { id: 1 }, { balance: 100 });
361
+ await delay(100);
362
+ await tx.update('accounts', { id: 2 }, { balance: 200 });
363
+ });
364
+ }
365
+
366
+ async function transferB() {
367
+ await db.transaction(async (tx) => {
368
+ await tx.update('accounts', { id: 2 }, { balance: 300 });
369
+ await delay(100);
370
+ await tx.update('accounts', { id: 1 }, { balance: 400 }); // DEADLOCK
371
+ });
372
+ }
373
+ testCode: |
374
+ describe('transfer deadlock', () => {
375
+ it('handles deadlock with retry', async () => {
376
+ const results = await Promise.allSettled([
377
+ transferA(),
378
+ transferB(),
379
+ ]);
380
+
381
+ // Should retry and succeed
382
+ const successes = results.filter(r => r.status === 'fulfilled');
383
+ expect(successes.length).toBe(2);
384
+ });
385
+ });
386
+ language: typescript
387
+ severity: high
388
+
389
+ - name: async-mutex-deadlock
390
+ concept: |
391
+ Deadlock with async mutexes. Even in single-threaded JavaScript, async
392
+ mutexes can deadlock if acquired in inconsistent order across different
393
+ async functions.
394
+ vulnerableCode: |
395
+ const mutexA = new Mutex();
396
+ const mutexB = new Mutex();
397
+
398
+ async function operationX() {
399
+ const releaseA = await mutexA.acquire();
400
+ await delay(10);
401
+ const releaseB = await mutexB.acquire(); // Waits
402
+ releaseB();
403
+ releaseA();
404
+ }
405
+
406
+ async function operationY() {
407
+ const releaseB = await mutexB.acquire();
408
+ await delay(10);
409
+ const releaseA = await mutexA.acquire(); // DEADLOCK
410
+ releaseA();
411
+ releaseB();
412
+ }
413
+ testCode: |
414
+ describe('async mutex deadlock', () => {
415
+ it('uses consistent lock ordering', async () => {
416
+ await Promise.race([
417
+ Promise.all([operationX(), operationY()]),
418
+ delay(1000).then(() => { throw new Error('Deadlock'); }),
419
+ ]);
420
+ });
421
+ });
422
+ language: typescript
423
+ severity: high
424
+
425
+ createdAt: 2024-01-01
426
+ updatedAt: 2024-01-01