ghostpkg 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.
@@ -0,0 +1,24 @@
1
+ name: Bug
2
+ description: Something crashed or behaved incorrectly
3
+ labels: ["bug"]
4
+ body:
5
+ - type: textarea
6
+ id: what
7
+ attributes:
8
+ label: What happened
9
+ validations:
10
+ required: true
11
+ - type: textarea
12
+ id: repro
13
+ attributes:
14
+ label: Command you ran
15
+ render: shell
16
+ validations:
17
+ required: true
18
+ - type: input
19
+ id: version
20
+ attributes:
21
+ label: ghostpkg version and OS
22
+ placeholder: "0.1.0, Windows 11, Python 3.12"
23
+ validations:
24
+ required: true
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Security vulnerability
4
+ url: https://github.com/M1rwana12/ghostpkg/security/advisories/new
5
+ about: Please report security issues privately, not as a public issue.
@@ -0,0 +1,40 @@
1
+ name: False positive
2
+ description: ghostpkg flagged a package that is actually fine
3
+ labels: ["false-positive", "bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ This is the most valuable report you can file. A tool that cries wolf on
9
+ real packages gets turned off, and then it protects nothing.
10
+ - type: input
11
+ id: package
12
+ attributes:
13
+ label: Package name
14
+ placeholder: some-real-package
15
+ validations:
16
+ required: true
17
+ - type: dropdown
18
+ id: ecosystem
19
+ attributes:
20
+ label: Ecosystem
21
+ options: [pypi, npm]
22
+ validations:
23
+ required: true
24
+ - type: textarea
25
+ id: output
26
+ attributes:
27
+ label: Output
28
+ description: Paste the full output, ideally from `ghostpkg check <name> --json`.
29
+ render: shell
30
+ validations:
31
+ required: true
32
+ - type: checkboxes
33
+ id: strict
34
+ attributes:
35
+ label: Were you using --strict?
36
+ description: >
37
+ --strict promotes warnings to blocks and is documented as flagging
38
+ legitimate new packages. That behaviour is expected.
39
+ options:
40
+ - label: I was NOT using --strict
@@ -0,0 +1,30 @@
1
+ name: Missed detection
2
+ description: ghostpkg passed a package it should have caught
3
+ labels: ["missed-detection"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Note the known limitation first: a hallucinated name that an attacker has
9
+ **already registered** passes the existence check by design. That case is
10
+ tracked as the project's main open problem — but concrete examples are
11
+ still very useful, so please file it.
12
+ - type: input
13
+ id: package
14
+ attributes:
15
+ label: Package name
16
+ validations:
17
+ required: true
18
+ - type: dropdown
19
+ id: ecosystem
20
+ attributes:
21
+ label: Ecosystem
22
+ options: [pypi, npm]
23
+ validations:
24
+ required: true
25
+ - type: textarea
26
+ id: why
27
+ attributes:
28
+ label: Why should it have been caught?
29
+ validations:
30
+ required: true
@@ -0,0 +1,26 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ${{ matrix.os }}
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu-latest, macos-latest, windows-latest]
15
+ python-version: ["3.9", "3.12", "3.13"]
16
+ steps:
17
+ - uses: actions/checkout@v7
18
+ - uses: actions/setup-python@v7
19
+ with:
20
+ python-version: ${{ matrix.python-version }}
21
+ - run: pip install -e ".[dev]"
22
+ - run: pytest -q
23
+ - name: CLI smoke test
24
+ run: |
25
+ ghostpkg --version
26
+ ghostpkg check requests
@@ -0,0 +1,69 @@
1
+ # --- Secrets: never commit credentials ---
2
+ # Token/credential files
3
+ *.token
4
+ *.secret
5
+ *.key
6
+ *.pem
7
+ *.pfx
8
+ *.p12
9
+ .env
10
+ .env.*
11
+ !.env.example
12
+ secrets.*
13
+ credentials.*
14
+ auth.json
15
+ hosts.yml
16
+ .netrc
17
+ _netrc
18
+
19
+ # gh / git credential stores (should never be here, blocked defensively)
20
+ .config/gh/
21
+ .gh/
22
+ .git-credentials
23
+
24
+ # --- Windows ---
25
+ Thumbs.db
26
+ ehthumbs.db
27
+ Desktop.ini
28
+ $RECYCLE.BIN/
29
+ *.lnk
30
+
31
+ # --- Editors / IDE ---
32
+ .vscode/
33
+ .idea/
34
+ *.swp
35
+ *.swo
36
+ *~
37
+
38
+ # --- Build / temp ---
39
+ dist/
40
+ build/
41
+ out/
42
+ tmp/
43
+ temp/
44
+ *.log
45
+ *.tmp
46
+ *.bak
47
+
48
+ # --- Language ecosystems ---
49
+ node_modules/
50
+ __pycache__/
51
+ *.py[cod]
52
+ .venv/
53
+ venv/
54
+ .pytest_cache/
55
+ target/
56
+
57
+ # --- Local scratch (never published) ---
58
+ scratch/
59
+ .local/
60
+
61
+ # Internal planning document -- deliberately not published.
62
+ # It is the portfolio strategy doc, not part of this tool.
63
+ PLAN.md
64
+
65
+ # Playwright MCP scratch output
66
+ .playwright-mcp/
67
+
68
+ # Banner art-direction options (working files, not shipped)
69
+ banner-options/
@@ -0,0 +1,39 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
5
+ this project uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.0] - 2026-09-01
10
+
11
+ First release.
12
+
13
+ ### Added
14
+ - `ghostpkg check` — check one or more package names against PyPI or npm.
15
+ - `ghostpkg scan` — check every dependency in `requirements.txt` or `package.json`.
16
+ - Verdicts: `BLOCK` for names absent from the registry, `WARN` for weak signals
17
+ (recent publication, single release, missing repository link, small edit
18
+ distance to a popular name), `OK` otherwise.
19
+ - `--strict` to promote warnings to blocks, `--json` for machine-readable output,
20
+ `-q/--quiet` to hide passing packages.
21
+ - Exit codes: `0` nothing blocked, `1` something blocked, `2` usage or registry
22
+ error.
23
+ - Bundled list of the 2,000 most-downloaded PyPI projects, used only for typo
24
+ distance.
25
+
26
+ ### Notes on the design
27
+ - The default profile blocks on **non-existence only**. An earlier version scored
28
+ packages and blocked anything suspicious; measured against the live feed of
29
+ newly published PyPI packages, it flagged 100% of legitimate same-day
30
+ publications. Age cannot separate a malicious registration from an honest new
31
+ release, so softer signals are warnings.
32
+ - The typo-distance budget scales with name length. A flat budget flagged `flask`,
33
+ `click` and `black` as typos of one another.
34
+ - Zero runtime dependencies, by policy.
35
+ - No corpus of hallucinated package names is shipped, following the decision of
36
+ the USENIX'25 authors not to publish theirs.
37
+
38
+ [Unreleased]: https://github.com/M1rwana12/ghostpkg/compare/v0.1.0...HEAD
39
+ [0.1.0]: https://github.com/M1rwana12/ghostpkg/releases/tag/v0.1.0
@@ -0,0 +1,69 @@
1
+ # Contributing to ghostpkg
2
+
3
+ Thanks for looking. This is a small, deliberately narrow tool, and the bar for
4
+ changes is mostly about keeping it that way.
5
+
6
+ ## Getting set up
7
+
8
+ ```bash
9
+ git clone https://github.com/M1rwana12/ghostpkg
10
+ cd ghostpkg
11
+ pip install -e ".[dev]"
12
+ pytest
13
+ ```
14
+
15
+ The test suite constructs `PackageFacts` directly and never touches the network,
16
+ so it runs offline and cannot break because a real package changed.
17
+
18
+ ## The two rules that shape this project
19
+
20
+ **1. No runtime dependencies.** A supply-chain security tool that installs a
21
+ dependency tree of its own undermines its own argument. Standard library only.
22
+ A pull request that adds a runtime dependency will be declined regardless of how
23
+ useful the dependency is.
24
+
25
+ **2. A false positive is worse than a miss.** People run this in front of every
26
+ install. If it cries wolf on a legitimate package, they turn it off, and then it
27
+ protects nothing.
28
+
29
+ That second rule is not a preference, it's a measurement. The first version of
30
+ this tool scored packages on age, release count and missing repository links,
31
+ then blocked anything suspicious. Tested against the live feed of newly published
32
+ PyPI packages, it flagged **100% of them**. A malicious slopsquat registered
33
+ three days ago and an honest new library published three days ago are the same
34
+ package from the outside.
35
+
36
+ So: the default profile blocks on non-existence only. If you want to propose a
37
+ new blocking signal, bring evidence that it does not fire on legitimate packages.
38
+
39
+ ## Especially welcome
40
+
41
+ - **False positive reports.** If `ghostpkg` flagged something real, that's a bug
42
+ and it's the most valuable report you can file.
43
+ - **The open problem:** detecting a hallucinated name that an attacker has
44
+ *already registered*. The existence check cannot see it. If you have an idea
45
+ that does not collapse into "block everything new", open an issue.
46
+ - npm coverage. The popular-name list used for typo distance is PyPI-derived, so
47
+ npm typosquat detection is weaker than it should be.
48
+ - More ecosystems: crates.io, RubyGems, Go modules.
49
+
50
+ ## Please don't
51
+
52
+ - **Do not add a corpus of hallucinated package names to this repository.** The
53
+ authors of the USENIX'25 study withheld theirs deliberately, because such a
54
+ list is a ready-made target list for attackers pre-registering those names.
55
+ That reasoning applies here. This project checks names live and ships no corpus.
56
+ - Don't broaden the scope into code scanning or malware detection. Other tools do
57
+ that well.
58
+
59
+ ## Style
60
+
61
+ Match the surrounding code. Type hints on public functions, `from __future__
62
+ import annotations` at the top of each module (the package supports Python 3.9).
63
+ Comments explain *why*, not *what* — several comments in `assess.py` record the
64
+ measurement behind a decision, and that is the kind worth writing.
65
+
66
+ ## Pull requests
67
+
68
+ Keep them focused. Add a test. CI runs on Linux, macOS and Windows across Python
69
+ 3.9, 3.12 and 3.13, and it needs to be green.
ghostpkg-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 m1rwana12
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.