pysentry-rs 0.3.6__tar.gz → 0.3.7__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 (76) hide show
  1. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/Cargo.lock +14 -14
  2. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/Cargo.toml +6 -6
  3. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/PKG-INFO +5 -5
  4. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/README.md +4 -4
  5. pysentry_rs-0.3.7/benchmarks/results/0.3.6.md +141 -0
  6. pysentry_rs-0.3.7/benchmarks/results/latest.md +141 -0
  7. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/cli.rs +17 -0
  8. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/config.rs +4 -0
  9. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/error.rs +1 -1
  10. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/lib.rs +8 -1
  11. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/output/report.rs +27 -2
  12. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/output/sarif.rs +12 -0
  13. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/parsers/mod.rs +3 -0
  14. pysentry_rs-0.3.7/src/parsers/pylock.rs +771 -0
  15. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/providers/osv.rs +1 -0
  16. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/providers/pypa.rs +47 -0
  17. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/providers/pypi.rs +1 -0
  18. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/vulnerability/database.rs +4 -0
  19. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/vulnerability/matcher.rs +68 -5
  20. pysentry_rs-0.3.6/benchmarks/results/latest.md +0 -141
  21. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/.github/FUNDING.yml +0 -0
  22. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/.github/dependabot.yml +0 -0
  23. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/.github/workflows/benchmark.yml +0 -0
  24. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/.github/workflows/ci.yml +0 -0
  25. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/.github/workflows/release.yml +0 -0
  26. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/.gitignore +0 -0
  27. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/.pre-commit-config.yaml +0 -0
  28. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/.pre-commit-hooks.yaml +0 -0
  29. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/LICENSE +0 -0
  30. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/.gitignore +0 -0
  31. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/.python-version +0 -0
  32. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/README.md +0 -0
  33. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/main.py +0 -0
  34. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/pyproject.toml +0 -0
  35. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/results/0.2.3.md +0 -0
  36. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/results/0.3.1.md +0 -0
  37. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/results/0.3.2.md +0 -0
  38. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/results/0.3.3.md +0 -0
  39. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/results/0.3.4.md +0 -0
  40. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/results/0.3.5.md +0 -0
  41. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/src/benchmark_runner.py +0 -0
  42. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/src/performance_monitor.py +0 -0
  43. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/src/report_generator.py +0 -0
  44. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/src/tool_wrapper.py +0 -0
  45. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/test_data/large_requirements.txt +0 -0
  46. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/test_data/small_requirements.txt +0 -0
  47. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/test_data/uv.lock +0 -0
  48. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/benchmarks/uv.lock +0 -0
  49. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/fixtures/pipfile-tests/Pipfile +0 -0
  50. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/fixtures/pipfile-tests/Pipfile.lock +0 -0
  51. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/fixtures/pipfile-vulnerable-tests/Pipfile +0 -0
  52. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/fixtures/requirements-tests/requirements-dev.txt +0 -0
  53. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/fixtures/requirements-tests/requirements.txt +0 -0
  54. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/fixtures/requirements-tests-vulnerable/requirements.txt +0 -0
  55. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/pyproject.toml +0 -0
  56. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/python/pysentry/__init__.py +0 -0
  57. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/cache/audit.rs +0 -0
  58. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/cache/mod.rs +0 -0
  59. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/cache/storage.rs +0 -0
  60. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/dependency/mod.rs +0 -0
  61. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/dependency/resolvers/mod.rs +0 -0
  62. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/dependency/resolvers/pip_tools.rs +0 -0
  63. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/dependency/resolvers/uv.rs +0 -0
  64. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/dependency/scanner.rs +0 -0
  65. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/main.rs +0 -0
  66. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/output/mod.rs +0 -0
  67. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/parsers/lock.rs +0 -0
  68. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/parsers/pipfile.rs +0 -0
  69. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/parsers/pipfile_lock.rs +0 -0
  70. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/parsers/poetry_lock.rs +0 -0
  71. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/parsers/pyproject.rs +0 -0
  72. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/parsers/requirements.rs +0 -0
  73. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/providers/mod.rs +0 -0
  74. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/python.rs +0 -0
  75. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/types.rs +0 -0
  76. {pysentry_rs-0.3.6 → pysentry_rs-0.3.7}/src/vulnerability/mod.rs +0 -0
@@ -1137,7 +1137,7 @@ dependencies = [
1137
1137
 
1138
1138
  [[package]]
1139
1139
  name = "pysentry"
1140
- version = "0.3.6"
1140
+ version = "0.3.7"
1141
1141
  dependencies = [
1142
1142
  "anyhow",
1143
1143
  "async-trait",
@@ -1277,9 +1277,9 @@ dependencies = [
1277
1277
 
1278
1278
  [[package]]
1279
1279
  name = "regex"
1280
- version = "1.11.1"
1280
+ version = "1.11.2"
1281
1281
  source = "registry+https://github.com/rust-lang/crates.io-index"
1282
- checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
1282
+ checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
1283
1283
  dependencies = [
1284
1284
  "aho-corasick",
1285
1285
  "memchr",
@@ -1512,9 +1512,9 @@ dependencies = [
1512
1512
 
1513
1513
  [[package]]
1514
1514
  name = "serde_json"
1515
- version = "1.0.142"
1515
+ version = "1.0.143"
1516
1516
  source = "registry+https://github.com/rust-lang/crates.io-index"
1517
- checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
1517
+ checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
1518
1518
  dependencies = [
1519
1519
  "itoa",
1520
1520
  "memchr",
@@ -1686,31 +1686,31 @@ checksum = "e502f78cdbb8ba4718f566c418c52bc729126ffd16baee5baa718cf25dd5a69a"
1686
1686
 
1687
1687
  [[package]]
1688
1688
  name = "tempfile"
1689
- version = "3.20.0"
1689
+ version = "3.21.0"
1690
1690
  source = "registry+https://github.com/rust-lang/crates.io-index"
1691
- checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
1691
+ checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e"
1692
1692
  dependencies = [
1693
1693
  "fastrand",
1694
1694
  "getrandom 0.3.3",
1695
1695
  "once_cell",
1696
1696
  "rustix",
1697
- "windows-sys 0.59.0",
1697
+ "windows-sys 0.60.2",
1698
1698
  ]
1699
1699
 
1700
1700
  [[package]]
1701
1701
  name = "thiserror"
1702
- version = "2.0.15"
1702
+ version = "2.0.16"
1703
1703
  source = "registry+https://github.com/rust-lang/crates.io-index"
1704
- checksum = "80d76d3f064b981389ecb4b6b7f45a0bf9fdac1d5b9204c7bd6714fecc302850"
1704
+ checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
1705
1705
  dependencies = [
1706
1706
  "thiserror-impl",
1707
1707
  ]
1708
1708
 
1709
1709
  [[package]]
1710
1710
  name = "thiserror-impl"
1711
- version = "2.0.15"
1711
+ version = "2.0.16"
1712
1712
  source = "registry+https://github.com/rust-lang/crates.io-index"
1713
- checksum = "44d29feb33e986b6ea906bd9c3559a856983f92371b3eaa5e83782a351623de0"
1713
+ checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
1714
1714
  dependencies = [
1715
1715
  "proc-macro2",
1716
1716
  "quote",
@@ -2524,9 +2524,9 @@ dependencies = [
2524
2524
 
2525
2525
  [[package]]
2526
2526
  name = "zip"
2527
- version = "4.3.0"
2527
+ version = "4.5.0"
2528
2528
  source = "registry+https://github.com/rust-lang/crates.io-index"
2529
- checksum = "9aed4ac33e8eb078c89e6cbb1d5c4c7703ec6d299fc3e7c3695af8f8b423468b"
2529
+ checksum = "8835eb39822904d39cb19465de1159e05d371973f0c6df3a365ad50565ddc8b9"
2530
2530
  dependencies = [
2531
2531
  "arbitrary",
2532
2532
  "crc32fast",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "pysentry"
3
- version = "0.3.6"
3
+ version = "0.3.7"
4
4
  edition = "2021"
5
5
  rust-version = "1.79"
6
6
  description = "Security vulnerability auditing for Python packages"
@@ -32,17 +32,17 @@ futures = "0.3.31"
32
32
  owo-colors = "4.2.2"
33
33
  pep440_rs = "0.7.3"
34
34
  pyo3 = { version = "0.25.1", features = ["extension-module"], optional = true }
35
- regex = "1.11.1"
35
+ regex = "1.11.2"
36
36
  reqwest = { version = "0.12.23", features = ["json", "stream", "rustls-tls-native-roots"], default-features = false }
37
37
  rustc-hash = "2.1.1"
38
38
  serde = { version = "1.0.219", features = ["derive"] }
39
- serde_json = "1.0.142"
39
+ serde_json = "1.0.143"
40
40
  serde_yaml = "0.9.34"
41
41
  sha2 = "0.10.9"
42
- tempfile = "3.20.0"
43
- thiserror = "2.0.15"
42
+ tempfile = "3.21.0"
43
+ thiserror = "2.0.16"
44
44
  tokio = { version = "1.47.1", features = ["fs", "io-util", "rt-multi-thread", "macros", "process"] }
45
45
  toml = "0.9.5"
46
46
  tracing = "0.1.41"
47
47
  tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
48
- zip = { version = "4.3.0", default-features = false, features = ["deflate"] }
48
+ zip = { version = "4.5.0", default-features = false, features = ["deflate"] }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pysentry-rs
3
- Version: 0.3.6
3
+ Version: 0.3.7
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)
@@ -37,11 +37,11 @@ A fast, reliable security vulnerability scanner for Python projects, written in
37
37
 
38
38
  ## Overview
39
39
 
40
- PySentry audits Python projects for known security vulnerabilities by analyzing dependency files (`uv.lock`, `poetry.lock`, `Pipfile.lock`, `pyproject.toml`, `Pipfile`, `requirements.txt`) and cross-referencing them against multiple vulnerability databases. It provides comprehensive reporting with support for various output formats and filtering options.
40
+ PySentry audits Python projects for known security vulnerabilities by analyzing dependency files (`uv.lock`, `poetry.lock`, `Pipfile.lock`, `pylock.toml`, `pyproject.toml`, `Pipfile`, `requirements.txt`) and cross-referencing them against multiple vulnerability databases. It provides comprehensive reporting with support for various output formats and filtering options.
41
41
 
42
42
  ## Key Features
43
43
 
44
- - **Multiple Project Formats**: Supports `uv.lock`, `poetry.lock`, `Pipfile.lock`, `pyproject.toml`, `Pipfile`, and `requirements.txt` files
44
+ - **Multiple Project Formats**: Supports `uv.lock`, `poetry.lock`, `Pipfile.lock`, `pylock.toml`, `pyproject.toml`, `Pipfile`, and `requirements.txt` files
45
45
  - **External Resolver Integration**: Leverages `uv` and `pip-tools` for accurate requirements.txt constraint solving
46
46
  - **Multiple Data Sources**:
47
47
  - PyPA Advisory Database (default)
@@ -301,7 +301,7 @@ Add PySentry to your `.pre-commit-config.yaml`:
301
301
  ```yaml
302
302
  repos:
303
303
  - repo: https://github.com/pysentry/pysentry-pre-commit
304
- rev: v0.3.5
304
+ rev: v0.3.6
305
305
  hooks:
306
306
  - id: pysentry # default pysentry settings
307
307
  ```
@@ -311,7 +311,7 @@ repos:
311
311
  ```yaml
312
312
  repos:
313
313
  - repo: https://github.com/pysentry/pysentry-pre-commit
314
- rev: v0.3.5
314
+ rev: v0.3.6
315
315
  hooks:
316
316
  - id: pysentry
317
317
  args: ["--sources", "pypa,osv", "--fail-on", "high"]
@@ -11,11 +11,11 @@ A fast, reliable security vulnerability scanner for Python projects, written in
11
11
 
12
12
  ## Overview
13
13
 
14
- PySentry audits Python projects for known security vulnerabilities by analyzing dependency files (`uv.lock`, `poetry.lock`, `Pipfile.lock`, `pyproject.toml`, `Pipfile`, `requirements.txt`) and cross-referencing them against multiple vulnerability databases. It provides comprehensive reporting with support for various output formats and filtering options.
14
+ PySentry audits Python projects for known security vulnerabilities by analyzing dependency files (`uv.lock`, `poetry.lock`, `Pipfile.lock`, `pylock.toml`, `pyproject.toml`, `Pipfile`, `requirements.txt`) and cross-referencing them against multiple vulnerability databases. It provides comprehensive reporting with support for various output formats and filtering options.
15
15
 
16
16
  ## Key Features
17
17
 
18
- - **Multiple Project Formats**: Supports `uv.lock`, `poetry.lock`, `Pipfile.lock`, `pyproject.toml`, `Pipfile`, and `requirements.txt` files
18
+ - **Multiple Project Formats**: Supports `uv.lock`, `poetry.lock`, `Pipfile.lock`, `pylock.toml`, `pyproject.toml`, `Pipfile`, and `requirements.txt` files
19
19
  - **External Resolver Integration**: Leverages `uv` and `pip-tools` for accurate requirements.txt constraint solving
20
20
  - **Multiple Data Sources**:
21
21
  - PyPA Advisory Database (default)
@@ -275,7 +275,7 @@ Add PySentry to your `.pre-commit-config.yaml`:
275
275
  ```yaml
276
276
  repos:
277
277
  - repo: https://github.com/pysentry/pysentry-pre-commit
278
- rev: v0.3.5
278
+ rev: v0.3.6
279
279
  hooks:
280
280
  - id: pysentry # default pysentry settings
281
281
  ```
@@ -285,7 +285,7 @@ repos:
285
285
  ```yaml
286
286
  repos:
287
287
  - repo: https://github.com/pysentry/pysentry-pre-commit
288
- rev: v0.3.5
288
+ rev: v0.3.6
289
289
  hooks:
290
290
  - id: pysentry
291
291
  args: ["--sources", "pypa,osv", "--fail-on", "high"]
@@ -0,0 +1,141 @@
1
+ # PySentry - pip-audit Benchmark Report
2
+
3
+ **Generated:** 2025-08-21 19:52:35
4
+ **Duration:** 1m 56.44s
5
+ **Total Tests:** 20
6
+
7
+ ## Executive Summary
8
+
9
+ **Overall Success Rate:** 100.0% (20/20 successful runs)
10
+
11
+ ### Small_Requirements Dataset - Cold Cache
12
+ - **Fastest:** pysentry-pypi (0.250s) - 35.37x faster than slowest
13
+ - **Memory Efficient:** pysentry-osv (11.03 MB) - 9.68x less memory than highest
14
+
15
+ ### Small_Requirements Dataset - Hot Cache
16
+ - **Fastest:** pysentry-pypi (0.221s) - 35.46x faster than slowest
17
+ - **Memory Efficient:** pysentry-osv (10.81 MB) - 9.68x less memory than highest
18
+
19
+ ### Large_Requirements Dataset - Cold Cache
20
+ - **Fastest:** pysentry-pypi (0.722s) - 27.16x faster than slowest
21
+ - **Memory Efficient:** pysentry-osv (10.93 MB) - 9.84x less memory than highest
22
+
23
+ ### Large_Requirements Dataset - Hot Cache
24
+ - **Fastest:** pysentry-pypi (0.686s) - 23.48x faster than slowest
25
+ - **Memory Efficient:** pysentry-osv (11.07 MB) - 9.83x less memory than highest
26
+
27
+ ## Test Environment
28
+
29
+ - **Platform:** Linux-6.11.0-1018-azure-x86_64-with-glibc2.39
30
+ - **Python Version:** 3.11.13
31
+ - **CPU Cores:** 4
32
+ - **Total Memory:** 15.62 GB
33
+ - **Available Memory:** 14.63 GB
34
+
35
+ ## Performance Comparison
36
+
37
+ ### Small_Requirements Dataset - Cold Cache
38
+
39
+ #### Execution Time Comparison
40
+
41
+ | Tool Configuration | Execution Time | Relative Performance |
42
+ |---------------------|---------------------|---------------------|
43
+ | 🥇 pysentry-pypi | 0.250s | 1.00x |
44
+ | 🥈 pysentry-osv | 1.045s | 4.18x |
45
+ | pysentry-all-sources | 1.152s | 4.60x |
46
+ | pysentry-pypa | 1.155s | 4.61x |
47
+ | pip-audit-default | 8.852s | 35.37x |
48
+
49
+ #### Memory Usage Comparison
50
+
51
+ | Tool Configuration | Peak Memory | Relative Performance |
52
+ |---------------------|---------------------|---------------------|
53
+ | 🥇 pysentry-osv | 11.03 MB | 1.00x |
54
+ | 🥈 pysentry-pypi | 11.64 MB | 1.06x |
55
+ | pip-audit-default | 45.64 MB | 4.14x |
56
+ | pysentry-pypa | 75.38 MB | 6.84x |
57
+ | pysentry-all-sources | 106.78 MB | 9.68x |
58
+
59
+ ### Small_Requirements Dataset - Hot Cache
60
+
61
+ #### Execution Time Comparison
62
+
63
+ | Tool Configuration | Execution Time | Relative Performance |
64
+ |---------------------|---------------------|---------------------|
65
+ | 🥇 pysentry-pypi | 0.221s | 1.00x |
66
+ | 🥈 pysentry-pypa | 0.729s | 3.29x |
67
+ | pysentry-osv | 0.982s | 4.43x |
68
+ | pysentry-all-sources | 1.112s | 5.02x |
69
+ | pip-audit-default | 7.854s | 35.46x |
70
+
71
+ #### Memory Usage Comparison
72
+
73
+ | Tool Configuration | Peak Memory | Relative Performance |
74
+ |---------------------|---------------------|---------------------|
75
+ | 🥇 pysentry-osv | 10.81 MB | 1.00x |
76
+ | 🥈 pysentry-pypi | 11.93 MB | 1.10x |
77
+ | pip-audit-default | 44.88 MB | 4.15x |
78
+ | pysentry-pypa | 69.38 MB | 6.42x |
79
+ | pysentry-all-sources | 104.60 MB | 9.68x |
80
+
81
+ ### Large_Requirements Dataset - Cold Cache
82
+
83
+ #### Execution Time Comparison
84
+
85
+ | Tool Configuration | Execution Time | Relative Performance |
86
+ |---------------------|---------------------|---------------------|
87
+ | 🥇 pysentry-pypi | 0.722s | 1.00x |
88
+ | 🥈 pysentry-pypa | 1.258s | 1.74x |
89
+ | pysentry-all-sources | 3.183s | 4.41x |
90
+ | pysentry-osv | 3.714s | 5.14x |
91
+ | pip-audit-default | 19.619s | 27.16x |
92
+
93
+ #### Memory Usage Comparison
94
+
95
+ | Tool Configuration | Peak Memory | Relative Performance |
96
+ |---------------------|---------------------|---------------------|
97
+ | 🥇 pysentry-osv | 10.93 MB | 1.00x |
98
+ | 🥈 pysentry-pypi | 14.27 MB | 1.31x |
99
+ | pip-audit-default | 47.34 MB | 4.33x |
100
+ | pysentry-pypa | 74.92 MB | 6.85x |
101
+ | pysentry-all-sources | 107.52 MB | 9.84x |
102
+
103
+ ### Large_Requirements Dataset - Hot Cache
104
+
105
+ #### Execution Time Comparison
106
+
107
+ | Tool Configuration | Execution Time | Relative Performance |
108
+ |---------------------|---------------------|---------------------|
109
+ | 🥇 pysentry-pypi | 0.686s | 1.00x |
110
+ | 🥈 pysentry-pypa | 1.206s | 1.76x |
111
+ | pysentry-all-sources | 3.464s | 5.05x |
112
+ | pysentry-osv | 3.799s | 5.54x |
113
+ | pip-audit-default | 16.105s | 23.48x |
114
+
115
+ #### Memory Usage Comparison
116
+
117
+ | Tool Configuration | Peak Memory | Relative Performance |
118
+ |---------------------|---------------------|---------------------|
119
+ | 🥇 pysentry-osv | 11.07 MB | 1.00x |
120
+ | 🥈 pysentry-pypi | 11.27 MB | 1.02x |
121
+ | pip-audit-default | 47.18 MB | 4.26x |
122
+ | pysentry-pypa | 52.84 MB | 4.77x |
123
+ | pysentry-all-sources | 108.84 MB | 9.83x |
124
+
125
+ ## Detailed Analysis
126
+
127
+ ### Pysentry Performance
128
+
129
+ - **Execution Time:** Avg: 1.542s, Min: 0.221s, Max: 3.799s
130
+
131
+ - **Memory Usage:** Avg: 49.58 MB, Min: 10.81 MB, Max: 108.84 MB
132
+
133
+ - **Success Rate:** 100.0% (16/16)
134
+
135
+ ### Pip-Audit Performance
136
+
137
+ - **Execution Time:** Avg: 13.108s, Min: 7.854s, Max: 19.619s
138
+
139
+ - **Memory Usage:** Avg: 46.26 MB, Min: 44.88 MB, Max: 47.34 MB
140
+
141
+ - **Success Rate:** 100.0% (4/4)
@@ -0,0 +1,141 @@
1
+ # PySentry - pip-audit Benchmark Report
2
+
3
+ **Generated:** 2025-08-21 19:52:35
4
+ **Duration:** 1m 56.44s
5
+ **Total Tests:** 20
6
+
7
+ ## Executive Summary
8
+
9
+ **Overall Success Rate:** 100.0% (20/20 successful runs)
10
+
11
+ ### Small_Requirements Dataset - Cold Cache
12
+ - **Fastest:** pysentry-pypi (0.250s) - 35.37x faster than slowest
13
+ - **Memory Efficient:** pysentry-osv (11.03 MB) - 9.68x less memory than highest
14
+
15
+ ### Small_Requirements Dataset - Hot Cache
16
+ - **Fastest:** pysentry-pypi (0.221s) - 35.46x faster than slowest
17
+ - **Memory Efficient:** pysentry-osv (10.81 MB) - 9.68x less memory than highest
18
+
19
+ ### Large_Requirements Dataset - Cold Cache
20
+ - **Fastest:** pysentry-pypi (0.722s) - 27.16x faster than slowest
21
+ - **Memory Efficient:** pysentry-osv (10.93 MB) - 9.84x less memory than highest
22
+
23
+ ### Large_Requirements Dataset - Hot Cache
24
+ - **Fastest:** pysentry-pypi (0.686s) - 23.48x faster than slowest
25
+ - **Memory Efficient:** pysentry-osv (11.07 MB) - 9.83x less memory than highest
26
+
27
+ ## Test Environment
28
+
29
+ - **Platform:** Linux-6.11.0-1018-azure-x86_64-with-glibc2.39
30
+ - **Python Version:** 3.11.13
31
+ - **CPU Cores:** 4
32
+ - **Total Memory:** 15.62 GB
33
+ - **Available Memory:** 14.63 GB
34
+
35
+ ## Performance Comparison
36
+
37
+ ### Small_Requirements Dataset - Cold Cache
38
+
39
+ #### Execution Time Comparison
40
+
41
+ | Tool Configuration | Execution Time | Relative Performance |
42
+ |---------------------|---------------------|---------------------|
43
+ | 🥇 pysentry-pypi | 0.250s | 1.00x |
44
+ | 🥈 pysentry-osv | 1.045s | 4.18x |
45
+ | pysentry-all-sources | 1.152s | 4.60x |
46
+ | pysentry-pypa | 1.155s | 4.61x |
47
+ | pip-audit-default | 8.852s | 35.37x |
48
+
49
+ #### Memory Usage Comparison
50
+
51
+ | Tool Configuration | Peak Memory | Relative Performance |
52
+ |---------------------|---------------------|---------------------|
53
+ | 🥇 pysentry-osv | 11.03 MB | 1.00x |
54
+ | 🥈 pysentry-pypi | 11.64 MB | 1.06x |
55
+ | pip-audit-default | 45.64 MB | 4.14x |
56
+ | pysentry-pypa | 75.38 MB | 6.84x |
57
+ | pysentry-all-sources | 106.78 MB | 9.68x |
58
+
59
+ ### Small_Requirements Dataset - Hot Cache
60
+
61
+ #### Execution Time Comparison
62
+
63
+ | Tool Configuration | Execution Time | Relative Performance |
64
+ |---------------------|---------------------|---------------------|
65
+ | 🥇 pysentry-pypi | 0.221s | 1.00x |
66
+ | 🥈 pysentry-pypa | 0.729s | 3.29x |
67
+ | pysentry-osv | 0.982s | 4.43x |
68
+ | pysentry-all-sources | 1.112s | 5.02x |
69
+ | pip-audit-default | 7.854s | 35.46x |
70
+
71
+ #### Memory Usage Comparison
72
+
73
+ | Tool Configuration | Peak Memory | Relative Performance |
74
+ |---------------------|---------------------|---------------------|
75
+ | 🥇 pysentry-osv | 10.81 MB | 1.00x |
76
+ | 🥈 pysentry-pypi | 11.93 MB | 1.10x |
77
+ | pip-audit-default | 44.88 MB | 4.15x |
78
+ | pysentry-pypa | 69.38 MB | 6.42x |
79
+ | pysentry-all-sources | 104.60 MB | 9.68x |
80
+
81
+ ### Large_Requirements Dataset - Cold Cache
82
+
83
+ #### Execution Time Comparison
84
+
85
+ | Tool Configuration | Execution Time | Relative Performance |
86
+ |---------------------|---------------------|---------------------|
87
+ | 🥇 pysentry-pypi | 0.722s | 1.00x |
88
+ | 🥈 pysentry-pypa | 1.258s | 1.74x |
89
+ | pysentry-all-sources | 3.183s | 4.41x |
90
+ | pysentry-osv | 3.714s | 5.14x |
91
+ | pip-audit-default | 19.619s | 27.16x |
92
+
93
+ #### Memory Usage Comparison
94
+
95
+ | Tool Configuration | Peak Memory | Relative Performance |
96
+ |---------------------|---------------------|---------------------|
97
+ | 🥇 pysentry-osv | 10.93 MB | 1.00x |
98
+ | 🥈 pysentry-pypi | 14.27 MB | 1.31x |
99
+ | pip-audit-default | 47.34 MB | 4.33x |
100
+ | pysentry-pypa | 74.92 MB | 6.85x |
101
+ | pysentry-all-sources | 107.52 MB | 9.84x |
102
+
103
+ ### Large_Requirements Dataset - Hot Cache
104
+
105
+ #### Execution Time Comparison
106
+
107
+ | Tool Configuration | Execution Time | Relative Performance |
108
+ |---------------------|---------------------|---------------------|
109
+ | 🥇 pysentry-pypi | 0.686s | 1.00x |
110
+ | 🥈 pysentry-pypa | 1.206s | 1.76x |
111
+ | pysentry-all-sources | 3.464s | 5.05x |
112
+ | pysentry-osv | 3.799s | 5.54x |
113
+ | pip-audit-default | 16.105s | 23.48x |
114
+
115
+ #### Memory Usage Comparison
116
+
117
+ | Tool Configuration | Peak Memory | Relative Performance |
118
+ |---------------------|---------------------|---------------------|
119
+ | 🥇 pysentry-osv | 11.07 MB | 1.00x |
120
+ | 🥈 pysentry-pypi | 11.27 MB | 1.02x |
121
+ | pip-audit-default | 47.18 MB | 4.26x |
122
+ | pysentry-pypa | 52.84 MB | 4.77x |
123
+ | pysentry-all-sources | 108.84 MB | 9.83x |
124
+
125
+ ## Detailed Analysis
126
+
127
+ ### Pysentry Performance
128
+
129
+ - **Execution Time:** Avg: 1.542s, Min: 0.221s, Max: 3.799s
130
+
131
+ - **Memory Usage:** Avg: 49.58 MB, Min: 10.81 MB, Max: 108.84 MB
132
+
133
+ - **Success Rate:** 100.0% (16/16)
134
+
135
+ ### Pip-Audit Performance
136
+
137
+ - **Execution Time:** Avg: 13.108s, Min: 7.854s, Max: 19.619s
138
+
139
+ - **Memory Usage:** Avg: 46.26 MB, Min: 44.88 MB, Max: 47.34 MB
140
+
141
+ - **Success Rate:** 100.0% (4/4)
@@ -151,6 +151,10 @@ pub struct AuditArgs {
151
151
  #[arg(long)]
152
152
  pub direct_only: bool,
153
153
 
154
+ /// Include withdrawn vulnerabilities in results
155
+ #[arg(long)]
156
+ pub include_withdrawn: bool,
157
+
154
158
  /// Disable caching
155
159
  #[arg(long)]
156
160
  pub no_cache: bool,
@@ -363,6 +367,10 @@ impl AuditArgs {
363
367
  merged.detailed = config.defaults.detailed;
364
368
  }
365
369
 
370
+ if !self.include_withdrawn {
371
+ merged.include_withdrawn = config.defaults.include_withdrawn;
372
+ }
373
+
366
374
  if self.resolver == ResolverTypeArg::Uv && config.resolver.resolver_type != "uv" {
367
375
  merged.resolver = match config.resolver.resolver_type.as_str() {
368
376
  "pip-tools" => ResolverTypeArg::PipTools,
@@ -1010,6 +1018,7 @@ async fn perform_audit(audit_args: &AuditArgs, cache_dir: &Path) -> Result<Audit
1010
1018
  audit_args.severity.clone().into(),
1011
1019
  audit_args.ignore_ids.to_vec(),
1012
1020
  audit_args.direct_only,
1021
+ audit_args.include_withdrawn,
1013
1022
  );
1014
1023
  let matcher = VulnerabilityMatcher::new(database, matcher_config);
1015
1024
 
@@ -1117,6 +1126,7 @@ pub async fn config_init(args: &ConfigInitArgs) -> Result<()> {
1117
1126
  println!("- Severity: low, medium, high, critical");
1118
1127
  println!("- Sources: pypa, pypi, osv");
1119
1128
  println!("- Resolver: uv, pip-tools");
1129
+ println!("- Include withdrawn: true/false");
1120
1130
 
1121
1131
  Ok(())
1122
1132
  }
@@ -1192,6 +1202,10 @@ pub async fn config_show(args: &ConfigShowArgs) -> Result<()> {
1192
1202
  config_loader.config.defaults.direct_only
1193
1203
  );
1194
1204
  println!(" Detailed: {}", config_loader.config.defaults.detailed);
1205
+ println!(
1206
+ " Include withdrawn: {}",
1207
+ config_loader.config.defaults.include_withdrawn
1208
+ );
1195
1209
  println!();
1196
1210
  println!(
1197
1211
  " Sources: {}",
@@ -1292,6 +1306,9 @@ fail_on = "high"
1292
1306
  # Uncomment to include dev/optional dependencies
1293
1307
  # scope = "all"
1294
1308
 
1309
+ # Uncomment to include withdrawn vulnerabilities by default
1310
+ # include_withdrawn = true
1311
+
1295
1312
  [sources]
1296
1313
  # Choose your vulnerability sources
1297
1314
  enabled = ["pypa"]
@@ -75,6 +75,9 @@ pub struct DefaultConfig {
75
75
 
76
76
  #[serde(default)]
77
77
  pub detailed: bool,
78
+
79
+ #[serde(default)]
80
+ pub include_withdrawn: bool,
78
81
  }
79
82
 
80
83
  #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -481,6 +484,7 @@ impl Default for DefaultConfig {
481
484
  scope: default_scope(),
482
485
  direct_only: false,
483
486
  detailed: false,
487
+ include_withdrawn: false,
484
488
  }
485
489
  }
486
490
  }
@@ -24,7 +24,7 @@ pub type Result<T> = std::result::Result<T, AuditError>;
24
24
  /// Audit error types
25
25
  #[derive(Debug, Error)]
26
26
  pub enum AuditError {
27
- #[error("No dependency information found. Run 'uv lock' to generate a lock file")]
27
+ #[error("No dependency information found. Generate a lock file (uv.lock, poetry.lock, Pipfile.lock, pylock.toml) or add pyproject.toml/requirements.txt")]
28
28
  NoDependencyInfo,
29
29
 
30
30
  #[error("Failed to download vulnerability database: {0}")]
@@ -97,6 +97,8 @@ impl AuditEngine {
97
97
  source_type: VulnerabilitySourceType,
98
98
  min_severity: SeverityLevel,
99
99
  ignore_ids: &[String],
100
+ direct_only: bool,
101
+ include_withdrawn: bool,
100
102
  ) -> Result<AuditReport> {
101
103
  let project_path = project_path.as_ref();
102
104
 
@@ -125,7 +127,12 @@ impl AuditEngine {
125
127
  let database = vuln_source.fetch_vulnerabilities(&packages).await?;
126
128
 
127
129
  // 4. Match vulnerabilities
128
- let matcher_config = MatcherConfig::new(min_severity, ignore_ids.to_vec(), false);
130
+ let matcher_config = MatcherConfig::new(
131
+ min_severity,
132
+ ignore_ids.to_vec(),
133
+ direct_only,
134
+ include_withdrawn,
135
+ );
129
136
  let matcher = VulnerabilityMatcher::new(database, matcher_config);
130
137
 
131
138
  let matches = matcher.find_vulnerabilities(&dependencies)?;
@@ -263,11 +263,18 @@ impl ReportGenerator {
263
263
  String::new()
264
264
  };
265
265
 
266
+ let withdrawn_tag = if m.vulnerability.withdrawn.is_some() {
267
+ format!(" {}", "(WITHDRAWN)".yellow().bold())
268
+ } else {
269
+ String::new()
270
+ };
271
+
266
272
  writeln!(
267
273
  output,
268
- " {}. {} {} v{} [{}]{}",
274
+ " {}. {}{} {} v{} [{}]{}",
269
275
  i + 1,
270
276
  ColoredOutput::vulnerability_id(&m.vulnerability.id),
277
+ withdrawn_tag,
271
278
  ColoredOutput::package_name(&m.package_name.to_string()),
272
279
  m.installed_version,
273
280
  ColoredOutput::severity(&m.vulnerability.severity),
@@ -438,12 +445,19 @@ impl ReportGenerator {
438
445
  String::new()
439
446
  };
440
447
 
448
+ let withdrawn_tag = if m.vulnerability.withdrawn.is_some() {
449
+ " ⚠️ **WITHDRAWN**"
450
+ } else {
451
+ ""
452
+ };
453
+
441
454
  writeln!(
442
455
  output,
443
- "### {}. {} `{}`{}",
456
+ "### {}. {} `{}`{}{}",
444
457
  i + 1,
445
458
  severity_icon,
446
459
  m.vulnerability.id,
460
+ withdrawn_tag,
447
461
  source_tag
448
462
  )?;
449
463
  writeln!(output)?;
@@ -459,6 +473,14 @@ impl ReportGenerator {
459
473
  writeln!(output, "- **CVSS Score:** {cvss:.1}")?;
460
474
  }
461
475
 
476
+ if let Some(withdrawn_date) = &m.vulnerability.withdrawn {
477
+ writeln!(
478
+ output,
479
+ "- **⚠️ Withdrawn:** {}",
480
+ withdrawn_date.format("%Y-%m-%d")
481
+ )?;
482
+ }
483
+
462
484
  writeln!(output, "- **Summary:** {}", m.vulnerability.summary)?;
463
485
 
464
486
  if let Some(description) = &m.vulnerability.description {
@@ -546,6 +568,7 @@ impl ReportGenerator {
546
568
  references: m.vulnerability.references.clone(),
547
569
  is_direct: m.is_direct,
548
570
  source: m.vulnerability.source.clone(),
571
+ withdrawn: m.vulnerability.withdrawn.map(|dt| dt.to_rfc3339()),
549
572
  })
550
573
  .collect(),
551
574
  fix_suggestions: report
@@ -610,6 +633,7 @@ struct JsonVulnerability {
610
633
  references: Vec<String>,
611
634
  is_direct: bool,
612
635
  source: Option<String>,
636
+ withdrawn: Option<String>,
613
637
  }
614
638
 
615
639
  #[derive(Serialize, Deserialize)]
@@ -660,6 +684,7 @@ mod tests {
660
684
  published: None,
661
685
  modified: None,
662
686
  source: Some("test".to_string()),
687
+ withdrawn: None,
663
688
  };
664
689
 
665
690
  let matches = vec![VulnerabilityMatch {
@@ -326,6 +326,17 @@ impl SarifGenerator {
326
326
  rule["properties"]["cvss_score"] = json!(cvss);
327
327
  }
328
328
 
329
+ // Add withdrawal information if available
330
+ if let Some(withdrawn_date) = &m.vulnerability.withdrawn {
331
+ rule["properties"]["withdrawn"] = json!(withdrawn_date.to_rfc3339());
332
+ rule["properties"]["tags"] = json!([
333
+ "security",
334
+ "vulnerability",
335
+ format!("{:?}", m.vulnerability.severity).to_lowercase(),
336
+ "withdrawn"
337
+ ]);
338
+ }
339
+
329
340
  // Add timestamps if available
330
341
  if let Some(published) = &m.vulnerability.published {
331
342
  rule["properties"]["published_date"] = json!(published.to_string());
@@ -643,6 +654,7 @@ mod tests {
643
654
  published: None,
644
655
  modified: None,
645
656
  source: Some("test".to_string()),
657
+ withdrawn: None,
646
658
  }
647
659
  }
648
660