secpipw 1.0.0__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.
Files changed (41) hide show
  1. secpipw-1.0.0/LICENSE +21 -0
  2. secpipw-1.0.0/PKG-INFO +217 -0
  3. secpipw-1.0.0/README.md +197 -0
  4. secpipw-1.0.0/pyproject.toml +42 -0
  5. secpipw-1.0.0/setup.cfg +4 -0
  6. secpipw-1.0.0/src/secpipw/__init__.py +5 -0
  7. secpipw-1.0.0/src/secpipw/__main__.py +4 -0
  8. secpipw-1.0.0/src/secpipw/cache_refresh.py +47 -0
  9. secpipw-1.0.0/src/secpipw/cli.py +470 -0
  10. secpipw-1.0.0/src/secpipw/data/pypi-project-names.json +44 -0
  11. secpipw-1.0.0/src/secpipw/install_checks.py +579 -0
  12. secpipw-1.0.0/src/secpipw/install_plan.py +180 -0
  13. secpipw-1.0.0/src/secpipw/package_install.py +241 -0
  14. secpipw-1.0.0/src/secpipw/pip_bridge.py +62 -0
  15. secpipw-1.0.0/src/secpipw/pip_guard.py +565 -0
  16. secpipw-1.0.0/src/secpipw/pth_monitor.py +1089 -0
  17. secpipw-1.0.0/src/secpipw/pypi_api.py +725 -0
  18. secpipw-1.0.0/src/secpipw/release_checks.py +1589 -0
  19. secpipw-1.0.0/src/secpipw/severity.py +28 -0
  20. secpipw-1.0.0/src/secpipw/terminal.py +16 -0
  21. secpipw-1.0.0/src/secpipw/tool_bridge.py +1324 -0
  22. secpipw-1.0.0/src/secpipw/typo.py +488 -0
  23. secpipw-1.0.0/src/secpipw/warning_gate.py +139 -0
  24. secpipw-1.0.0/src/secpipw.egg-info/PKG-INFO +217 -0
  25. secpipw-1.0.0/src/secpipw.egg-info/SOURCES.txt +39 -0
  26. secpipw-1.0.0/src/secpipw.egg-info/dependency_links.txt +1 -0
  27. secpipw-1.0.0/src/secpipw.egg-info/entry_points.txt +5 -0
  28. secpipw-1.0.0/src/secpipw.egg-info/requires.txt +2 -0
  29. secpipw-1.0.0/src/secpipw.egg-info/top_level.txt +1 -0
  30. secpipw-1.0.0/tests/test_install_checks.py +240 -0
  31. secpipw-1.0.0/tests/test_install_plan.py +147 -0
  32. secpipw-1.0.0/tests/test_package_install.py +163 -0
  33. secpipw-1.0.0/tests/test_pip_bridge.py +854 -0
  34. secpipw-1.0.0/tests/test_pip_guard.py +727 -0
  35. secpipw-1.0.0/tests/test_pth_monitor.py +586 -0
  36. secpipw-1.0.0/tests/test_pypi_api.py +534 -0
  37. secpipw-1.0.0/tests/test_release_checks.py +1013 -0
  38. secpipw-1.0.0/tests/test_severity.py +30 -0
  39. secpipw-1.0.0/tests/test_tool_bridge.py +408 -0
  40. secpipw-1.0.0/tests/test_typo.py +130 -0
  41. secpipw-1.0.0/tests/test_warning_gate.py +223 -0
secpipw-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (C) 2026 Weilin Du
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
secpipw-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,217 @@
1
+ Metadata-Version: 2.4
2
+ Name: secpipw
3
+ Version: 1.0.0
4
+ Summary: A defensive pip wrapper with supply-chain preflight checks.
5
+ Author: Weilin Du (LamentXU)
6
+ License-Expression: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3 :: Only
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Requires-Dist: packaging<26,>=24.0
18
+ Requires-Dist: python-Levenshtein<0.28,>=0.27
19
+ Dynamic: license-file
20
+
21
+ *Not Finished Yet. Contribution Welcome. Site at https://spip.lamentxu.top/*
22
+ # secpipw
23
+ English | [简体中文](./README.zh-CN.md)
24
+
25
+ [![Test](https://github.com/LamentXU123/spip/actions/workflows/test.yml/badge.svg)](https://github.com/LamentXU123/spip/actions/workflows/test.yml)
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
27
+ ![Python_version](https://img.shields.io/pypi/pyversions/secpipw.svg?logo=python&logoColor=FBE071)
28
+ ![PyPI Version](https://img.shields.io/pypi/v/secpipw)
29
+ [![Codecov](https://codecov.io/gh/LamentXU123/spip/graph/badge.svg)](https://codecov.io/gh/LamentXU123/spip)
30
+
31
+ An open-source, free, powerful, light-weight guard for your pip to avoid supply-chain attacks.
32
+
33
+ By using this, you can avoid being screwed by the poisoned LiteLLM, etc. just because you type `pip install`
34
+
35
+ Although `secpipw` is designed for low learning budget, we still recommend you to read our [docs](https://spip.lamentxu.top/docs) before you try this product in your production environment.
36
+
37
+ ## What?
38
+
39
+ Currently, supply chain attacks are one of the major security concerns all over the world. The `secpipw` project is a future `pip` wrapper focused on supply-chain risk controls.
40
+
41
+ ## Wait, What?
42
+
43
+ You can use
44
+
45
+ ```bash
46
+ spip install requests
47
+ ```
48
+
49
+ Instead of
50
+
51
+ ```bash
52
+ pip install requests
53
+ ```
54
+
55
+ To install a package more safely in the scope of supply chain security.
56
+
57
+ You do not need to configure. You do not need to learn. Just pure install-to-master.
58
+
59
+ In other words, you can completely replace `pip install` with `spip install` to make your installation safer :)
60
+
61
+ ## Package manager support
62
+
63
+ secpipw now has diversified package-manager support:
64
+
65
+ - [x] `pip`: `spip install requests`
66
+ - [x] `pipx`: `spipx install black`
67
+ - [x] `poetry`: `spoetry add requests`
68
+ - [x] `uv`: `suv pip install requests`
69
+ - [ ] `conda`: planned
70
+
71
+ You can guard common `pipx`, `poetry`, and `uv` package additions:
72
+
73
+ ```bash
74
+ spipx install black
75
+ spoetry add requests
76
+ suv pip install requests
77
+ ```
78
+
79
+ The package installs `spipx`, `spoetry`, and `suv` dedicated entry points.
80
+ Supported guarded commands are
81
+ `pipx install`, `pipx inject`, `pipx run`, `poetry add`, `poetry self add`,
82
+ `uv pip install`, `uv add`, `uv tool install`, and `uv tool run`. Other
83
+ non-install commands are passed through unchanged. Commands that would install
84
+ packages but cannot be translated into a pip install plan, such as
85
+ `pipx upgrade`, `poetry add --source internal ...`, or `uv run ...`, are refused
86
+ instead of running without checks.
87
+
88
+ If you want a near drop-in experience, you can set a shell alias from `pip` to `spip`.
89
+
90
+ Command Prompt (Windows):
91
+
92
+ ```cmd
93
+ pip install secpipw
94
+ doskey pip=spip $*
95
+ ```
96
+
97
+ Bash (Linux):
98
+
99
+ ```bash
100
+ pip install secpipw
101
+ echo "alias pip='spip'" >> ~/.bashrc
102
+ source ~/.bashrc
103
+ ```
104
+
105
+ Zsh (macOS):
106
+
107
+ ```zsh
108
+ pip install secpipw
109
+ echo "alias pip='spip'" >> ~/.zshrc
110
+ source ~/.zshrc
111
+ ```
112
+
113
+ The `secpipw` project will actively check for all the supply chain risks and avoid you installing potentially malicious packages when typing `spip install`
114
+
115
+ For `install`, `secpipw` uses pip's own resolver and then checks the selected install plan before pip builds or installs the resolved distributions. If the checks pass, the same pip install flow continues; `secpipw` does not run a second `pip install` for the already-resolved packages.
116
+
117
+ Except for the `install` commands, the project behaves exactly the same as the original `pip` program. That is, you can always use `spip` instead of `pip` in any case :)
118
+
119
+ For `pipx`, `poetry`, and `uv`, secpipw runs a pip-compatible preflight
120
+ resolution and artifact check before handing control to the original tool. The
121
+ original tool still performs the actual environment update.
122
+
123
+ For more details, please see our docs: https://spip.lamentxu.top/docs
124
+
125
+ ## What problem do secpipw solved?
126
+
127
+ Supply-chain poisoning has always been a persistent security problem. Existing solutions include mature but expensive-to-run tools like GuardDog, and lightweight tools like sfw that rely entirely on a paid Socket API. GuardDog is too heavy for everyday CI usage and is better suited to static analysis by security researchers. Running GuardDog against every artifact downloaded by `pip install`, including all dependencies, would slow installs down. sfw is lighter, but its dependence on a paid API creates another cost for everyday developers.
128
+
129
+ secpipw solves this by hooking into pip's installer and merging security checks directly into the pip install download and installation flow. At the same time, the performance impact is usually small. secpipw is completely free for everyone.
130
+
131
+ Today, many independent developers have suffered CI server compromises that leak secret keys and cause serious damage. With secpipw installed, that risk is greatly reduced, while requiring no payment, no extra performance budget, and no learning or configuration. Install it once with `pip install secpipw`, set an alias once, and keep using pip while gaining an important protection layer in the background.
132
+
133
+ ## Warning policies
134
+
135
+ ## TODO
136
+
137
+ Contributions welcome:
138
+
139
+ - Framework
140
+ - [x] Support guarded `uv pip install`, `uv add`, `uv tool install`, and `uv tool run`
141
+ - [x] Support guarded `pipx install`, `pipx inject`, and `pipx run`
142
+ - [x] Support guarded `poetry add` and `poetry self add`
143
+ - [ ] Support `conda`
144
+ - CI
145
+ - [x] Write a benchmark CI in the github workflow to compare the performance of `spip install` and `pip install`
146
+ - Documentation
147
+ - [ ] Use some modern documentation framework to refactor the /doc/docs directory.
148
+ - [ ] Support website view on mobile phones. @didongji91
149
+ - Checks
150
+ - [x] Record and compare installed package entry-point and `.pth` baselines across `spip` installs
151
+ - [x] If new or changed `.pth` file is added
152
+ - [x] If entry-point metadata or script files change
153
+ - [x] Detect yanked releases from pip's resolved install report
154
+ - [x] Compare archive hashes with already available PyPI release metadata
155
+ - [ ] Add check of the diff between the last version of the package and the to-be-installed version, search for malicious changes
156
+ - [ ] If setup.py has been changed
157
+
158
+ We currently have three install warning policies:
159
+
160
+ - `HIGH`: pause installation and require `--spip-ignore-warning`
161
+ - `MEDIUM`: prompt `y/n` before continuing
162
+ - `LOW`: warn and continue
163
+
164
+ The default sensitivity is `low`, which uses the policy above. You can make
165
+ the gate stricter with `--sensitivity medium` or `--sensitivity high`:
166
+
167
+ - `--sensitivity medium`: `MEDIUM` and above pause installation; `LOW` prompts.
168
+ - `--sensitivity high`: `LOW` and above pause installation.
169
+
170
+ Use `--spip-ignore <level>` to completely ignore warnings at that severity and below.
171
+ For example, `--spip-ignore LOW` suppresses `LOW` warnings, while `--spip-ignore MEDIUM`
172
+ suppresses both `LOW` and `MEDIUM` warnings. Ignored warnings are not printed,
173
+ and checks that can only produce ignored severities are skipped.
174
+
175
+ ## Caches
176
+
177
+ secpipw stores PyPI name, release-time, and maintainer email history caches in
178
+ the user's cache directory by default, so the same cache is reused across projects.
179
+ Set `SPIP_CACHE_DIR` to override the cache directory.
180
+
181
+ ## Benchmark
182
+
183
+ Run the local benchmark with:
184
+
185
+ ```bash
186
+ python scripts/benchmark_install.py --runs 5 --warmups 0
187
+ ```
188
+
189
+ The default benchmark compares `pip install ruff` and `spip install ruff`,
190
+ timing package download and installation together. It uses `--no-cache-dir`,
191
+ `--no-deps`, and a fresh `--target` directory for each measured run, so the
192
+ result focuses on repeated installs of one well-known package body rather than a
193
+ dependency tree. The Benchmark GitHub Actions workflow runs on relevant `main` changes, on a
194
+ weekly schedule, or by manual dispatch. It publishes the latest
195
+ `benchmark.json` to the remote `benchmark-data` branch, and the website renders
196
+ `x1.0742`-style median ratios from that data. Benchmark updates do not advance
197
+ `main`.
198
+
199
+ When `secpipw` detects a potential risk, a warning will be raised, with the level depending on the severity the risk is.
200
+
201
+ For now, the project has several major check points:
202
+
203
+ - [x] Fake typo checks: Hackers often use "fake typos" to inject a malicious dependency package into the poisoned source file. `secpipw` detects this by first resolving all the packages that `pip install` is going to download, and then comparing non-popular resolved package names with a local hot-package list. Warning levels:
204
+ - Medium severity: `requsets` vs `requests`
205
+ - Medium severity: `panda` vs `pandas`
206
+ - Low severity: `sixth` vs `six`
207
+ - [x] Direct URL dependency checks: If the install target or a resolved dependency uses a direct URL, VCS URL, or PEP 508 direct reference, `secpipw` will raise a `MEDIUM` warning.
208
+ - [x] Fresh release checks: If the selected PyPI release was published less than 8 hours ago, `secpipw` will raise a `MEDIUM` warning; if it was published less than 48 hours ago, `secpipw` will raise a `LOW` warning.
209
+ - [x] Yanked release checks: If pip resolves a release that is marked as yanked, `secpipw` will raise a `MEDIUM` warning using pip's install report.
210
+ - [x] Archive hash checks: If PyPI release metadata is already available and the selected wheel/sdist digest does not match the resolved archive hash, `secpipw` will raise a `HIGH` warning.
211
+ - [x] Empty description checks: If the selected PyPI release metadata has no summary and no long description, `secpipw` will raise a `LOW` warning.
212
+ - [x] Suspicious metadata URL checks: If PyPI metadata points to a shortener, raw IP, suspicious TLD, embedded credentials, or similar suspicious URL, `secpipw` will raise a `LOW` warning.
213
+ - [x] Repository mismatch checks: If PyPI metadata points to a GitHub/GitLab repository whose repo name appears unrelated to the package name, `secpipw` will raise a `LOW` warning.
214
+ - [x] Maintainer email domain drift checks: If a package's maintainer email domain changes compared with the local `secpipw` history cache, `secpipw` will raise a `LOW` warning.
215
+ - [x] Zero-version checks: If the selected package version is `0.0` or `0.0.0`, `secpipw` will raise a `LOW` warning.
216
+ - [x] `.pth` file detection: Instead of directly injecting malicious code inside the package, today most hackers will place their bad stuff under a `.pth` file, with an `import` as the beginning. `secpipw` only checks the installed file-system diff after installation. The warning level is always `MEDIUM`, and `secpipw` will ask whether to delete the suspicious installed `.pth` file.
217
+ - [ ] TODO ...
@@ -0,0 +1,197 @@
1
+ *Not Finished Yet. Contribution Welcome. Site at https://spip.lamentxu.top/*
2
+ # secpipw
3
+ English | [简体中文](./README.zh-CN.md)
4
+
5
+ [![Test](https://github.com/LamentXU123/spip/actions/workflows/test.yml/badge.svg)](https://github.com/LamentXU123/spip/actions/workflows/test.yml)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+ ![Python_version](https://img.shields.io/pypi/pyversions/secpipw.svg?logo=python&logoColor=FBE071)
8
+ ![PyPI Version](https://img.shields.io/pypi/v/secpipw)
9
+ [![Codecov](https://codecov.io/gh/LamentXU123/spip/graph/badge.svg)](https://codecov.io/gh/LamentXU123/spip)
10
+
11
+ An open-source, free, powerful, light-weight guard for your pip to avoid supply-chain attacks.
12
+
13
+ By using this, you can avoid being screwed by the poisoned LiteLLM, etc. just because you type `pip install`
14
+
15
+ Although `secpipw` is designed for low learning budget, we still recommend you to read our [docs](https://spip.lamentxu.top/docs) before you try this product in your production environment.
16
+
17
+ ## What?
18
+
19
+ Currently, supply chain attacks are one of the major security concerns all over the world. The `secpipw` project is a future `pip` wrapper focused on supply-chain risk controls.
20
+
21
+ ## Wait, What?
22
+
23
+ You can use
24
+
25
+ ```bash
26
+ spip install requests
27
+ ```
28
+
29
+ Instead of
30
+
31
+ ```bash
32
+ pip install requests
33
+ ```
34
+
35
+ To install a package more safely in the scope of supply chain security.
36
+
37
+ You do not need to configure. You do not need to learn. Just pure install-to-master.
38
+
39
+ In other words, you can completely replace `pip install` with `spip install` to make your installation safer :)
40
+
41
+ ## Package manager support
42
+
43
+ secpipw now has diversified package-manager support:
44
+
45
+ - [x] `pip`: `spip install requests`
46
+ - [x] `pipx`: `spipx install black`
47
+ - [x] `poetry`: `spoetry add requests`
48
+ - [x] `uv`: `suv pip install requests`
49
+ - [ ] `conda`: planned
50
+
51
+ You can guard common `pipx`, `poetry`, and `uv` package additions:
52
+
53
+ ```bash
54
+ spipx install black
55
+ spoetry add requests
56
+ suv pip install requests
57
+ ```
58
+
59
+ The package installs `spipx`, `spoetry`, and `suv` dedicated entry points.
60
+ Supported guarded commands are
61
+ `pipx install`, `pipx inject`, `pipx run`, `poetry add`, `poetry self add`,
62
+ `uv pip install`, `uv add`, `uv tool install`, and `uv tool run`. Other
63
+ non-install commands are passed through unchanged. Commands that would install
64
+ packages but cannot be translated into a pip install plan, such as
65
+ `pipx upgrade`, `poetry add --source internal ...`, or `uv run ...`, are refused
66
+ instead of running without checks.
67
+
68
+ If you want a near drop-in experience, you can set a shell alias from `pip` to `spip`.
69
+
70
+ Command Prompt (Windows):
71
+
72
+ ```cmd
73
+ pip install secpipw
74
+ doskey pip=spip $*
75
+ ```
76
+
77
+ Bash (Linux):
78
+
79
+ ```bash
80
+ pip install secpipw
81
+ echo "alias pip='spip'" >> ~/.bashrc
82
+ source ~/.bashrc
83
+ ```
84
+
85
+ Zsh (macOS):
86
+
87
+ ```zsh
88
+ pip install secpipw
89
+ echo "alias pip='spip'" >> ~/.zshrc
90
+ source ~/.zshrc
91
+ ```
92
+
93
+ The `secpipw` project will actively check for all the supply chain risks and avoid you installing potentially malicious packages when typing `spip install`
94
+
95
+ For `install`, `secpipw` uses pip's own resolver and then checks the selected install plan before pip builds or installs the resolved distributions. If the checks pass, the same pip install flow continues; `secpipw` does not run a second `pip install` for the already-resolved packages.
96
+
97
+ Except for the `install` commands, the project behaves exactly the same as the original `pip` program. That is, you can always use `spip` instead of `pip` in any case :)
98
+
99
+ For `pipx`, `poetry`, and `uv`, secpipw runs a pip-compatible preflight
100
+ resolution and artifact check before handing control to the original tool. The
101
+ original tool still performs the actual environment update.
102
+
103
+ For more details, please see our docs: https://spip.lamentxu.top/docs
104
+
105
+ ## What problem do secpipw solved?
106
+
107
+ Supply-chain poisoning has always been a persistent security problem. Existing solutions include mature but expensive-to-run tools like GuardDog, and lightweight tools like sfw that rely entirely on a paid Socket API. GuardDog is too heavy for everyday CI usage and is better suited to static analysis by security researchers. Running GuardDog against every artifact downloaded by `pip install`, including all dependencies, would slow installs down. sfw is lighter, but its dependence on a paid API creates another cost for everyday developers.
108
+
109
+ secpipw solves this by hooking into pip's installer and merging security checks directly into the pip install download and installation flow. At the same time, the performance impact is usually small. secpipw is completely free for everyone.
110
+
111
+ Today, many independent developers have suffered CI server compromises that leak secret keys and cause serious damage. With secpipw installed, that risk is greatly reduced, while requiring no payment, no extra performance budget, and no learning or configuration. Install it once with `pip install secpipw`, set an alias once, and keep using pip while gaining an important protection layer in the background.
112
+
113
+ ## Warning policies
114
+
115
+ ## TODO
116
+
117
+ Contributions welcome:
118
+
119
+ - Framework
120
+ - [x] Support guarded `uv pip install`, `uv add`, `uv tool install`, and `uv tool run`
121
+ - [x] Support guarded `pipx install`, `pipx inject`, and `pipx run`
122
+ - [x] Support guarded `poetry add` and `poetry self add`
123
+ - [ ] Support `conda`
124
+ - CI
125
+ - [x] Write a benchmark CI in the github workflow to compare the performance of `spip install` and `pip install`
126
+ - Documentation
127
+ - [ ] Use some modern documentation framework to refactor the /doc/docs directory.
128
+ - [ ] Support website view on mobile phones. @didongji91
129
+ - Checks
130
+ - [x] Record and compare installed package entry-point and `.pth` baselines across `spip` installs
131
+ - [x] If new or changed `.pth` file is added
132
+ - [x] If entry-point metadata or script files change
133
+ - [x] Detect yanked releases from pip's resolved install report
134
+ - [x] Compare archive hashes with already available PyPI release metadata
135
+ - [ ] Add check of the diff between the last version of the package and the to-be-installed version, search for malicious changes
136
+ - [ ] If setup.py has been changed
137
+
138
+ We currently have three install warning policies:
139
+
140
+ - `HIGH`: pause installation and require `--spip-ignore-warning`
141
+ - `MEDIUM`: prompt `y/n` before continuing
142
+ - `LOW`: warn and continue
143
+
144
+ The default sensitivity is `low`, which uses the policy above. You can make
145
+ the gate stricter with `--sensitivity medium` or `--sensitivity high`:
146
+
147
+ - `--sensitivity medium`: `MEDIUM` and above pause installation; `LOW` prompts.
148
+ - `--sensitivity high`: `LOW` and above pause installation.
149
+
150
+ Use `--spip-ignore <level>` to completely ignore warnings at that severity and below.
151
+ For example, `--spip-ignore LOW` suppresses `LOW` warnings, while `--spip-ignore MEDIUM`
152
+ suppresses both `LOW` and `MEDIUM` warnings. Ignored warnings are not printed,
153
+ and checks that can only produce ignored severities are skipped.
154
+
155
+ ## Caches
156
+
157
+ secpipw stores PyPI name, release-time, and maintainer email history caches in
158
+ the user's cache directory by default, so the same cache is reused across projects.
159
+ Set `SPIP_CACHE_DIR` to override the cache directory.
160
+
161
+ ## Benchmark
162
+
163
+ Run the local benchmark with:
164
+
165
+ ```bash
166
+ python scripts/benchmark_install.py --runs 5 --warmups 0
167
+ ```
168
+
169
+ The default benchmark compares `pip install ruff` and `spip install ruff`,
170
+ timing package download and installation together. It uses `--no-cache-dir`,
171
+ `--no-deps`, and a fresh `--target` directory for each measured run, so the
172
+ result focuses on repeated installs of one well-known package body rather than a
173
+ dependency tree. The Benchmark GitHub Actions workflow runs on relevant `main` changes, on a
174
+ weekly schedule, or by manual dispatch. It publishes the latest
175
+ `benchmark.json` to the remote `benchmark-data` branch, and the website renders
176
+ `x1.0742`-style median ratios from that data. Benchmark updates do not advance
177
+ `main`.
178
+
179
+ When `secpipw` detects a potential risk, a warning will be raised, with the level depending on the severity the risk is.
180
+
181
+ For now, the project has several major check points:
182
+
183
+ - [x] Fake typo checks: Hackers often use "fake typos" to inject a malicious dependency package into the poisoned source file. `secpipw` detects this by first resolving all the packages that `pip install` is going to download, and then comparing non-popular resolved package names with a local hot-package list. Warning levels:
184
+ - Medium severity: `requsets` vs `requests`
185
+ - Medium severity: `panda` vs `pandas`
186
+ - Low severity: `sixth` vs `six`
187
+ - [x] Direct URL dependency checks: If the install target or a resolved dependency uses a direct URL, VCS URL, or PEP 508 direct reference, `secpipw` will raise a `MEDIUM` warning.
188
+ - [x] Fresh release checks: If the selected PyPI release was published less than 8 hours ago, `secpipw` will raise a `MEDIUM` warning; if it was published less than 48 hours ago, `secpipw` will raise a `LOW` warning.
189
+ - [x] Yanked release checks: If pip resolves a release that is marked as yanked, `secpipw` will raise a `MEDIUM` warning using pip's install report.
190
+ - [x] Archive hash checks: If PyPI release metadata is already available and the selected wheel/sdist digest does not match the resolved archive hash, `secpipw` will raise a `HIGH` warning.
191
+ - [x] Empty description checks: If the selected PyPI release metadata has no summary and no long description, `secpipw` will raise a `LOW` warning.
192
+ - [x] Suspicious metadata URL checks: If PyPI metadata points to a shortener, raw IP, suspicious TLD, embedded credentials, or similar suspicious URL, `secpipw` will raise a `LOW` warning.
193
+ - [x] Repository mismatch checks: If PyPI metadata points to a GitHub/GitLab repository whose repo name appears unrelated to the package name, `secpipw` will raise a `LOW` warning.
194
+ - [x] Maintainer email domain drift checks: If a package's maintainer email domain changes compared with the local `secpipw` history cache, `secpipw` will raise a `LOW` warning.
195
+ - [x] Zero-version checks: If the selected package version is `0.0` or `0.0.0`, `secpipw` will raise a `LOW` warning.
196
+ - [x] `.pth` file detection: Instead of directly injecting malicious code inside the package, today most hackers will place their bad stuff under a `.pth` file, with an `import` as the beginning. `secpipw` only checks the installed file-system diff after installation. The warning level is always `MEDIUM`, and `secpipw` will ask whether to delete the suspicious installed `.pth` file.
197
+ - [ ] TODO ...
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ license = "MIT"
7
+ name = "secpipw"
8
+ version = "1.0.0"
9
+ description = "A defensive pip wrapper with supply-chain preflight checks."
10
+ readme = "README.md"
11
+ requires-python = ">=3.10"
12
+ classifiers = [
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3 :: Only",
15
+ "Programming Language :: Python :: 3.10",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Programming Language :: Python :: 3.13",
19
+ "Programming Language :: Python :: 3.14",
20
+ ]
21
+ authors = [
22
+ { name = "Weilin Du (LamentXU)" }
23
+ ]
24
+ dependencies = [
25
+ "packaging>=24.0,<26",
26
+ "python-Levenshtein>=0.27,<0.28"
27
+ ]
28
+
29
+ [project.scripts]
30
+ spip = "secpipw.cli:main"
31
+ spipx = "secpipw.cli:pipx_main"
32
+ spoetry = "secpipw.cli:poetry_main"
33
+ suv = "secpipw.cli:uv_main"
34
+
35
+ [tool.setuptools]
36
+ package-dir = {"" = "src"}
37
+
38
+ [tool.setuptools.packages.find]
39
+ where = ["src"]
40
+
41
+ [tool.setuptools.package-data]
42
+ secpipw = ["data/*.json"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,5 @@
1
+ from secpipw.severity import Severity, parse_severity
2
+
3
+ __all__ = ["__version__", "Severity", "parse_severity"]
4
+
5
+ __version__ = "8.0"
@@ -0,0 +1,4 @@
1
+ from secpipw.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ raise SystemExit(main())
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Callable
5
+
6
+ from secpipw.pypi_api import OfficialPyPIClient
7
+
8
+
9
+ @dataclass(frozen=True)
10
+ class CacheRefreshResult:
11
+ key: str
12
+ description: str
13
+ count: int
14
+ location: str
15
+
16
+
17
+ @dataclass(frozen=True)
18
+ class CacheRefreshTask:
19
+ key: str
20
+ description: str
21
+ run: Callable[[OfficialPyPIClient], CacheRefreshResult]
22
+
23
+
24
+ def _refresh_project_name_cache(client: OfficialPyPIClient) -> CacheRefreshResult:
25
+ count = client.refresh_project_name_cache()
26
+ return CacheRefreshResult(
27
+ key="pypi-project-names",
28
+ description="PyPI project name cache",
29
+ count=count,
30
+ location=str(client.cache_path),
31
+ )
32
+
33
+
34
+ REFRESH_TASKS: tuple[CacheRefreshTask, ...] = (
35
+ CacheRefreshTask(
36
+ key="pypi-project-names",
37
+ description="PyPI project name cache",
38
+ run=_refresh_project_name_cache,
39
+ ),
40
+ )
41
+
42
+
43
+ def refresh_all_caches(
44
+ client: OfficialPyPIClient | None = None,
45
+ ) -> list[CacheRefreshResult]:
46
+ client = client or OfficialPyPIClient()
47
+ return [task.run(client) for task in REFRESH_TASKS]