pysentry-rs 0.2.1__tar.gz → 0.2.2__tar.gz

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.

Potentially problematic release.


This version of pysentry-rs might be problematic. Click here for more details.

Files changed (50) hide show
  1. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/Cargo.lock +74 -1
  2. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/Cargo.toml +3 -1
  3. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/PKG-INFO +147 -35
  4. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/README.md +146 -34
  5. pysentry_rs-0.2.2/python/pysentry/__init__.py +24 -0
  6. pysentry_rs-0.2.2/src/cache/audit.rs +502 -0
  7. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/cache/storage.rs +2 -0
  8. pysentry_rs-0.2.1/src/main.rs → pysentry_rs-0.2.2/src/cli.rs +76 -378
  9. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/dependency/resolvers/mod.rs +126 -29
  10. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/dependency/resolvers/pip_tools.rs +187 -1
  11. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/dependency/resolvers/uv.rs +178 -1
  12. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/dependency/scanner.rs +1 -1
  13. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/lib.rs +5 -1
  14. pysentry_rs-0.2.2/src/main.rs +67 -0
  15. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/parsers/mod.rs +1 -1
  16. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/parsers/pyproject.rs +2 -2
  17. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/parsers/requirements.rs +3 -3
  18. pysentry_rs-0.2.2/src/python.rs +87 -0
  19. pysentry_rs-0.2.2/src/types.rs +156 -0
  20. pysentry_rs-0.2.1/python/pysentry/__init__.py +0 -292
  21. pysentry_rs-0.2.1/python/pysentry/__main__.py +0 -6
  22. pysentry_rs-0.2.1/src/cache/audit.rs +0 -76
  23. pysentry_rs-0.2.1/src/python.rs +0 -486
  24. pysentry_rs-0.2.1/src/types.rs +0 -89
  25. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/.github/FUNDING.yml +0 -0
  26. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/.github/dependabot.yml +0 -0
  27. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/.github/workflows/ci.yml +0 -0
  28. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/.github/workflows/release.yml +0 -0
  29. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/.gitignore +0 -0
  30. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/.pre-commit-config.yaml +0 -0
  31. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/LICENSE +0 -0
  32. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/fixtures/requirements-tests/requirements-dev.txt +0 -0
  33. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/fixtures/requirements-tests/requirements.txt +0 -0
  34. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/fixtures/requirements-tests-vulnerable/requirements.txt +0 -0
  35. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/pyproject.toml +0 -0
  36. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/cache/mod.rs +0 -0
  37. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/dependency/mod.rs +0 -0
  38. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/error.rs +0 -0
  39. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/output/mod.rs +0 -0
  40. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/output/report.rs +0 -0
  41. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/output/sarif.rs +0 -0
  42. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/parsers/lock.rs +0 -0
  43. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/parsers/poetry_lock.rs +0 -0
  44. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/providers/mod.rs +0 -0
  45. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/providers/osv.rs +0 -0
  46. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/providers/pypa.rs +0 -0
  47. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/providers/pypi.rs +0 -0
  48. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/vulnerability/database.rs +0 -0
  49. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/vulnerability/matcher.rs +0 -0
  50. {pysentry_rs-0.2.1 → pysentry_rs-0.2.2}/src/vulnerability/mod.rs +0 -0
@@ -150,6 +150,15 @@ version = "2.9.1"
150
150
  source = "registry+https://github.com/rust-lang/crates.io-index"
151
151
  checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
152
152
 
153
+ [[package]]
154
+ name = "block-buffer"
155
+ version = "0.10.4"
156
+ source = "registry+https://github.com/rust-lang/crates.io-index"
157
+ checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
158
+ dependencies = [
159
+ "generic-array",
160
+ ]
161
+
153
162
  [[package]]
154
163
  name = "bumpalo"
155
164
  version = "3.19.0"
@@ -250,6 +259,15 @@ version = "0.8.7"
250
259
  source = "registry+https://github.com/rust-lang/crates.io-index"
251
260
  checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
252
261
 
262
+ [[package]]
263
+ name = "cpufeatures"
264
+ version = "0.2.17"
265
+ source = "registry+https://github.com/rust-lang/crates.io-index"
266
+ checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
267
+ dependencies = [
268
+ "libc",
269
+ ]
270
+
253
271
  [[package]]
254
272
  name = "crc32fast"
255
273
  version = "1.5.0"
@@ -259,6 +277,16 @@ dependencies = [
259
277
  "cfg-if",
260
278
  ]
261
279
 
280
+ [[package]]
281
+ name = "crypto-common"
282
+ version = "0.1.6"
283
+ source = "registry+https://github.com/rust-lang/crates.io-index"
284
+ checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
285
+ dependencies = [
286
+ "generic-array",
287
+ "typenum",
288
+ ]
289
+
262
290
  [[package]]
263
291
  name = "derive_arbitrary"
264
292
  version = "1.4.1"
@@ -270,6 +298,16 @@ dependencies = [
270
298
  "syn",
271
299
  ]
272
300
 
301
+ [[package]]
302
+ name = "digest"
303
+ version = "0.10.7"
304
+ source = "registry+https://github.com/rust-lang/crates.io-index"
305
+ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
306
+ dependencies = [
307
+ "block-buffer",
308
+ "crypto-common",
309
+ ]
310
+
273
311
  [[package]]
274
312
  name = "dirs"
275
313
  version = "6.0.0"
@@ -448,6 +486,16 @@ dependencies = [
448
486
  "slab",
449
487
  ]
450
488
 
489
+ [[package]]
490
+ name = "generic-array"
491
+ version = "0.14.7"
492
+ source = "registry+https://github.com/rust-lang/crates.io-index"
493
+ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
494
+ dependencies = [
495
+ "typenum",
496
+ "version_check",
497
+ ]
498
+
451
499
  [[package]]
452
500
  name = "getrandom"
453
501
  version = "0.2.16"
@@ -1067,7 +1115,7 @@ dependencies = [
1067
1115
 
1068
1116
  [[package]]
1069
1117
  name = "pysentry"
1070
- version = "0.2.1"
1118
+ version = "0.2.2"
1071
1119
  dependencies = [
1072
1120
  "anyhow",
1073
1121
  "async-trait",
@@ -1078,10 +1126,12 @@ dependencies = [
1078
1126
  "futures",
1079
1127
  "pep440_rs",
1080
1128
  "pyo3",
1129
+ "regex",
1081
1130
  "reqwest",
1082
1131
  "serde",
1083
1132
  "serde_json",
1084
1133
  "serde_yaml",
1134
+ "sha2",
1085
1135
  "tempfile",
1086
1136
  "thiserror",
1087
1137
  "tokio",
@@ -1438,6 +1488,17 @@ dependencies = [
1438
1488
  "unsafe-libyaml",
1439
1489
  ]
1440
1490
 
1491
+ [[package]]
1492
+ name = "sha2"
1493
+ version = "0.10.9"
1494
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1495
+ checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
1496
+ dependencies = [
1497
+ "cfg-if",
1498
+ "cpufeatures",
1499
+ "digest",
1500
+ ]
1501
+
1441
1502
  [[package]]
1442
1503
  name = "sharded-slab"
1443
1504
  version = "0.1.7"
@@ -1826,6 +1887,12 @@ version = "0.2.5"
1826
1887
  source = "registry+https://github.com/rust-lang/crates.io-index"
1827
1888
  checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
1828
1889
 
1890
+ [[package]]
1891
+ name = "typenum"
1892
+ version = "1.18.0"
1893
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1894
+ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
1895
+
1829
1896
  [[package]]
1830
1897
  name = "unicode-ident"
1831
1898
  version = "1.0.18"
@@ -1891,6 +1958,12 @@ version = "0.1.1"
1891
1958
  source = "registry+https://github.com/rust-lang/crates.io-index"
1892
1959
  checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
1893
1960
 
1961
+ [[package]]
1962
+ name = "version_check"
1963
+ version = "0.9.5"
1964
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1965
+ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
1966
+
1894
1967
  [[package]]
1895
1968
  name = "want"
1896
1969
  version = "0.3.1"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "pysentry"
3
- version = "0.2.1"
3
+ version = "0.2.2"
4
4
  edition = "2021"
5
5
  rust-version = "1.79"
6
6
  description = "Security vulnerability auditing for Python packages"
@@ -31,10 +31,12 @@ fs-err = "3.1.1"
31
31
  futures = "0.3.31"
32
32
  pep440_rs = "0.7.3"
33
33
  pyo3 = { version = "0.25.1", features = ["extension-module"], optional = true }
34
+ regex = "1.11.1"
34
35
  reqwest = { version = "0.12.22", features = ["json", "stream", "rustls-tls"], default-features = false }
35
36
  serde = { version = "1.0.219", features = ["derive"] }
36
37
  serde_json = "1.0.142"
37
38
  serde_yaml = "0.9.34"
39
+ sha2 = "0.10.9"
38
40
  tempfile = "3.20.0"
39
41
  thiserror = "2.0.12"
40
42
  tokio = { version = "1.47.1", features = ["fs", "io-util", "rt-multi-thread", "macros", "process"] }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pysentry-rs
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
@@ -48,7 +48,7 @@ PySentry audits Python projects for known security vulnerabilities by analyzing
48
48
  - **Performance Focused**:
49
49
  - Written in Rust for speed
50
50
  - Async/concurrent processing
51
- - Intelligent caching system
51
+ - Multi-tier intelligent caching (vulnerability data + resolved dependencies)
52
52
  - **Comprehensive Filtering**:
53
53
  - Severity levels (low, medium, high, critical)
54
54
  - Dependency scopes (main only vs all [optional, dev, prod, etc] dependencies)
@@ -254,6 +254,12 @@ pysentry /path/to/project
254
254
 
255
255
  # Debug requirements.txt resolution
256
256
  pysentry --verbose --resolver uv /path/to/project
257
+
258
+ # Use longer resolution cache TTL (48 hours)
259
+ pysentry --resolution-cache-ttl 48 /path/to/project
260
+
261
+ # Clear resolution cache before scanning
262
+ pysentry --clear-resolution-cache /path/to/project
257
263
  ```
258
264
 
259
265
  ### CI/CD Integration Examples
@@ -273,42 +279,115 @@ pysentry --format markdown --output SECURITY-REPORT.md
273
279
 
274
280
  # Comprehensive audit with all sources and full reporting
275
281
  pysentry --sources pypa,pypi,osv --all-extras --format json --fail-on low
282
+
283
+ # CI environment with fresh resolution cache
284
+ pysentry --clear-resolution-cache --sources pypa,osv --format sarif
285
+
286
+ # CI with resolution cache disabled
287
+ pysentry --no-resolution-cache --format json --output security-report.json
276
288
  ```
277
289
 
278
290
  ## Configuration
279
291
 
280
292
  ### Command Line Options
281
293
 
282
- | Option | Description | Default |
283
- | ---------------- | ------------------------------------------------------- | ------------------- |
284
- | `--format` | Output format: `human`, `json`, `sarif`, `markdown` | `human` |
285
- | `--severity` | Minimum severity: `low`, `medium`, `high`, `critical` | `low` |
286
- | `--fail-on` | Fail (exit non-zero) on vulnerabilities ≥ severity | `medium` |
287
- | `--sources` | Vulnerability sources: `pypa`, `pypi`, `osv` (multiple) | `pypa` |
288
- | `--all-extras` | Include all dependencies (main + dev + optional) | `false` |
289
- | `--direct-only` | Check only direct dependencies | `false` |
290
- | `--ignore` | Vulnerability IDs to ignore (repeatable) | `[]` |
291
- | `--output` | Output file path | `stdout` |
292
- | `--no-cache` | Disable caching | `false` |
293
- | `--cache-dir` | Custom cache directory | `~/.cache/pysentry` |
294
- | `--verbose` | Enable verbose output | `false` |
295
- | `--quiet` | Suppress non-error output | `false` |
296
- | `--resolver` | Dependency resolver: `auto`, `uv`, `pip-tools` | `auto` |
297
- | `--requirements` | Additional requirements files (repeatable) | `[]` |
294
+ | Option | Description | Default |
295
+ | -------------------------- | ------------------------------------------------------- | ----------------- |
296
+ | `--format` | Output format: `human`, `json`, `sarif`, `markdown` | `human` |
297
+ | `--severity` | Minimum severity: `low`, `medium`, `high`, `critical` | `low` |
298
+ | `--fail-on` | Fail (exit non-zero) on vulnerabilities ≥ severity | `medium` |
299
+ | `--sources` | Vulnerability sources: `pypa`, `pypi`, `osv` (multiple) | `pypa` |
300
+ | `--all-extras` | Include all dependencies (main + dev + optional) | `false` |
301
+ | `--direct-only` | Check only direct dependencies | `false` |
302
+ | `--ignore` | Vulnerability IDs to ignore (repeatable) | `[]` |
303
+ | `--output` | Output file path | `stdout` |
304
+ | `--no-cache` | Disable all caching | `false` |
305
+ | `--cache-dir` | Custom cache directory | Platform-specific |
306
+ | `--resolution-cache-ttl` | Resolution cache TTL in hours | `24` |
307
+ | `--no-resolution-cache` | Disable resolution caching only | `false` |
308
+ | `--clear-resolution-cache` | Clear resolution cache on startup | `false` |
309
+ | `--verbose` | Enable verbose output | `false` |
310
+ | `--quiet` | Suppress non-error output | `false` |
311
+ | `--resolver` | Dependency resolver: `auto`, `uv`, `pip-tools` | `auto` |
312
+ | `--requirements` | Additional requirements files (repeatable) | `[]` |
298
313
 
299
314
  ### Cache Management
300
315
 
301
- PySentry uses an intelligent caching system to avoid redundant API calls:
316
+ PySentry uses an intelligent multi-tier caching system for optimal performance:
317
+
318
+ #### Vulnerability Data Cache
319
+
320
+ - **Location**: `{CACHE_DIR}/pysentry/vulnerability-db/`
321
+ - **Purpose**: Caches vulnerability databases from PyPA, PyPI, OSV
322
+ - **TTL**: 24 hours (configurable per source)
323
+ - **Benefits**: Avoids redundant API calls and downloads
324
+
325
+ #### Resolution Cache
326
+
327
+ - **Location**: `{CACHE_DIR}/pysentry/dependency-resolution/`
328
+ - **Purpose**: Caches resolved dependencies from `uv`/`pip-tools`
329
+ - **TTL**: 24 hours (configurable via `--resolution-cache-ttl`)
330
+ - **Benefits**: Dramatically speeds up repeated scans of requirements.txt files
331
+ - **Cache Key**: Based on requirements content, resolver version, Python version, platform
332
+
333
+ #### Platform-Specific Cache Locations
334
+
335
+ - **Linux**: `~/.cache/pysentry/`
336
+ - **macOS**: `~/Library/Caches/pysentry/`
337
+ - **Windows**: `%LOCALAPPDATA%\pysentry\`
338
+
339
+ **Finding Your Cache Location**: Run with `--verbose` to see the actual cache directory path being used.
340
+
341
+ #### Cache Features
302
342
 
303
- - **Default Location**: `~/.cache/pysentry/` (or system temp directory)
304
- - **TTL-based Expiration**: Separate expiration for each vulnerability source
305
343
  - **Atomic Updates**: Prevents cache corruption during concurrent access
306
344
  - **Custom Location**: Use `--cache-dir` to specify alternative location
345
+ - **Selective Clearing**: Control caching behavior per cache type
346
+ - **Content-based Invalidation**: Automatic cache invalidation on content changes
307
347
 
308
- To clear the cache:
348
+ #### Cache Control Examples
309
349
 
310
350
  ```bash
351
+ # Disable all caching
352
+ pysentry --no-cache
353
+
354
+ # Disable only resolution caching (keep vulnerability cache)
355
+ pysentry --no-resolution-cache
356
+
357
+ # Set resolution cache TTL to 48 hours
358
+ pysentry --resolution-cache-ttl 48
359
+
360
+ # Clear resolution cache on startup (useful for CI)
361
+ pysentry --clear-resolution-cache
362
+
363
+ # Custom cache directory
364
+ pysentry --cache-dir /tmp/my-pysentry-cache
365
+ ```
366
+
367
+ To manually clear all caches:
368
+
369
+ ```bash
370
+ # Linux
311
371
  rm -rf ~/.cache/pysentry/
372
+
373
+ # macOS
374
+ rm -rf ~/Library/Caches/pysentry/
375
+
376
+ # Windows (PowerShell)
377
+ Remove-Item -Recurse -Force "$env:LOCALAPPDATA\pysentry"
378
+ ```
379
+
380
+ To clear only resolution cache:
381
+
382
+ ```bash
383
+ # Linux
384
+ rm -rf ~/.cache/pysentry/dependency-resolution/
385
+
386
+ # macOS
387
+ rm -rf ~/Library/Caches/pysentry/dependency-resolution/
388
+
389
+ # Windows (PowerShell)
390
+ Remove-Item -Recurse -Force "$env:LOCALAPPDATA\pysentry\dependency-resolution"
312
391
  ```
313
392
 
314
393
  ## Supported Project Formats
@@ -437,26 +516,28 @@ Compatible with GitHub Security tab, VS Code, and other security tools.
437
516
 
438
517
  PySentry is designed for speed and efficiency:
439
518
 
440
- - **Concurrent Processing**: Vulnerability data fetched in parallel
441
- - **Smart Caching**: Reduces API calls and parsing overhead
519
+ - **Concurrent Processing**: Vulnerability data fetched in parallel from multiple sources
520
+ - **Multi-tier Caching**: Intelligent caching for both vulnerability data and resolved dependencies
442
521
  - **Efficient Matching**: In-memory indexing for fast vulnerability lookups
443
522
  - **Streaming**: Large databases processed without excessive memory usage
444
523
 
524
+ ### Resolution Cache Performance
525
+
526
+ The resolution cache provides dramatic performance improvements for requirements.txt files:
527
+
528
+ - **First scan**: Standard resolution time using `uv` or `pip-tools`
529
+ - **Subsequent scans**: Near-instantaneous when cache is fresh (>90% time savings)
530
+ - **Cache invalidation**: Automatic when requirements content, resolver, or environment changes
531
+ - **Content-aware**: Different cache entries for different Python versions and platforms
532
+
445
533
  ### Requirements.txt Resolution Performance
446
534
 
447
- PySentry leverages external resolvers for optimal performance:
535
+ PySentry leverages external resolvers with intelligent caching:
448
536
 
449
537
  - **uv resolver**: 2-10x faster than pip-tools, handles large dependency trees efficiently
450
538
  - **pip-tools resolver**: Reliable fallback, slower but widely compatible
451
539
  - **Isolated execution**: Prevents project pollution while maintaining security
452
-
453
- ### Benchmarks
454
-
455
- Typical performance on a project with 100+ dependencies:
456
-
457
- - **Cold cache**: 15-30 seconds
458
- - **Warm cache**: 2-5 seconds
459
- - **Memory usage**: ~50MB peak
540
+ - **Resolution caching**: Eliminates repeated resolver calls for unchanged requirements
460
541
 
461
542
  ## Development
462
543
 
@@ -581,12 +662,43 @@ ls uv.lock poetry.lock pyproject.toml
581
662
  **Performance Issues**
582
663
 
583
664
  ```bash
584
- # Clear cache and retry
585
- rm -rf ~/.cache/pysentry
665
+ # Clear all caches and retry
666
+ rm -rf ~/.cache/pysentry # Linux
667
+ rm -rf ~/Library/Caches/pysentry # macOS
668
+ pysentry
669
+
670
+ # Clear only resolution cache (if vulnerability cache is working)
671
+ rm -rf ~/.cache/pysentry/dependency-resolution/ # Linux
672
+ rm -rf ~/Library/Caches/pysentry/dependency-resolution/ # macOS
586
673
  pysentry
587
674
 
675
+ # Clear resolution cache via CLI
676
+ pysentry --clear-resolution-cache
677
+
588
678
  # Use verbose mode to identify bottlenecks
589
679
  pysentry --verbose
680
+
681
+ # Disable caching to isolate issues
682
+ pysentry --no-cache
683
+ ```
684
+
685
+ **Resolution Cache Issues**
686
+
687
+ ```bash
688
+ # Clear stale resolution cache after environment changes
689
+ pysentry --clear-resolution-cache
690
+
691
+ # Disable resolution cache if causing issues
692
+ pysentry --no-resolution-cache
693
+
694
+ # Extend cache TTL for stable environments
695
+ pysentry --resolution-cache-ttl 168 # 1 week
696
+
697
+ # Check cache usage with verbose output
698
+ pysentry --verbose # Shows cache hits/misses
699
+
700
+ # Force fresh resolution (ignores cache)
701
+ pysentry --clear-resolution-cache --no-resolution-cache
590
702
  ```
591
703
 
592
704
  ## Acknowledgments
@@ -22,7 +22,7 @@ PySentry audits Python projects for known security vulnerabilities by analyzing
22
22
  - **Performance Focused**:
23
23
  - Written in Rust for speed
24
24
  - Async/concurrent processing
25
- - Intelligent caching system
25
+ - Multi-tier intelligent caching (vulnerability data + resolved dependencies)
26
26
  - **Comprehensive Filtering**:
27
27
  - Severity levels (low, medium, high, critical)
28
28
  - Dependency scopes (main only vs all [optional, dev, prod, etc] dependencies)
@@ -228,6 +228,12 @@ pysentry /path/to/project
228
228
 
229
229
  # Debug requirements.txt resolution
230
230
  pysentry --verbose --resolver uv /path/to/project
231
+
232
+ # Use longer resolution cache TTL (48 hours)
233
+ pysentry --resolution-cache-ttl 48 /path/to/project
234
+
235
+ # Clear resolution cache before scanning
236
+ pysentry --clear-resolution-cache /path/to/project
231
237
  ```
232
238
 
233
239
  ### CI/CD Integration Examples
@@ -247,42 +253,115 @@ pysentry --format markdown --output SECURITY-REPORT.md
247
253
 
248
254
  # Comprehensive audit with all sources and full reporting
249
255
  pysentry --sources pypa,pypi,osv --all-extras --format json --fail-on low
256
+
257
+ # CI environment with fresh resolution cache
258
+ pysentry --clear-resolution-cache --sources pypa,osv --format sarif
259
+
260
+ # CI with resolution cache disabled
261
+ pysentry --no-resolution-cache --format json --output security-report.json
250
262
  ```
251
263
 
252
264
  ## Configuration
253
265
 
254
266
  ### Command Line Options
255
267
 
256
- | Option | Description | Default |
257
- | ---------------- | ------------------------------------------------------- | ------------------- |
258
- | `--format` | Output format: `human`, `json`, `sarif`, `markdown` | `human` |
259
- | `--severity` | Minimum severity: `low`, `medium`, `high`, `critical` | `low` |
260
- | `--fail-on` | Fail (exit non-zero) on vulnerabilities ≥ severity | `medium` |
261
- | `--sources` | Vulnerability sources: `pypa`, `pypi`, `osv` (multiple) | `pypa` |
262
- | `--all-extras` | Include all dependencies (main + dev + optional) | `false` |
263
- | `--direct-only` | Check only direct dependencies | `false` |
264
- | `--ignore` | Vulnerability IDs to ignore (repeatable) | `[]` |
265
- | `--output` | Output file path | `stdout` |
266
- | `--no-cache` | Disable caching | `false` |
267
- | `--cache-dir` | Custom cache directory | `~/.cache/pysentry` |
268
- | `--verbose` | Enable verbose output | `false` |
269
- | `--quiet` | Suppress non-error output | `false` |
270
- | `--resolver` | Dependency resolver: `auto`, `uv`, `pip-tools` | `auto` |
271
- | `--requirements` | Additional requirements files (repeatable) | `[]` |
268
+ | Option | Description | Default |
269
+ | -------------------------- | ------------------------------------------------------- | ----------------- |
270
+ | `--format` | Output format: `human`, `json`, `sarif`, `markdown` | `human` |
271
+ | `--severity` | Minimum severity: `low`, `medium`, `high`, `critical` | `low` |
272
+ | `--fail-on` | Fail (exit non-zero) on vulnerabilities ≥ severity | `medium` |
273
+ | `--sources` | Vulnerability sources: `pypa`, `pypi`, `osv` (multiple) | `pypa` |
274
+ | `--all-extras` | Include all dependencies (main + dev + optional) | `false` |
275
+ | `--direct-only` | Check only direct dependencies | `false` |
276
+ | `--ignore` | Vulnerability IDs to ignore (repeatable) | `[]` |
277
+ | `--output` | Output file path | `stdout` |
278
+ | `--no-cache` | Disable all caching | `false` |
279
+ | `--cache-dir` | Custom cache directory | Platform-specific |
280
+ | `--resolution-cache-ttl` | Resolution cache TTL in hours | `24` |
281
+ | `--no-resolution-cache` | Disable resolution caching only | `false` |
282
+ | `--clear-resolution-cache` | Clear resolution cache on startup | `false` |
283
+ | `--verbose` | Enable verbose output | `false` |
284
+ | `--quiet` | Suppress non-error output | `false` |
285
+ | `--resolver` | Dependency resolver: `auto`, `uv`, `pip-tools` | `auto` |
286
+ | `--requirements` | Additional requirements files (repeatable) | `[]` |
272
287
 
273
288
  ### Cache Management
274
289
 
275
- PySentry uses an intelligent caching system to avoid redundant API calls:
290
+ PySentry uses an intelligent multi-tier caching system for optimal performance:
291
+
292
+ #### Vulnerability Data Cache
293
+
294
+ - **Location**: `{CACHE_DIR}/pysentry/vulnerability-db/`
295
+ - **Purpose**: Caches vulnerability databases from PyPA, PyPI, OSV
296
+ - **TTL**: 24 hours (configurable per source)
297
+ - **Benefits**: Avoids redundant API calls and downloads
298
+
299
+ #### Resolution Cache
300
+
301
+ - **Location**: `{CACHE_DIR}/pysentry/dependency-resolution/`
302
+ - **Purpose**: Caches resolved dependencies from `uv`/`pip-tools`
303
+ - **TTL**: 24 hours (configurable via `--resolution-cache-ttl`)
304
+ - **Benefits**: Dramatically speeds up repeated scans of requirements.txt files
305
+ - **Cache Key**: Based on requirements content, resolver version, Python version, platform
306
+
307
+ #### Platform-Specific Cache Locations
308
+
309
+ - **Linux**: `~/.cache/pysentry/`
310
+ - **macOS**: `~/Library/Caches/pysentry/`
311
+ - **Windows**: `%LOCALAPPDATA%\pysentry\`
312
+
313
+ **Finding Your Cache Location**: Run with `--verbose` to see the actual cache directory path being used.
314
+
315
+ #### Cache Features
276
316
 
277
- - **Default Location**: `~/.cache/pysentry/` (or system temp directory)
278
- - **TTL-based Expiration**: Separate expiration for each vulnerability source
279
317
  - **Atomic Updates**: Prevents cache corruption during concurrent access
280
318
  - **Custom Location**: Use `--cache-dir` to specify alternative location
319
+ - **Selective Clearing**: Control caching behavior per cache type
320
+ - **Content-based Invalidation**: Automatic cache invalidation on content changes
281
321
 
282
- To clear the cache:
322
+ #### Cache Control Examples
283
323
 
284
324
  ```bash
325
+ # Disable all caching
326
+ pysentry --no-cache
327
+
328
+ # Disable only resolution caching (keep vulnerability cache)
329
+ pysentry --no-resolution-cache
330
+
331
+ # Set resolution cache TTL to 48 hours
332
+ pysentry --resolution-cache-ttl 48
333
+
334
+ # Clear resolution cache on startup (useful for CI)
335
+ pysentry --clear-resolution-cache
336
+
337
+ # Custom cache directory
338
+ pysentry --cache-dir /tmp/my-pysentry-cache
339
+ ```
340
+
341
+ To manually clear all caches:
342
+
343
+ ```bash
344
+ # Linux
285
345
  rm -rf ~/.cache/pysentry/
346
+
347
+ # macOS
348
+ rm -rf ~/Library/Caches/pysentry/
349
+
350
+ # Windows (PowerShell)
351
+ Remove-Item -Recurse -Force "$env:LOCALAPPDATA\pysentry"
352
+ ```
353
+
354
+ To clear only resolution cache:
355
+
356
+ ```bash
357
+ # Linux
358
+ rm -rf ~/.cache/pysentry/dependency-resolution/
359
+
360
+ # macOS
361
+ rm -rf ~/Library/Caches/pysentry/dependency-resolution/
362
+
363
+ # Windows (PowerShell)
364
+ Remove-Item -Recurse -Force "$env:LOCALAPPDATA\pysentry\dependency-resolution"
286
365
  ```
287
366
 
288
367
  ## Supported Project Formats
@@ -411,26 +490,28 @@ Compatible with GitHub Security tab, VS Code, and other security tools.
411
490
 
412
491
  PySentry is designed for speed and efficiency:
413
492
 
414
- - **Concurrent Processing**: Vulnerability data fetched in parallel
415
- - **Smart Caching**: Reduces API calls and parsing overhead
493
+ - **Concurrent Processing**: Vulnerability data fetched in parallel from multiple sources
494
+ - **Multi-tier Caching**: Intelligent caching for both vulnerability data and resolved dependencies
416
495
  - **Efficient Matching**: In-memory indexing for fast vulnerability lookups
417
496
  - **Streaming**: Large databases processed without excessive memory usage
418
497
 
498
+ ### Resolution Cache Performance
499
+
500
+ The resolution cache provides dramatic performance improvements for requirements.txt files:
501
+
502
+ - **First scan**: Standard resolution time using `uv` or `pip-tools`
503
+ - **Subsequent scans**: Near-instantaneous when cache is fresh (>90% time savings)
504
+ - **Cache invalidation**: Automatic when requirements content, resolver, or environment changes
505
+ - **Content-aware**: Different cache entries for different Python versions and platforms
506
+
419
507
  ### Requirements.txt Resolution Performance
420
508
 
421
- PySentry leverages external resolvers for optimal performance:
509
+ PySentry leverages external resolvers with intelligent caching:
422
510
 
423
511
  - **uv resolver**: 2-10x faster than pip-tools, handles large dependency trees efficiently
424
512
  - **pip-tools resolver**: Reliable fallback, slower but widely compatible
425
513
  - **Isolated execution**: Prevents project pollution while maintaining security
426
-
427
- ### Benchmarks
428
-
429
- Typical performance on a project with 100+ dependencies:
430
-
431
- - **Cold cache**: 15-30 seconds
432
- - **Warm cache**: 2-5 seconds
433
- - **Memory usage**: ~50MB peak
514
+ - **Resolution caching**: Eliminates repeated resolver calls for unchanged requirements
434
515
 
435
516
  ## Development
436
517
 
@@ -555,12 +636,43 @@ ls uv.lock poetry.lock pyproject.toml
555
636
  **Performance Issues**
556
637
 
557
638
  ```bash
558
- # Clear cache and retry
559
- rm -rf ~/.cache/pysentry
639
+ # Clear all caches and retry
640
+ rm -rf ~/.cache/pysentry # Linux
641
+ rm -rf ~/Library/Caches/pysentry # macOS
642
+ pysentry
643
+
644
+ # Clear only resolution cache (if vulnerability cache is working)
645
+ rm -rf ~/.cache/pysentry/dependency-resolution/ # Linux
646
+ rm -rf ~/Library/Caches/pysentry/dependency-resolution/ # macOS
560
647
  pysentry
561
648
 
649
+ # Clear resolution cache via CLI
650
+ pysentry --clear-resolution-cache
651
+
562
652
  # Use verbose mode to identify bottlenecks
563
653
  pysentry --verbose
654
+
655
+ # Disable caching to isolate issues
656
+ pysentry --no-cache
657
+ ```
658
+
659
+ **Resolution Cache Issues**
660
+
661
+ ```bash
662
+ # Clear stale resolution cache after environment changes
663
+ pysentry --clear-resolution-cache
664
+
665
+ # Disable resolution cache if causing issues
666
+ pysentry --no-resolution-cache
667
+
668
+ # Extend cache TTL for stable environments
669
+ pysentry --resolution-cache-ttl 168 # 1 week
670
+
671
+ # Check cache usage with verbose output
672
+ pysentry --verbose # Shows cache hits/misses
673
+
674
+ # Force fresh resolution (ignores cache)
675
+ pysentry --clear-resolution-cache --no-resolution-cache
564
676
  ```
565
677
 
566
678
  ## Acknowledgments