sentro 0.1.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 (61) hide show
  1. sentro-0.1.0/.gitignore +20 -0
  2. sentro-0.1.0/.idea/.gitignore +3 -0
  3. sentro-0.1.0/.idea/inspectionProfiles/Project_Default.xml +7 -0
  4. sentro-0.1.0/.idea/inspectionProfiles/profiles_settings.xml +6 -0
  5. sentro-0.1.0/.idea/misc.xml +7 -0
  6. sentro-0.1.0/.idea/modules.xml +8 -0
  7. sentro-0.1.0/.idea/safe-pip-install.iml +18 -0
  8. sentro-0.1.0/.idea/vcs.xml +6 -0
  9. sentro-0.1.0/.idea/workspace.xml +43 -0
  10. sentro-0.1.0/.pypirc +5 -0
  11. sentro-0.1.0/PKG-INFO +230 -0
  12. sentro-0.1.0/PUBLISH.md +100 -0
  13. sentro-0.1.0/README.md +204 -0
  14. sentro-0.1.0/pypitoken.text +5 -0
  15. sentro-0.1.0/pyproject.toml +57 -0
  16. sentro-0.1.0/src/sentro/__init__.py +3 -0
  17. sentro-0.1.0/src/sentro/__main__.py +4 -0
  18. sentro-0.1.0/src/sentro/_version.py +1 -0
  19. sentro-0.1.0/src/sentro/cli.py +195 -0
  20. sentro-0.1.0/src/sentro/config.py +133 -0
  21. sentro-0.1.0/src/sentro/data/popular_packages.txt +259 -0
  22. sentro-0.1.0/src/sentro/extraction/__init__.py +0 -0
  23. sentro-0.1.0/src/sentro/extraction/extractor.py +27 -0
  24. sentro-0.1.0/src/sentro/extraction/sdist_extractor.py +91 -0
  25. sentro-0.1.0/src/sentro/extraction/wheel_extractor.py +54 -0
  26. sentro-0.1.0/src/sentro/installer.py +169 -0
  27. sentro-0.1.0/src/sentro/models.py +70 -0
  28. sentro-0.1.0/src/sentro/orchestrator.py +140 -0
  29. sentro-0.1.0/src/sentro/pypi/__init__.py +0 -0
  30. sentro-0.1.0/src/sentro/pypi/client.py +84 -0
  31. sentro-0.1.0/src/sentro/pypi/downloader.py +70 -0
  32. sentro-0.1.0/src/sentro/reporting/__init__.py +0 -0
  33. sentro-0.1.0/src/sentro/reporting/json_reporter.py +41 -0
  34. sentro-0.1.0/src/sentro/reporting/reporter.py +22 -0
  35. sentro-0.1.0/src/sentro/reporting/text_reporter.py +95 -0
  36. sentro-0.1.0/src/sentro/scanners/__init__.py +0 -0
  37. sentro-0.1.0/src/sentro/scanners/base.py +48 -0
  38. sentro-0.1.0/src/sentro/scanners/dependency_confusion.py +56 -0
  39. sentro-0.1.0/src/sentro/scanners/malicious_code.py +332 -0
  40. sentro-0.1.0/src/sentro/scanners/metadata.py +133 -0
  41. sentro-0.1.0/src/sentro/scanners/obfuscation.py +173 -0
  42. sentro-0.1.0/src/sentro/scanners/setup_hooks.py +158 -0
  43. sentro-0.1.0/src/sentro/scanners/typosquatting.py +112 -0
  44. sentro-0.1.0/tests/conftest.py +151 -0
  45. sentro-0.1.0/tests/fixtures/pypi_responses/new_package.json +37 -0
  46. sentro-0.1.0/tests/fixtures/pypi_responses/requests.json +62 -0
  47. sentro-0.1.0/tests/test_cli.py +98 -0
  48. sentro-0.1.0/tests/test_config.py +86 -0
  49. sentro-0.1.0/tests/test_extractor.py +48 -0
  50. sentro-0.1.0/tests/test_installer.py +65 -0
  51. sentro-0.1.0/tests/test_integration.py +39 -0
  52. sentro-0.1.0/tests/test_models.py +34 -0
  53. sentro-0.1.0/tests/test_pipeline.py +61 -0
  54. sentro-0.1.0/tests/test_reporter.py +88 -0
  55. sentro-0.1.0/tests/test_scanner_dependency_confusion.py +55 -0
  56. sentro-0.1.0/tests/test_scanner_malicious_code.py +103 -0
  57. sentro-0.1.0/tests/test_scanner_metadata.py +115 -0
  58. sentro-0.1.0/tests/test_scanner_obfuscation.py +72 -0
  59. sentro-0.1.0/tests/test_scanner_setup_hooks.py +81 -0
  60. sentro-0.1.0/tests/test_scanner_typosquatting.py +49 -0
  61. sentro-0.1.0/uv.lock +524 -0
@@ -0,0 +1,20 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .eggs/
5
+ dist/
6
+ build/
7
+ .venv/
8
+ venv/
9
+ .env
10
+ *.egg
11
+ .pytest_cache/
12
+ .coverage
13
+ htmlcov/
14
+ .mypy_cache/
15
+ .ruff_cache/
16
+ *.whl
17
+ *.tar.gz
18
+ /tmp/
19
+ .safe-pip.toml
20
+ *.claude
@@ -0,0 +1,3 @@
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
@@ -0,0 +1,7 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <profile version="1.0">
3
+ <option name="myName" value="Project Default" />
4
+ <inspection_tool class="PyArgumentListInspection" enabled="false" level="WARNING" enabled_by_default="false" />
5
+ <inspection_tool class="PyStatementEffectInspection" enabled="false" level="WARNING" enabled_by_default="false" />
6
+ </profile>
7
+ </component>
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <settings>
3
+ <option name="USE_PROJECT_PROFILE" value="false" />
4
+ <version value="1.0" />
5
+ </settings>
6
+ </component>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="Black">
4
+ <option name="sdkName" value="uv (safe-pip-install)" />
5
+ </component>
6
+ <component name="ProjectRootManager" version="2" project-jdk-name="uv (safe-pip-install)" project-jdk-type="Python SDK" />
7
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/safe-pip-install.iml" filepath="$PROJECT_DIR$/.idea/safe-pip-install.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,18 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="PYTHON_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
6
+ <excludeFolder url="file://$MODULE_DIR$/.venv" />
7
+ </content>
8
+ <orderEntry type="jdk" jdkName="uv (safe-pip-install)" jdkType="Python SDK" />
9
+ <orderEntry type="sourceFolder" forTests="false" />
10
+ </component>
11
+ <component name="PyDocumentationSettings">
12
+ <option name="format" value="PLAIN" />
13
+ <option name="myDocStringFormat" value="Plain" />
14
+ </component>
15
+ <component name="TestRunnerService">
16
+ <option name="PROJECT_TEST_RUNNER" value="py.test" />
17
+ </component>
18
+ </module>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$/.." vcs="Git" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,43 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ChangeListManager">
4
+ <list default="true" id="b83261b5-2f82-4a61-8ff1-8fb46c8264ce" name="Changes" comment="" />
5
+ <option name="SHOW_DIALOG" value="false" />
6
+ <option name="HIGHLIGHT_CONFLICTS" value="true" />
7
+ <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
8
+ <option name="LAST_RESOLUTION" value="IGNORE" />
9
+ </component>
10
+ <component name="Git.Settings">
11
+ <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/.." />
12
+ </component>
13
+ <component name="ProjectColorInfo">{
14
+ &quot;associatedIndex&quot;: 1
15
+ }</component>
16
+ <component name="ProjectId" id="3CFzClefo4gqasflutg5HAmFyGK" />
17
+ <component name="ProjectViewState">
18
+ <option name="hideEmptyMiddlePackages" value="true" />
19
+ <option name="showLibraryContents" value="true" />
20
+ </component>
21
+ <component name="PropertiesComponent"><![CDATA[{
22
+ "keyToString": {
23
+ "ModuleVcsDetector.initialDetectionPerformed": "true",
24
+ "RunOnceActivity.ShowReadmeOnStart": "true",
25
+ "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
26
+ "RunOnceActivity.git.unshallow": "true",
27
+ "dart.analysis.tool.window.visible": "false",
28
+ "git-widget-placeholder": "origin",
29
+ "last_opened_file_path": "/home/ckdev/development/sentro",
30
+ "show.migrate.to.gradle.popup": "false"
31
+ }
32
+ }]]></component>
33
+ <component name="TaskManager">
34
+ <task active="true" id="Default" summary="Default task">
35
+ <changelist id="b83261b5-2f82-4a61-8ff1-8fb46c8264ce" name="Changes" comment="" />
36
+ <created>1775995982467</created>
37
+ <option name="number" value="Default" />
38
+ <option name="presentableId" value="Default" />
39
+ <updated>1775995982467</updated>
40
+ </task>
41
+ <servers />
42
+ </component>
43
+ </project>
sentro-0.1.0/.pypirc ADDED
@@ -0,0 +1,5 @@
1
+
2
+ [pypi]
3
+ username = pypi-AgEIcHlwaS5vcmcCJDU4NWVmNWE1LTJlNDgtNDkwNC05ZTJiLTg5ZmEyZGEwNmFjNwACKlszLCIzYjNhMDQ4NS00YzIyLTRmZWMtYmZhYS1kYjJlOTYwYzRjYWMiXQAABiDp1kxUluuyn5czGGcGgE7A3oZSX4pYSH-lILOF35JLlA
4
+ password = solvyx11062022Aa@
5
+
sentro-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,230 @@
1
+ Metadata-Version: 2.4
2
+ Name: sentro
3
+ Version: 0.1.0
4
+ Summary: A security-conscious pip wrapper that scans packages for malicious code before installation
5
+ Author-email: Solvyx <dev@solvyx.dev>
6
+ License: MIT
7
+ Keywords: malware-detection,package-manager,pip,security,supply-chain
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Topic :: Security
15
+ Classifier: Topic :: Software Development :: Build Tools
16
+ Requires-Python: >=3.11
17
+ Requires-Dist: click>=8.1
18
+ Requires-Dist: packaging>=24.0
19
+ Requires-Dist: rich>=13.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
22
+ Requires-Dist: pytest-mock>=3.0; extra == 'dev'
23
+ Requires-Dist: pytest>=8.0; extra == 'dev'
24
+ Requires-Dist: responses>=0.25; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # sentro
28
+
29
+ Built by [Solvyx.dev](https://solvyx.dev) — a pip wrapper that scans Python packages for malicious code before installing them.
30
+
31
+ ```bash
32
+ sentro install requests
33
+ ```
34
+
35
+ ```
36
+ ╭──────────────────────── sentro scan ─────────────────────────╮
37
+ │ Package : requests 2.31.0 │
38
+ │ PyPI : verified │
39
+ │ Risk : SAFE (score 0/100) │
40
+ ╰─────────────────────────────────────────────────────────────────╯
41
+ No issues found.
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Why
47
+
48
+ Supply-chain attacks on PyPI are getting more frequent. Attackers publish packages with names one typo away from `requests` or `numpy`, or shadow internal package names to trigger dependency confusion. The malicious code runs at install time inside `setup.py`, or silently on first `import`.
49
+
50
+ `sentro` downloads and scans a package before pip ever touches it.
51
+
52
+ ---
53
+
54
+ ## What it detects
55
+
56
+ | Check | Examples |
57
+ |---|---|
58
+ | **Malicious code** | `eval()` / `exec()` at module level, `os.system()`, `subprocess(shell=True)`, socket connections to hardcoded IPs |
59
+ | **Install hooks** | Dangerous calls in `setup.py` that run unconditionally at install time, `cmdclass` overrides, dynamic `install_requires` |
60
+ | **Obfuscation** | `exec(base64.b64decode(...))` chains, high-entropy string constants, `marshal.loads` payloads |
61
+ | **Typosquatting** | Names similar to popular packages (`reqeusts`, `numpy-dev`), Unicode homoglyphs |
62
+ | **Dependency confusion** | Package names that shadow Python stdlib modules (`json`, `os`, `urllib`) |
63
+ | **Metadata signals** | Package age under 7 days, very low download count, missing author/homepage |
64
+
65
+ Each finding contributes to a risk score (0–100). The overall verdict is **SAFE**, **WARNING**, or **DANGER**.
66
+
67
+ ---
68
+
69
+ ## Install
70
+
71
+ ```bash
72
+ pip install sentro
73
+ ```
74
+
75
+ Requires Python 3.11+.
76
+
77
+ ---
78
+
79
+ ## Usage
80
+
81
+ ```bash
82
+ # Scan and install
83
+ sentro install requests
84
+
85
+ # Scan only — don't install
86
+ sentro install requests --no-install
87
+
88
+ # Block installation if anything scores DANGER
89
+ sentro install requests --strict
90
+
91
+ # Pin a version
92
+ sentro install "requests==2.28.0"
93
+
94
+ # Multiple packages
95
+ sentro install requests flask sqlalchemy
96
+
97
+ # JSON output (for CI pipelines)
98
+ sentro install requests --no-install --output-format json
99
+
100
+ # See which installer was detected
101
+ sentro detect-installer
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Flags
107
+
108
+ | Flag | Description |
109
+ |---|---|
110
+ | `--strict` | Exit 1 and block install if any package scores DANGER |
111
+ | `--no-install` | Scan only, don't install |
112
+ | `--skip-scan` | Skip scanning, forward directly to the installer |
113
+ | `--output-format text\|json` | Output format (default: `text`) |
114
+ | `--installer pip\|uv\|conda\|mamba\|poetry\|pipenv\|pdm\|auto` | Installer to use (default: `auto`) |
115
+ | `--config PATH` | Path to a TOML config file |
116
+
117
+ ---
118
+
119
+ ## Installer detection
120
+
121
+ `sentro` auto-detects your package manager so the install step uses the right tool.
122
+
123
+ | Installer | Detected when |
124
+ |---|---|
125
+ | `uv` | `uv` is on PATH and a virtual env is active |
126
+ | `conda` / `mamba` | `CONDA_DEFAULT_ENV` or `CONDA_PREFIX` is set |
127
+ | `poetry` | `pyproject.toml` has `[tool.poetry]` and `poetry` is on PATH |
128
+ | `pipenv` | `Pipfile` exists and `pipenv` is on PATH |
129
+ | `pdm` | `pyproject.toml` has `[tool.pdm]` and `pdm` is on PATH |
130
+ | `pip` | Fallback |
131
+
132
+ Override with `--installer pip` or set `SENTRO_INSTALLER=pip`.
133
+
134
+ ---
135
+
136
+ ## Configuration
137
+
138
+ Create a `.sentro.toml` in your project root (or add `[tool.sentro]` to `pyproject.toml`):
139
+
140
+ ```toml
141
+ [sentro]
142
+ strict = true
143
+
144
+ [sentro.thresholds]
145
+ warning = 30
146
+ danger = 70
147
+
148
+ whitelist_packages = ["requests", "numpy"]
149
+ scanners_disabled = ["metadata"]
150
+ ```
151
+
152
+ Config is merged from multiple sources in this order (last wins):
153
+
154
+ 1. `~/.config/sentro/config.toml` — user-level defaults
155
+ 2. `pyproject.toml` `[tool.sentro]` in the current directory
156
+ 3. `.sentro.toml` in the current directory
157
+ 4. `--config PATH` flag
158
+ 5. `SENTRO_*` environment variables
159
+ 6. CLI flags
160
+
161
+ ### Environment variables
162
+
163
+ | Variable | Effect |
164
+ |---|---|
165
+ | `SENTRO_STRICT=true` | Enable strict mode |
166
+ | `SENTRO_INSTALLER=pip` | Force a specific installer |
167
+ | `SENTRO_OUTPUT_FORMAT=json` | JSON output |
168
+ | `SENTRO_DANGER_THRESHOLD=50` | Override the DANGER score threshold |
169
+ | `SENTRO_WARNING_THRESHOLD=20` | Override the WARNING score threshold |
170
+ | `SENTRO_WHITELIST=requests,numpy` | Comma-separated whitelist |
171
+
172
+ ---
173
+
174
+ ## CI usage
175
+
176
+ ```yaml
177
+ # GitHub Actions example
178
+ - name: Scan dependencies
179
+ run: |
180
+ pip install sentro
181
+ sentro install -r requirements.txt --strict --output-format json > scan.json
182
+ ```
183
+
184
+ The `--strict` flag makes the step fail if any package scores DANGER. The JSON output can be parsed or stored as an artifact.
185
+
186
+ ---
187
+
188
+ ## False positives
189
+
190
+ Some legitimate packages use dynamic imports or `eval()` inside functions (template engines, plugin loaders, REPLs). `sentro` tries to distinguish:
191
+
192
+ - `eval()` / `exec()` **at module level** → DANGER (runs unconditionally on import)
193
+ - `eval()` / `exec()` **inside a function** → WARNING (may be legitimate)
194
+ - `__import__()` **inside a function** → not flagged (standard plugin-loader pattern)
195
+
196
+ If a package you trust keeps triggering warnings, add it to `whitelist_packages` in your config.
197
+
198
+ ---
199
+
200
+ ## Development
201
+
202
+ ```bash
203
+ git clone https://github.com/solvyx-dev/sentro
204
+ cd sentro
205
+ pip install -e ".[dev]"
206
+
207
+ # Run tests (no network required)
208
+ pytest -m "not integration"
209
+
210
+ # Run with coverage
211
+ pytest --cov=sentro --cov-report=term-missing
212
+
213
+ # Run integration tests (requires internet)
214
+ pytest -m integration
215
+ ```
216
+
217
+ ---
218
+
219
+ ## Roadmap
220
+
221
+ - [ ] `requirements.txt` file scanning (`sentro install -r requirements.txt`)
222
+ - [ ] Support for other languages (npm, cargo, gem)
223
+ - [ ] GitHub Action
224
+ - [ ] Cache scan results to avoid re-scanning unchanged packages
225
+
226
+ ---
227
+
228
+ ## License
229
+
230
+ MIT — built and maintained by [Solvyx.dev](https://solvyx.dev)
@@ -0,0 +1,100 @@
1
+ # PyPI Publishing Checklist
2
+
3
+ ## Status: Ready to publish
4
+
5
+ Name confirmed available on PyPI: **`sentro`**
6
+
7
+ ---
8
+
9
+ ## What is already done
10
+
11
+ - [x] Package name `sentro` available on PyPI
12
+ - [x] `README.md` written
13
+ - [x] `pyproject.toml` complete — author: Solvyx, dev@solvyx.dev
14
+ - [x] 91 unit tests passing
15
+ - [x] `build` and `twine` installed
16
+ - [x] All references updated to `sentro`
17
+
18
+ ---
19
+
20
+ ## Publishing steps
21
+
22
+ ### 1. Create a PyPI account
23
+ https://pypi.org/account/register
24
+
25
+ ### 2. Create an API token
26
+ https://pypi.org/manage/account/token/
27
+
28
+ Set scope to "Entire account" for the first upload, then restrict it to the `sentro` project.
29
+
30
+ ### 3. Configure credentials
31
+
32
+ ```bash
33
+ # Option A — ~/.pypirc file
34
+ [pypi]
35
+ username = __token__
36
+ password = pypi-xxxxxxxxxxxxxxxx
37
+
38
+ # Option B — env vars (better for CI)
39
+ export TWINE_USERNAME=__token__
40
+ export TWINE_PASSWORD=pypi-xxxxxxxxxxxxxxxx
41
+ ```
42
+
43
+ ### 4. Build
44
+
45
+ ```bash
46
+ cd /home/ckdev/development/sentro
47
+ python -m build
48
+ # produces:
49
+ # dist/sentro-0.1.0-py3-none-any.whl
50
+ # dist/sentro-0.1.0.tar.gz
51
+ ```
52
+
53
+ ### 5. Test on TestPyPI first
54
+
55
+ ```bash
56
+ twine upload --repository testpypi dist/*
57
+ # verify at: https://test.pypi.org/project/sentro/
58
+
59
+ pip install --index-url https://test.pypi.org/simple/ sentro
60
+ sentro --version
61
+ sentro install requests --no-install
62
+ ```
63
+
64
+ ### 6. Upload to PyPI
65
+
66
+ ```bash
67
+ twine upload dist/*
68
+ ```
69
+
70
+ ### 7. Verify live
71
+
72
+ ```bash
73
+ pip install sentro
74
+ sentro --version
75
+ sentro install requests --no-install
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Bumping the version
81
+
82
+ When ready to release a new version:
83
+
84
+ 1. Update `pyproject.toml` → `version = "x.x.x"`
85
+ 2. Update `src/sentro/_version.py` → `__version__ = "x.x.x"`
86
+ 3. Build and upload again
87
+
88
+ Current version: `0.1.0`
89
+
90
+ Before bumping to `1.0.0` consider:
91
+ - `requirements.txt` file scanning (`sentro install -r requirements.txt`)
92
+ - Broader real-world package testing
93
+ - Stable config format
94
+
95
+ ---
96
+
97
+ ## Notes
98
+
99
+ - `PUBLISH.md` is dev-only — it won't be included in the PyPI distribution
100
+ - The GitHub repo should be at `https://github.com/solvyx-dev/sentro` before publishing
sentro-0.1.0/README.md ADDED
@@ -0,0 +1,204 @@
1
+ # sentro
2
+
3
+ Built by [Solvyx.dev](https://solvyx.dev) — a pip wrapper that scans Python packages for malicious code before installing them.
4
+
5
+ ```bash
6
+ sentro install requests
7
+ ```
8
+
9
+ ```
10
+ ╭──────────────────────── sentro scan ─────────────────────────╮
11
+ │ Package : requests 2.31.0 │
12
+ │ PyPI : verified │
13
+ │ Risk : SAFE (score 0/100) │
14
+ ╰─────────────────────────────────────────────────────────────────╯
15
+ No issues found.
16
+ ```
17
+
18
+ ---
19
+
20
+ ## Why
21
+
22
+ Supply-chain attacks on PyPI are getting more frequent. Attackers publish packages with names one typo away from `requests` or `numpy`, or shadow internal package names to trigger dependency confusion. The malicious code runs at install time inside `setup.py`, or silently on first `import`.
23
+
24
+ `sentro` downloads and scans a package before pip ever touches it.
25
+
26
+ ---
27
+
28
+ ## What it detects
29
+
30
+ | Check | Examples |
31
+ |---|---|
32
+ | **Malicious code** | `eval()` / `exec()` at module level, `os.system()`, `subprocess(shell=True)`, socket connections to hardcoded IPs |
33
+ | **Install hooks** | Dangerous calls in `setup.py` that run unconditionally at install time, `cmdclass` overrides, dynamic `install_requires` |
34
+ | **Obfuscation** | `exec(base64.b64decode(...))` chains, high-entropy string constants, `marshal.loads` payloads |
35
+ | **Typosquatting** | Names similar to popular packages (`reqeusts`, `numpy-dev`), Unicode homoglyphs |
36
+ | **Dependency confusion** | Package names that shadow Python stdlib modules (`json`, `os`, `urllib`) |
37
+ | **Metadata signals** | Package age under 7 days, very low download count, missing author/homepage |
38
+
39
+ Each finding contributes to a risk score (0–100). The overall verdict is **SAFE**, **WARNING**, or **DANGER**.
40
+
41
+ ---
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ pip install sentro
47
+ ```
48
+
49
+ Requires Python 3.11+.
50
+
51
+ ---
52
+
53
+ ## Usage
54
+
55
+ ```bash
56
+ # Scan and install
57
+ sentro install requests
58
+
59
+ # Scan only — don't install
60
+ sentro install requests --no-install
61
+
62
+ # Block installation if anything scores DANGER
63
+ sentro install requests --strict
64
+
65
+ # Pin a version
66
+ sentro install "requests==2.28.0"
67
+
68
+ # Multiple packages
69
+ sentro install requests flask sqlalchemy
70
+
71
+ # JSON output (for CI pipelines)
72
+ sentro install requests --no-install --output-format json
73
+
74
+ # See which installer was detected
75
+ sentro detect-installer
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Flags
81
+
82
+ | Flag | Description |
83
+ |---|---|
84
+ | `--strict` | Exit 1 and block install if any package scores DANGER |
85
+ | `--no-install` | Scan only, don't install |
86
+ | `--skip-scan` | Skip scanning, forward directly to the installer |
87
+ | `--output-format text\|json` | Output format (default: `text`) |
88
+ | `--installer pip\|uv\|conda\|mamba\|poetry\|pipenv\|pdm\|auto` | Installer to use (default: `auto`) |
89
+ | `--config PATH` | Path to a TOML config file |
90
+
91
+ ---
92
+
93
+ ## Installer detection
94
+
95
+ `sentro` auto-detects your package manager so the install step uses the right tool.
96
+
97
+ | Installer | Detected when |
98
+ |---|---|
99
+ | `uv` | `uv` is on PATH and a virtual env is active |
100
+ | `conda` / `mamba` | `CONDA_DEFAULT_ENV` or `CONDA_PREFIX` is set |
101
+ | `poetry` | `pyproject.toml` has `[tool.poetry]` and `poetry` is on PATH |
102
+ | `pipenv` | `Pipfile` exists and `pipenv` is on PATH |
103
+ | `pdm` | `pyproject.toml` has `[tool.pdm]` and `pdm` is on PATH |
104
+ | `pip` | Fallback |
105
+
106
+ Override with `--installer pip` or set `SENTRO_INSTALLER=pip`.
107
+
108
+ ---
109
+
110
+ ## Configuration
111
+
112
+ Create a `.sentro.toml` in your project root (or add `[tool.sentro]` to `pyproject.toml`):
113
+
114
+ ```toml
115
+ [sentro]
116
+ strict = true
117
+
118
+ [sentro.thresholds]
119
+ warning = 30
120
+ danger = 70
121
+
122
+ whitelist_packages = ["requests", "numpy"]
123
+ scanners_disabled = ["metadata"]
124
+ ```
125
+
126
+ Config is merged from multiple sources in this order (last wins):
127
+
128
+ 1. `~/.config/sentro/config.toml` — user-level defaults
129
+ 2. `pyproject.toml` `[tool.sentro]` in the current directory
130
+ 3. `.sentro.toml` in the current directory
131
+ 4. `--config PATH` flag
132
+ 5. `SENTRO_*` environment variables
133
+ 6. CLI flags
134
+
135
+ ### Environment variables
136
+
137
+ | Variable | Effect |
138
+ |---|---|
139
+ | `SENTRO_STRICT=true` | Enable strict mode |
140
+ | `SENTRO_INSTALLER=pip` | Force a specific installer |
141
+ | `SENTRO_OUTPUT_FORMAT=json` | JSON output |
142
+ | `SENTRO_DANGER_THRESHOLD=50` | Override the DANGER score threshold |
143
+ | `SENTRO_WARNING_THRESHOLD=20` | Override the WARNING score threshold |
144
+ | `SENTRO_WHITELIST=requests,numpy` | Comma-separated whitelist |
145
+
146
+ ---
147
+
148
+ ## CI usage
149
+
150
+ ```yaml
151
+ # GitHub Actions example
152
+ - name: Scan dependencies
153
+ run: |
154
+ pip install sentro
155
+ sentro install -r requirements.txt --strict --output-format json > scan.json
156
+ ```
157
+
158
+ The `--strict` flag makes the step fail if any package scores DANGER. The JSON output can be parsed or stored as an artifact.
159
+
160
+ ---
161
+
162
+ ## False positives
163
+
164
+ Some legitimate packages use dynamic imports or `eval()` inside functions (template engines, plugin loaders, REPLs). `sentro` tries to distinguish:
165
+
166
+ - `eval()` / `exec()` **at module level** → DANGER (runs unconditionally on import)
167
+ - `eval()` / `exec()` **inside a function** → WARNING (may be legitimate)
168
+ - `__import__()` **inside a function** → not flagged (standard plugin-loader pattern)
169
+
170
+ If a package you trust keeps triggering warnings, add it to `whitelist_packages` in your config.
171
+
172
+ ---
173
+
174
+ ## Development
175
+
176
+ ```bash
177
+ git clone https://github.com/solvyx-dev/sentro
178
+ cd sentro
179
+ pip install -e ".[dev]"
180
+
181
+ # Run tests (no network required)
182
+ pytest -m "not integration"
183
+
184
+ # Run with coverage
185
+ pytest --cov=sentro --cov-report=term-missing
186
+
187
+ # Run integration tests (requires internet)
188
+ pytest -m integration
189
+ ```
190
+
191
+ ---
192
+
193
+ ## Roadmap
194
+
195
+ - [ ] `requirements.txt` file scanning (`sentro install -r requirements.txt`)
196
+ - [ ] Support for other languages (npm, cargo, gem)
197
+ - [ ] GitHub Action
198
+ - [ ] Cache scan results to avoid re-scanning unchanged packages
199
+
200
+ ---
201
+
202
+ ## License
203
+
204
+ MIT — built and maintained by [Solvyx.dev](https://solvyx.dev)
@@ -0,0 +1,5 @@
1
+ #pypi_token
2
+ pypi-AgEIcHlwaS5vcmcCJDU4NWVmNWE1LTJlNDgtNDkwNC05ZTJiLTg5ZmEyZGEwNmFjNwACKlszLCIzYjNhMDQ4NS00YzIyLTRmZWMtYmZhYS1kYjJlOTYwYzRjYWMiXQAABiDp1kxUluuyn5czGGcGgE7A3oZSX4pYSH-lILOF35JLlA
3
+
4
+ #pytest
5
+ pypi-AgENdGVzdC5weXBpLm9yZwIkYmJiYjJiYjItZmQ0NC00ODEwLTg2MzUtODY5M2E2NTRmMmRmAAIqWzMsImQ0ZjJiYWVkLWMzZWMtNDJhOC1hZGNjLTgzOWVjMDYxOTQ4NyJdAAAGIDrSZxLBJkzqeh6h47AmWXOAkuxOgILfO7xg-b4YQ7VL