package-alert 0.1.0__py3-none-any.whl

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 (47) hide show
  1. package_alert-0.1.0.dist-info/METADATA +433 -0
  2. package_alert-0.1.0.dist-info/RECORD +47 -0
  3. package_alert-0.1.0.dist-info/WHEEL +4 -0
  4. package_alert-0.1.0.dist-info/entry_points.txt +2 -0
  5. package_alert-0.1.0.dist-info/licenses/LICENSE +194 -0
  6. packagealert/__init__.py +1 -0
  7. packagealert/alerts/__init__.py +1 -0
  8. packagealert/alerts/desktop.py +51 -0
  9. packagealert/alerts/terminal.py +65 -0
  10. packagealert/analyzers/__init__.py +1 -0
  11. packagealert/analyzers/risk.py +99 -0
  12. packagealert/cli/__init__.py +1 -0
  13. packagealert/cli/app.py +898 -0
  14. packagealert/cli/status.py +357 -0
  15. packagealert/config.py +147 -0
  16. packagealert/daemon.py +232 -0
  17. packagealert/heuristics/__init__.py +1 -0
  18. packagealert/heuristics/base.py +12 -0
  19. packagealert/heuristics/npm.py +102 -0
  20. packagealert/heuristics/python.py +85 -0
  21. packagealert/heuristics/typosquat.py +80 -0
  22. packagealert/logging_setup.py +49 -0
  23. packagealert/models/__init__.py +1 -0
  24. packagealert/models/advisories.py +30 -0
  25. packagealert/models/events.py +27 -0
  26. packagealert/models/risk.py +27 -0
  27. packagealert/monitors/__init__.py +1 -0
  28. packagealert/monitors/base.py +31 -0
  29. packagealert/monitors/cache.py +160 -0
  30. packagealert/monitors/process.py +236 -0
  31. packagealert/osv/__init__.py +1 -0
  32. packagealert/osv/cache.py +77 -0
  33. packagealert/osv/client.py +142 -0
  34. packagealert/osv/popularity.py +77 -0
  35. packagealert/parsers/__init__.py +1 -0
  36. packagealert/parsers/lockfiles.py +304 -0
  37. packagealert/parsers/npm.py +68 -0
  38. packagealert/parsers/process_args.py +360 -0
  39. packagealert/parsers/wheel.py +58 -0
  40. packagealert/sandbox/__init__.py +0 -0
  41. packagealert/sandbox/bwrap.py +69 -0
  42. packagealert/sandbox/runner.py +992 -0
  43. packagealert/scheduler/__init__.py +0 -0
  44. packagealert/scheduler/db.py +267 -0
  45. packagealert/scheduler/runner.py +228 -0
  46. packagealert/storage/__init__.py +1 -0
  47. packagealert/storage/db.py +111 -0
@@ -0,0 +1,433 @@
1
+ Metadata-Version: 2.4
2
+ Name: package-alert
3
+ Version: 0.1.0
4
+ Summary: Real-time security monitor for Python, Node.js, and PHP package installations
5
+ Project-URL: Homepage, https://github.com/alslater/package-alert
6
+ Project-URL: Repository, https://github.com/alslater/package-alert
7
+ Author-email: Al Slater <al.slater@essiell.com>
8
+ License: Apache-2.0
9
+ License-File: LICENSE
10
+ Keywords: composer,malware,npm,osv,pip,sandbox,security,supply-chain
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Security
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.12
21
+ Requires-Dist: aiosqlite>=0.20
22
+ Requires-Dist: httpx>=0.27
23
+ Requires-Dist: levenshtein>=0.25
24
+ Requires-Dist: psutil>=6
25
+ Requires-Dist: pydantic>=2.7
26
+ Requires-Dist: rich>=13
27
+ Requires-Dist: typer>=0.12
28
+ Requires-Dist: watchdog>=4
29
+ Provides-Extra: dev
30
+ Requires-Dist: hatch; extra == 'dev'
31
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
32
+ Requires-Dist: pytest-mock>=3; extra == 'dev'
33
+ Requires-Dist: pytest>=8; extra == 'dev'
34
+ Requires-Dist: respx>=0.21; extra == 'dev'
35
+ Description-Content-Type: text/markdown
36
+
37
+ # package-alert
38
+
39
+ **package-alert** monitors Python, Node.js, and PHP package installations in real time and alerts developers when a malicious or suspicious package is detected. It can also run package manager commands inside an isolated bubblewrap sandbox with pre-flight and post-install OSV checks, scan project lock files or installed environments on demand, and schedule automatic daily or weekly scans across multiple projects.
40
+
41
+ ## Features
42
+
43
+ - **Real-time process monitoring** — detects `pip install`, `uv add`, `uv sync`, `pipenv install`, `npm install`, `composer require`, and more as they happen
44
+ - **Lock file scanning** — after a lock-file-based install finishes, reads the lock file for exact package versions and scans all of them in a single OSV batch call
45
+ - **Cache monitoring** — watches pip/uv/npm cache directories for newly downloaded packages
46
+ - **OSV.dev integration** — checks every package against the [Open Source Vulnerabilities](https://osv.dev) database
47
+ - **Heuristic risk scoring** — detects suspicious packages even without a known advisory
48
+ - **Typosquatting detection** — flags packages that closely resemble popular libraries (Levenshtein distance)
49
+ - **Popularity signal** — queries deps.dev to flag packages with very few versions or dependents
50
+ - **Low latency alerts** — Rich terminal panel + `notify-send` desktop notifications
51
+ - **Alert history** — all alerts persisted in SQLite with package name, version, advisory, and project path
52
+ - **Sandboxed installs** — `package-alert run` wraps any package manager command in a bubblewrap sandbox with pre-flight and post-install OSV checks
53
+
54
+ ## Supported Ecosystems
55
+
56
+ | Ecosystem | Package managers monitored | Lock files scanned |
57
+ |-----------|---------------------------|-------------------|
58
+ | PyPI | `pip`, `python -m pip`, `uv add`, `uv sync`, `uv lock`, `pipenv install` | `uv.lock`, `Pipfile.lock`, `requirements.txt` |
59
+ | npm | `npm install`, `npm add`, `npm ci` | `package-lock.json` |
60
+ | Packagist | `composer install`, `composer update`, `composer require`, `php composer.phar …` | `composer.lock`, `composer.json` |
61
+
62
+ ## Installation
63
+
64
+ **Recommended — pipx (isolated environment, `package-alert` available system-wide):**
65
+
66
+ ```bash
67
+ pipx install package-alert
68
+ ```
69
+
70
+ **Development install:**
71
+
72
+ ```bash
73
+ pipx install -e .
74
+ ```
75
+
76
+ ## Quick Start
77
+
78
+ ```bash
79
+ # Start the background daemon
80
+ package-alert daemon
81
+
82
+ # Check daemon status
83
+ package-alert status
84
+
85
+ # Run a package manager command in a sandbox
86
+ package-alert run uv sync
87
+ package-alert run npm install
88
+
89
+ # Scan the current project's lock files for vulnerabilities
90
+ package-alert scan-project
91
+
92
+ # Scan an explicit requirements file (e.g. a pinned CI lockfile)
93
+ package-alert scan-project -r requirements-lock.txt
94
+
95
+ # Query a specific package
96
+ package-alert query requests 2.31.0
97
+
98
+ # View recent alerts
99
+ package-alert alerts
100
+ ```
101
+
102
+ ## Commands
103
+
104
+ ### Global options
105
+
106
+ | Option | Description |
107
+ |--------|-------------|
108
+ | `--verbose` / `-v` | Print log output to the console. Without this flag log output is written only to the configured log file. |
109
+ | `--config` / `-c` | Path to a TOML config file (overrides the default `~/.config/package-alert/config.toml`). |
110
+
111
+ ### `daemon`
112
+
113
+ Start the monitoring daemon. Only one instance may run at a time (enforced via a PID file at `~/.local/share/package-alert/daemon.pid`).
114
+
115
+ ```bash
116
+ package-alert daemon [--config PATH]
117
+ ```
118
+
119
+ The daemon:
120
+ 1. Polls running processes every second for package manager invocations
121
+ 2. Watches pip/uv/npm cache directories with inotify for newly downloaded wheels/tarballs
122
+ 3. Dynamically registers site-packages directories when a venv install is detected
123
+ 4. Waits for lock-file-based installs (npm, uv sync/lock, pipenv, composer) to finish, then reads the lock file and sends all packages to OSV in a single batch call
124
+ 5. Checks each package against OSV; fires alerts for malicious packages or those exceeding the heuristic risk threshold
125
+
126
+ ### `run`
127
+
128
+ Run a package manager command inside a [bubblewrap](https://github.com/containers/bubblewrap) sandbox.
129
+
130
+ ```bash
131
+ package-alert run [--no-network] <command> [args...]
132
+ ```
133
+
134
+ **Examples:**
135
+
136
+ ```bash
137
+ package-alert run uv sync
138
+ package-alert run uv add httpx
139
+ package-alert run pip install requests flask==3.0.0
140
+ package-alert run npm install
141
+ package-alert run npm install lodash@4.17.21
142
+ package-alert run composer install
143
+ package-alert run --no-network uv sync # fully offline; uv cache must be warm
144
+ ```
145
+
146
+ **What it does:**
147
+
148
+ 1. **Pre-flight check** — identifies what will be installed (from the command arguments or the project lock file) and batch-queries OSV before anything runs. Blocks immediately if a known-malicious package is found.
149
+ 2. **Sandboxed execution** — runs the command inside a bubblewrap namespace with layered filesystem isolation (see below). Network access is **allowed by default** so package managers can reach their registries; use `--no-network` only when all packages are already cached locally.
150
+ 3. **Post-install scan** — diffs the install targets against a pre-run snapshot, identifies new packages by their metadata files (`.dist-info`, `package.json`, `composer.json`), and runs another OSV check on everything that appeared.
151
+
152
+ | Option | Description |
153
+ |--------|-------------|
154
+ | `--no-network` | Block all outbound network inside the sandbox. Use only when all packages are already in the local cache. |
155
+ | `--env VAR` | Pass an additional environment variable through into the sandbox. Repeatable: `--env MY_TOKEN --env CUSTOM_URL`. |
156
+ | `--expose-ssh-keys` | Expose `~/.ssh` read-only inside the sandbox. Required when installing packages with `git+ssh://` or scp-style (`git@host:org/repo`) VCS dependencies. package-alert detects these automatically and suggests the flag if it is not passed. |
157
+ | `--config PATH` | Path to config TOML file. |
158
+
159
+ **Filesystem isolation:**
160
+
161
+ The sandbox uses a layered mount strategy to prevent install-time scripts from reading credentials or secrets outside the project:
162
+
163
+ | Layer | What happens |
164
+ |-------|-------------|
165
+ | `/` read-only | The entire filesystem is mounted read-only — install scripts cannot modify system files or other projects. |
166
+ | `$HOME` hidden | A fresh empty tmpfs is overlaid on the home directory, hiding `~/.ssh`, `~/.aws`, `~/.gnupg`, `.env` files in sibling projects, and any other secrets stored there. |
167
+ | Safe home paths re-exposed | A curated allowlist of home subdirectories is re-mounted read-only inside the tmpfs so package managers can function normally (see table below). |
168
+ | Install targets writable | The project directory, site-packages/`node_modules`/`vendor`, and package manager caches are bound writable on top of the above. |
169
+
170
+ Paths re-exposed inside the home tmpfs (read-only):
171
+
172
+ | Path | Purpose |
173
+ |------|---------|
174
+ | `$PYENV_ROOT` (`~/.pyenv`) | pyenv-managed Python installations |
175
+ | `$NVM_DIR` (`~/.nvm`) | nvm-managed Node.js installations |
176
+ | `~/.local/bin` | User-local binaries (uv, pip-installed scripts, etc.) |
177
+ | `~/.local/share/uv` | uv-managed Python installations and tool environments |
178
+ | `~/.local/pipx` | pipx-managed tool environments (shebangs in `~/.local/bin` may point here) |
179
+ | `~/.config/pip`, `~/.pip` | pip configuration (index URLs, proxy settings) |
180
+ | `~/.config/uv` | uv configuration |
181
+ | `~/.npmrc` | npm registry and auth configuration |
182
+ | `~/.cache/pip`, `~/.cache/uv`, `~/.npm` | Package manager caches (writable) |
183
+ | `~/.config/composer` | Composer home (writable, when present) |
184
+
185
+ Paths that are **not** accessible inside the sandbox by default: `~/.ssh`, `~/.aws`, `~/.gnupg`, `~/.config/gcloud`, `~/.netrc`, `~/.git-credentials`, and everything else in `$HOME` not listed above. Pass `--expose-ssh-keys` to re-expose `~/.ssh` read-only when SSH-authenticated VCS dependencies are needed.
186
+
187
+ **Environment isolation:**
188
+
189
+ The sandbox process also starts with a stripped environment. A curated set of variables is forwarded (PATH, HOME, locale, proxy settings, registry URLs for pip/uv/npm/composer, SSL certificates, pyenv/nvm locations). Variables not in this allowlist are removed. Use `--env VAR` on the command line or `sandbox.extra_env` in the config file to forward additional variables.
190
+
191
+ **Requirements:** `bwrap` (bubblewrap) must be installed.
192
+
193
+ ```bash
194
+ # Ubuntu/Debian
195
+ sudo apt install bubblewrap
196
+
197
+ # Fedora/RHEL
198
+ sudo dnf install bubblewrap
199
+
200
+ # Arch
201
+ sudo pacman -S bubblewrap
202
+ ```
203
+
204
+ **Virtual environment detection:** for Python commands, package-alert automatically detects the target site-packages directory by checking (in order) the executable path in the command, `VIRTUAL_ENV` (pip/pipenv only — uv always uses the project-local `.venv`), and `.venv`/`venv` directories in the current working directory.
205
+
206
+ ### `status`
207
+
208
+ Show the current state of the daemon and related paths.
209
+
210
+ ```bash
211
+ package-alert status [--json] [--config PATH]
212
+ ```
213
+
214
+ Displays:
215
+
216
+ - Daemon running/stopped, PID, uptime, and whether it was started by systemd
217
+ - Config file path in use
218
+ - Daemon log file path and whether it exists
219
+ - CLI log file path and whether it exists
220
+
221
+ Use `--json` for machine-readable output.
222
+
223
+ ### `scan-project`
224
+
225
+ Scan a project directory for vulnerable or malicious packages.
226
+
227
+ ```bash
228
+ package-alert scan-project [PATH] [OPTIONS]
229
+ ```
230
+
231
+ | Option | Default | Description |
232
+ |--------|---------|-------------|
233
+ | `PATH` | `.` | Project directory |
234
+ | `--scan-unpinned` | off | Also query OSV for unpinned/range-constrained dependencies |
235
+ | `--scan-installed` | off | Scan `venv/.venv` site-packages or `node_modules` instead of lock files |
236
+ | `--requirements` / `-r` | — | Explicit requirements file to scan instead of auto-detecting lock files (mutually exclusive with `--scan-installed`) |
237
+ | `--details` / `-d` | off | Show full advisory details and URL |
238
+ | `--format` / `-f` | `text` | Output format: `text`, `json`, `html`, `browser` |
239
+
240
+ **Formats:**
241
+
242
+ - `text` — colour-coded terminal output; severity badge on the advisory line (`[HIGH] GHSA-…`)
243
+ - `json` — machine-readable JSON with all findings, unpinned packages, and sources
244
+ - `html` — self-contained HTML report printed to stdout
245
+ - `browser` — writes HTML to `/tmp/package-alert-*.html` and opens it in the default browser
246
+
247
+ `--requirements` accepts a path relative to `PATH` (the project directory) or an absolute path. Nested `-r`/`--requirement` includes within the file are followed recursively. `--requirements` and `--scan-installed` are mutually exclusive.
248
+
249
+ **Auto-detected lock files (in order of precedence):**
250
+
251
+ - `package-lock.json` → npm
252
+ - `uv.lock` → PyPI (uv)
253
+ - `Pipfile.lock` → PyPI (pipenv)
254
+ - `requirements.txt` / `requirements/base.txt` / `requirements/prod.txt` → PyPI (only when no uv/pipenv lock found)
255
+ - `composer.lock` → Packagist
256
+ - `composer.json` (fallback when no lock file) → Packagist
257
+
258
+ ### `scan-cache`
259
+
260
+ Scan pip and uv cache directories for wheels that have known malicious advisories.
261
+
262
+ ```bash
263
+ package-alert scan-cache [--config PATH]
264
+ ```
265
+
266
+ ### `query`
267
+
268
+ Query OSV for a specific package, with full advisory details.
269
+
270
+ ```bash
271
+ package-alert query PACKAGE [VERSION] [--ecosystem pypi|npm] [--config PATH]
272
+ ```
273
+
274
+ ### `alerts`
275
+
276
+ Show recent alerts stored in the database.
277
+
278
+ ```bash
279
+ package-alert alerts [--limit N] [--config PATH]
280
+ ```
281
+
282
+ Displays a table with: package name, ecosystem, version, advisory ID or risk score, project path, and timestamp.
283
+
284
+ ### `clear-cache`
285
+
286
+ Clear the OSV query cache.
287
+
288
+ ```bash
289
+ package-alert clear-cache [--ecosystem pypi|npm] [--config PATH]
290
+ ```
291
+
292
+ Omit `--ecosystem` to clear all ecosystems.
293
+
294
+ ### `config-show`
295
+
296
+ Print the resolved configuration as JSON (useful for verifying config file is being read).
297
+
298
+ ```bash
299
+ package-alert config-show [--config PATH]
300
+ ```
301
+
302
+ ### Scheduled Scans
303
+
304
+ Register projects for automatic daily or weekly scans run by the daemon. Each path can be registered for multiple scan types independently.
305
+
306
+ ```bash
307
+ # Register the current project for daily lock-file scans
308
+ package-alert schedule add --daily
309
+
310
+ # Also register for weekly installed-packages scans (both coexist independently)
311
+ package-alert schedule add --weekly --installed
312
+
313
+ # Register a specific path
314
+ package-alert schedule add /path/to/project --daily
315
+
316
+ # List all registered projects (shows all path/scan_type pairs)
317
+ package-alert schedule list
318
+
319
+ # Remove only the installed-packages scan entry
320
+ package-alert schedule remove --installed
321
+
322
+ # Remove all scan entries for the current project
323
+ package-alert schedule remove
324
+
325
+ # List completed scans for the current project (newest first)
326
+ package-alert scans list
327
+ package-alert scans list /path/to/project --limit 10
328
+
329
+ # Show findings from a specific scan
330
+ package-alert scans show 42
331
+ package-alert scans show 42 --format json
332
+ package-alert scans show 42 --format html
333
+ package-alert scans show 42 --format browser
334
+ package-alert scans show 42 --details
335
+ ```
336
+
337
+ ## Configuration
338
+
339
+ Config is loaded from `~/.config/package-alert/config.toml` automatically if it exists. Override with `--config PATH` on any command.
340
+
341
+ ```toml
342
+ # Logging for the long-running daemon process.
343
+ [log]
344
+ level = "INFO" # DEBUG, INFO, WARNING, ERROR, CRITICAL
345
+ file = "~/.local/share/package-alert/daemon.log" # set file = "" to disable file logging
346
+ # max_bytes = 10485760 # 10 MB per file before rotation
347
+ # backup_count = 3
348
+
349
+ # Logging for short-lived CLI commands (scan-project, query, alerts, etc.).
350
+ [cli_log]
351
+ level = "INFO"
352
+ file = "~/.local/share/package-alert/cli.log" # set file = "" to disable file logging
353
+
354
+ [watch]
355
+ enable_cache_monitoring = true
356
+ enable_process_monitoring = true
357
+ pip_cache_dir = "~/.cache/pip"
358
+ uv_cache_dir = "~/.cache/uv"
359
+ npm_cache_dir = "~/.npm/_cacache"
360
+ site_packages_dirs = [] # extra site-packages to watch
361
+ process_poll_interval_seconds = 1.0
362
+
363
+ [osv]
364
+ base_url = "https://api.osv.dev/v1"
365
+ cache_ttl_hours = 24
366
+ timeout_seconds = 10.0
367
+ max_retries = 3
368
+
369
+ [alerts]
370
+ desktop_notifications = true
371
+ terminal_notifications = true
372
+ min_severity_for_desktop = "MEDIUM"
373
+
374
+ [heuristics]
375
+ enabled = true
376
+ warning_threshold = 40
377
+ critical_threshold = 70
378
+
379
+ [sandbox]
380
+ # Additional environment variable names to forward into the sandbox beyond
381
+ # the built-in allowlist (PATH, HOME, proxy vars, registry URLs, etc.).
382
+ extra_env = []
383
+ # Example: extra_env = ["MY_PRIVATE_REGISTRY_TOKEN", "CUSTOM_CERT_PATH"]
384
+
385
+ # Additional paths to mount as empty tmpfs inside the sandbox.
386
+ # Use this on systems where other root-owned paths cause tool failures inside
387
+ # bwrap's user namespace (e.g. SSH proxy config files owned by root).
388
+ extra_tmpfs = []
389
+ # Example: extra_tmpfs = ["/etc/ssh/other_config.d"]
390
+
391
+ [scheduler]
392
+ enabled = true
393
+ daily_hour = 2 # hour of day (0–23) to run daily scans
394
+ weekly_day = 6 # day of week to run weekly scans (0=Mon … 6=Sun)
395
+ weekly_hour = 2 # hour of day to run weekly scans
396
+ max_scan_history = 5 # completed scan records to keep per project per scan type
397
+ ```
398
+
399
+ **Scan types:**
400
+
401
+ - `project` (default) — scans lock files (`requirements.txt`, `uv.lock`, `package-lock.json`, `composer.lock`). Reproducible; works offline with cached OSV results.
402
+ - `installed` — enumerates packages actually installed in the project's virtual environment (`pip list`, `npm ls`, `composer show`). Catches drift between lock file and real environment.
403
+
404
+ ## Data Storage
405
+
406
+ All persistent data lives in `~/.local/share/package-alert/`:
407
+
408
+ | File | Purpose |
409
+ |------|---------|
410
+ | `package-alert.db` | SQLite database: OSV cache, alert history, popularity cache |
411
+ | `daemon.log` | Rotating daemon log file (10 MB × 3 backups) |
412
+ | `cli.log` | Rotating CLI command log file (10 MB × 3 backups) |
413
+ | `daemon.pid` | PID file used to prevent duplicate daemon instances |
414
+
415
+ ## systemd (Linux)
416
+
417
+ ```bash
418
+ mkdir -p ~/.config/systemd/user
419
+ cp package-alert.service ~/.config/systemd/user/
420
+ systemctl --user enable --now package-alert
421
+ ```
422
+
423
+ ## Architecture
424
+
425
+ See [ARCHITECTURE.md](ARCHITECTURE.md).
426
+
427
+ ## Security
428
+
429
+ See [THREAT_MODEL.md](THREAT_MODEL.md).
430
+
431
+ ## Roadmap
432
+
433
+ See [ROADMAP.md](ROADMAP.md).
@@ -0,0 +1,47 @@
1
+ packagealert/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
2
+ packagealert/config.py,sha256=i8fVuq1ksArMYt3p-fkmjMF64-gYghCXgdffeKVQNko,4640
3
+ packagealert/daemon.py,sha256=xMKVfvl5_SG9G0QyETOI2IABLf48WrHI2Lw6ondL3KA,8853
4
+ packagealert/logging_setup.py,sha256=jd_yd161jDlw8k2dJcjrLt2x8lki-LgapXqlIyMT5E4,1445
5
+ packagealert/alerts/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
6
+ packagealert/alerts/desktop.py,sha256=dwfRltaRZxAFq1NNdNTlj3-E3Y4ROi-w1yN09FZwpzg,1723
7
+ packagealert/alerts/terminal.py,sha256=YglcEe1XdcAVNOpoqw2nISufu-txgXIMOaDvtcP5SGM,2317
8
+ packagealert/analyzers/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
9
+ packagealert/analyzers/risk.py,sha256=K4mfUdPiB4oZ_DEYpapuqK9C0nWRGlI-e9GEbmvQTX0,4062
10
+ packagealert/cli/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
11
+ packagealert/cli/app.py,sha256=bpWQRdXBFcrAm1kjAdq12NjCORxKCbuuwXe7LINuf_s,32747
12
+ packagealert/cli/status.py,sha256=i7EFN7hqvkINVOi1ROFBAZWMfohtp-Li-NUS-GNMWAc,13685
13
+ packagealert/heuristics/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
14
+ packagealert/heuristics/base.py,sha256=iAku5fzHSYNzpg5S7Y5JZ4LsifXjoE6I7mLWbBA9730,278
15
+ packagealert/heuristics/npm.py,sha256=9I1yh9Str37SaYVURU8j0E1-5SOxuTZQ1pw8e2iHlN0,3431
16
+ packagealert/heuristics/python.py,sha256=f0RgI_LfHkloS4Zf4ElduYsLnNmKDsP-ePNrkOyIuMg,2908
17
+ packagealert/heuristics/typosquat.py,sha256=bbAbezj4n_Tvwfgu_hAJAlgZz0IOH43z1hFLAS6zThE,3198
18
+ packagealert/models/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
19
+ packagealert/models/advisories.py,sha256=WdeIu4_h73thQzJm_9sb1vbAZqiJ6Cn2KsDg79fI0Qo,718
20
+ packagealert/models/events.py,sha256=84vJHF9_-emI8yjK3PuhBVaHH2bV77RDVGYov5EGFhE,773
21
+ packagealert/models/risk.py,sha256=Yp_2zkL_xqrNYMmTZwCGlKfL6WBesuG8XBBuKLkDeww,541
22
+ packagealert/monitors/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
23
+ packagealert/monitors/base.py,sha256=-UW-zgMts-AFX-okaoHKyt_22Dg6_6DdZsWnJPc1iwg,924
24
+ packagealert/monitors/cache.py,sha256=KlrmQeB47YLgyK5wm8ptAAY7ZB9Zyua1v4HzxTw9IbI,5717
25
+ packagealert/monitors/process.py,sha256=Yn5AtUX5Wg-UKr2GstwiFIYjqoZzrx3B6uqMIXXBrCQ,9044
26
+ packagealert/osv/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
27
+ packagealert/osv/cache.py,sha256=Ia2b7CGB0xZ0p3g61cfbln6zs3_3mbzuDG9APAd-yhU,2745
28
+ packagealert/osv/client.py,sha256=d1CJtWDzRbj74BXGE5_B6oBpTGmqBux-8W6yUFMMm6I,5806
29
+ packagealert/osv/popularity.py,sha256=EUbu1rahBrACEmUGTNgcKzdFpfqYadQuuQrTMbEcogk,2656
30
+ packagealert/parsers/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
31
+ packagealert/parsers/lockfiles.py,sha256=0lYZvvxA2DRqDcp-gootqf9izgH-lwsHgJnVzHjBAS8,10485
32
+ packagealert/parsers/npm.py,sha256=MQQ7HcP7nsfIIL3qHtJWWU-NiW6Ffq9M87dMcmyk4DQ,2250
33
+ packagealert/parsers/process_args.py,sha256=9eFGyNxwyOD7_1h1N3xlde4O73x0L3GSzKk2JNsk2Fc,14111
34
+ packagealert/parsers/wheel.py,sha256=10MwkO8Bfxqimoekf_ZnPMwdJHwXSUPnyFg-Fr1P1sk,1790
35
+ packagealert/sandbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
+ packagealert/sandbox/bwrap.py,sha256=TVVkvu0cX6rNpmgGG6YXDfyxDdjrvE7_6CNpHp4_VPw,2754
37
+ packagealert/sandbox/runner.py,sha256=C1k7UVeEL29T-yW0kYrNfrqcF0mdV-DHvdBhDPEi2ng,40718
38
+ packagealert/scheduler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
+ packagealert/scheduler/db.py,sha256=M0htE8pzIeB8424bCnlPeS4y1NJ8TLUi-25J2QZB4tQ,8540
40
+ packagealert/scheduler/runner.py,sha256=_pYJMvoeq7w3khaWX2n79NhXZArwJZdMgT9FsRmdSTM,8819
41
+ packagealert/storage/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
42
+ packagealert/storage/db.py,sha256=kHMwMzIrqFFkV3AGfdUDzHIvi7KE3sWbUDk3Q-JcgW8,3714
43
+ package_alert-0.1.0.dist-info/METADATA,sha256=vfmnX1IAuTBTPx9i3z3Zd9HWCRSP9H2ogtSy5tAswYk,17361
44
+ package_alert-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
45
+ package_alert-0.1.0.dist-info/entry_points.txt,sha256=WVyua0xmy_uXc8030vDHnx9L-HYm38oXlG-CXYJnDMo,60
46
+ package_alert-0.1.0.dist-info/licenses/LICENSE,sha256=XTZ0pVGuaqGagC9i75KwOcpCn7bQh9DWwkKH10epLzo,10882
47
+ package_alert-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ package-alert = packagealert.cli.app:main