{"id":36990330,"url":"https://github.com/thekitchencoder/package-scan","last_synced_at":"2026-01-13T23:36:03.541Z","repository":{"id":327544621,"uuid":"1109234265","full_name":"thekitchencoder/package-scan","owner":"thekitchencoder","description":"Multi-Ecosystem Package version Threat Scanner","archived":false,"fork":false,"pushed_at":"2025-12-06T09:43:55.000Z","size":349,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-07T14:37:36.593Z","etag":null,"topics":["hulud","security-tools"],"latest_commit_sha":null,"homepage":"https://thekitchencoder.github.io/package-scan/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thekitchencoder.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-12-03T14:20:50.000Z","updated_at":"2025-12-06T09:21:20.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/thekitchencoder/package-scan","commit_stats":null,"previous_names":["thekitchencoder/hulud-scan"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/thekitchencoder/package-scan","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thekitchencoder%2Fpackage-scan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thekitchencoder%2Fpackage-scan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thekitchencoder%2Fpackage-scan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thekitchencoder%2Fpackage-scan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thekitchencoder","download_url":"https://codeload.github.com/thekitchencoder/package-scan/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thekitchencoder%2Fpackage-scan/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28399508,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-13T14:36:09.778Z","status":"ssl_error","status_checked_at":"2026-01-13T14:35:19.697Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hulud","security-tools"],"created_at":"2026-01-13T23:36:02.906Z","updated_at":"2026-01-13T23:36:03.535Z","avatar_url":"https://github.com/thekitchencoder.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# package-scan\n\n[![Tests](https://github.com/thekitchencoder/package-scan/actions/workflows/RunTests.yml/badge.svg)](https://github.com/thekitchencoder/package-scan/actions/workflows/RunTests.yml)\n[![Documentation Status](https://github.com/thekitchencoder/package-scan/actions/workflows/BuildAndDeployDocs.yml/badge.svg)](https://github.com/thekitchencoder/package-scan/actions/workflows/BuildAndDeployDocs.yml)\n[![Docker Build](https://github.com/thekitchencoder/package-scan/actions/workflows/DockerImageReleaseWorkflow.yml/badge.svg)](https://github.com/thekitchencoder/package-scan/actions/workflows/DockerImageReleaseWorkflow.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)\n[![Docker Pulls](https://img.shields.io/docker/pulls/kitchencoder/package-scan)](https://hub.docker.com/r/kitchencoder/package-scan)\n\n**Rapid-response supply chain attack scanner** for detecting compromised packages during active security incidents.\n\n📚 **[Full Documentation](https://thekitchencoder.github.io/package-scan/)** | 🐙 **[GitHub](https://github.com/thekitchencoder/package-scan)**\n\nWhen a new supply chain attack emerges (like the sha1-Hulud worm or event-stream incident), security teams need to **quickly scan their infrastructure** against lists of known compromised packages. `package-scan` fills this critical gap—it's not a replacement for comprehensive vulnerability scanners like Snyk or npm audit, but a **focused tool for rapid incident response**.\n\n## Why package-scan?\n\n**✅ Use package-scan when:**\n- A new supply chain attack is discovered\n- You have a list of compromised packages to check against\n- You need results in minutes, not hours\n- You're scanning multiple ecosystems (npm, Maven, Python)\n- You need to share threat intelligence via simple CSV files\n\n**❌ Use other tools for:**\n- Ongoing vulnerability monitoring → Snyk, Dependabot\n- CVE database scanning → npm audit, pip-audit\n- SBOM generation → Syft, CycloneDX\n- Static code analysis → Semgrep, CodeQL\n\n## Key Features\n\n- **Multi-ecosystem**: Scans npm, Maven/Gradle, Python (pip/Poetry/Pipenv/conda)\n- **Rapid deployment**: Docker container or pip install\n- **Simple threat lists**: CSV-based, easy to create and share\n- **Version intelligence**: Handles semver ranges, Maven ranges, PEP 440 specifiers\n- **CI/CD ready**: JSON output, exit codes, Docker support\n\n## Quick Start\n\n### Using Docker (Recommended for rapid deployment)\n\n```bash\n# Pull the latest image\ndocker pull kitchencoder/package-scan:latest\n\n# Scan your current directory (all ecosystems, all threats)\ndocker run --rm -v \"$(pwd):/workspace\" kitchencoder/package-scan:latest\n\n# Scan for specific threat (e.g., sha1-Hulud worm)\ndocker run --rm -v \"$(pwd):/workspace\" kitchencoder/package-scan:latest --threat sha1-Hulud\n\n# Scan specific ecosystem only\ndocker run --rm -v \"$(pwd):/workspace\" kitchencoder/package-scan:latest --ecosystem npm\n```\n\n### Using pip\n\n```bash\n# Install\npip install -e .\n\n# Scan current directory\npackage-scan\n\n# Scan for specific threat\npackage-scan --threat sha1-Hulud\n\n# Scan specific ecosystem\npackage-scan --ecosystem maven\n\n# Use custom threat CSV\npackage-scan --csv /path/to/threat-list.csv\n```\n\n## Installation\n\n### Docker (Recommended)\n\nPre-built images are available on Docker Hub:\n\n```bash\ndocker pull kitchencoder/package-scan:latest\n```\n\nOr build locally:\n\n```bash\ndocker build -t package-scan .\n```\n\n### Python Package\n\n1. Create virtual environment:\n   ```bash\n   python3 -m venv venv\n   source venv/bin/activate  # Windows: venv\\Scripts\\activate\n   ```\n\n2. Install with all ecosystem support:\n   ```bash\n   pip install -e \".[all]\"\n   ```\n\n   Or install for specific ecosystems:\n   ```bash\n   pip install -e \".[pnpm]\"    # pnpm/conda support\n   pip install -e \".[java]\"     # Maven/Gradle support\n   pip install -e \".[python]\"   # Python ecosystem support\n   ```\n\n3. Verify installation:\n   ```bash\n   package-scan --help\n   package-scan --list-ecosystems\n   ```\n\n## Usage\n\n### Basic Scanning\n\n```bash\n# Scan current directory (all ecosystems, all threats)\npackage-scan\n\n# Scan specific directory\npackage-scan --dir /path/to/project\n\n# Scan for specific threat\npackage-scan --threat sha1-Hulud\n\n# Scan specific ecosystem\npackage-scan --ecosystem npm\npackage-scan --ecosystem maven,pip  # Multiple ecosystems\n```\n\n### Threat Management\n\n```bash\n# List available ecosystems\npackage-scan --list-ecosystems\n\n# View threat database information\nthreat-db info                                  # Summary + packages for all threats\nthreat-db info --threat sha1-Hulud              # Summary + packages for specific threat\nthreat-db info --summary                        # Summary only (metadata + statistics)\nthreat-db info --packages                       # Packages only (formatted display)\n\n# Export threat database as CSV\nthreat-db info --csv \u003e threats.csv              # Both metadata (as # comments) + CSV data\nthreat-db info --packages --csv \u003e data.csv      # CSV data only\nthreat-db info --summary --csv \u003e metadata.txt   # Metadata only (as # comments)\nthreat-db info --threat sha1-Hulud --packages --csv \u003e hulud.csv\n\n# Use custom threat CSV\npackage-scan --csv /path/to/custom-threats.csv\n\n# Validate threat CSV before use\nthreat-db validate --file /path/to/custom-threats.csv\n\n# Validate with strict ecosystem checking\nthreat-db validate --file threats.csv --strict\n\n# Validate with verbose output (shows all warnings)\nthreat-db validate --file threats.csv --verbose\n```\n\n### Output Options\n\n```bash\n# Custom output file\npackage-scan --output scan-results.json\n\n# No JSON file (console only)\npackage-scan --no-save\n```\n\n### Docker Examples\n\n```bash\n# Scan with custom threat CSV\ndocker run --rm \\\n  -v \"$(pwd):/workspace\" \\\n  -v \"/path/to/custom.csv:/app/custom.csv\" \\\n  kitchencoder/package-scan:latest --csv /app/custom.csv\n  \n# Host file paths in the report\ndocker run --rm \\\n  -v \"$(pwd):/workspace\" \\\n  -e  SCAN_PATH_PREFIX=\"$(pwd)\" \\\n  kitchencoder/package-scan:latest --csv /app/custom.csv\n\n# CI/CD: Exit with error if threats found\ndocker run --rm -v \"$(pwd):/workspace\" kitchencoder/package-scan:latest --no-save || exit 1\n\n# Scan monorepo subdirectory\ndocker run --rm -v \"$(pwd):/workspace\" kitchencoder/package-scan:latest --dir /workspace/services/api\n```\n\n## CLI Options\n\n**package-scan** (main scanner):\n- `--dir PATH`: Directory to scan (default: current directory)\n- `--threat NAME`: Scan for specific threat (can be repeated)\n- `--csv FILE`: Use custom threat CSV file\n- `--ecosystem LIST`: Comma-separated list of ecosystems to scan\n- `--output FILE`: JSON report filename (default: `package_scan_report.json`)\n- `--no-save`: Don't write JSON report\n- `--list-ecosystems`: List supported ecosystems and exit\n\n**threat-db info** (threat database queries):\n- `--file PATH`: Query specific threat CSV file\n- `--threat NAME`: Filter for specific threat(s)\n- `--summary`: Show only metadata and statistics\n- `--packages`: Show only affected packages\n- `--csv`: Output in CSV format (metadata as # comments)\n- **Default (no flags)**: Shows both summary and packages\n\n## Threat CSV Format\n\nThreat databases use a simple CSV format with three columns and optional metadata:\n\n```csv\n# Description: Unauthenticated remote code execution vulnerability in React\n# Source: https://react.dev/blog/2025/12/03/critical-security-vulnerability\n# Last updated: 2025-12-06 00:51:00 UTC\necosystem,name,version\nnpm,react-server-dom-webpack,19.0\nnpm,react-server-dom-webpack,19.1.0\nnpm,react-server-dom-parcel,19.0\n```\n\n### CSV Structure\n\n**Required columns:**\n- `ecosystem`: Package ecosystem (npm, maven, pip, gem)\n- `name`: Package identifier\n- `version`: Specific version number\n\n**Optional metadata** (comment lines starting with `#`):\n- `Description`: Brief description of the threat\n- `Source`: URL or reference to threat intelligence\n- `Last updated`: ISO 8601 timestamp (YYYY-MM-DD HH:MM:SS UTC)\n- `Severity`: critical|high|medium|low (optional)\n- `CVE`: CVE identifier (optional)\n- Any custom fields you want to track\n\n**Package naming conventions:**\n- **npm**: Package name as-is (supports `@scope/package`)\n- **maven**: `groupId:artifactId` format\n- **pip**: Lowercase package name (PyPI convention)\n\n### Viewing Threat Metadata\n\nDisplay metadata from a threat file:\n\n```bash\nthreat-db info --file threats/CVE-2025-55182.csv\n```\n\nExample output:\n```\n📋 THREAT METADATA\nFile: threats/CVE-2025-55182.csv\n\nDescription: Unauthenticated remote code execution vulnerability\nSource: https://react.dev/blog/2025/12/03/...\nLast updated: 2025-12-06 00:51:00 UTC\n```\n\n### Validating Threat Files\n\nBefore using a custom threat CSV file, you can validate it to ensure proper formatting:\n\n```bash\nthreat-db validate --file my-threats.csv\n```\n\nThe validator checks for:\n- ✓ Correct headers (`ecosystem,name,version`)\n- ✓ Non-empty required fields\n- ✓ Valid ecosystem names (npm, maven, pip, gem)\n- ✓ Proper package name format (e.g., Maven's `groupId:artifactId`)\n- ✓ Valid version strings\n- ✓ Duplicate entries\n- ✓ Recommended metadata fields (Description, Source, Last updated)\n\n**Validation modes:**\n- **Normal mode** (default): Warns about unknown ecosystems but passes validation\n- **Strict mode** (`--strict`): Fails validation for unknown ecosystems\n- **Verbose mode** (`--verbose`): Shows all warnings and detailed statistics\n\nExample validation output:\n```\n🔍 THREAT DATABASE VALIDATION\nFile: my-threats.csv\nFormat: modern\n\nStatistics:\n  Total rows: 150\n  Valid rows: 148\n  Invalid rows: 2\n  Unique entries: 148\n  Unique packages: 95\n  Ecosystems: maven, npm, pip\n\n⚠️  WARNINGS (3):\n  • Line 45 [name]: Maven package should be in 'groupId:artifactId' format: 'log4j-core'\n  • Line 89: Duplicate entry: ecosystem=npm, name=left-pad, version=1.3.0\n\n❌ ERRORS (2):\n  • Line 23 [version]: Version contains whitespace characters: '1.0 .0'\n  • Line 67 [name]: Empty package name\n\n✗ VALIDATION FAILED\n```\n\n## What Gets Scanned\n\nThe scanner detects and analyzes multiple ecosystems:\n\n### npm Ecosystem\n- **Manifests**: package.json (dependencies, devDependencies, etc.)\n- **Lockfiles**: package-lock.json (v1/v2/v3), yarn.lock, pnpm-lock.yaml\n- **Installed**: node_modules/ directories\n- **Version matching**: npm semver (^1.0.0, ~1.2.0, \u003e=2.0.0, etc.)\n\n### Maven/Gradle Ecosystem\n- **Manifests**: pom.xml, build.gradle, build.gradle.kts\n- **Lockfiles**: gradle.lockfile\n- **Version matching**: Maven ranges ([1.0,2.0)), Gradle dynamic (1.2.+)\n\n### Python Ecosystem\n- **Manifests**: requirements.txt, pyproject.toml, Pipfile, environment.yml\n- **Lockfiles**: poetry.lock, Pipfile.lock\n- **Version matching**: PEP 440 specifiers (==, \u003e=, ~=, etc.)\n\nThe scanner automatically detects which ecosystems are present in your project and scans accordingly.\n\n## Output\n\n### Console Output\n\nFindings are grouped by ecosystem and type:\n\n```\n═══════════════════════════════════════════════════════════\n📦 npm Findings\n═══════════════════════════════════════════════════════════\n\nMANIFEST FILES (package.json):\n  /project/package.json\n    left-pad@1.3.0 (declared: ^1.3.0)\n\nLOCK FILES:\n  /project/package-lock.json\n    some-package@2.0.1 (exact match)\n\n═══════════════════════════════════════════════════════════\n☕ maven Findings\n═══════════════════════════════════════════════════════════\n\nMANIFEST FILES (pom.xml):\n  /project/pom.xml\n    org.springframework:spring-core@5.3.0 (declared: [5.0,6.0))\n```\n\n### JSON Output\n\nDefault filename: `package_scan_report.json`\n\n```json\n{\n  \"total_findings\": 10,\n  \"threats\": [\"sha1-Hulud\"],\n  \"ecosystems\": [\"npm\", \"maven\", \"pip\"],\n  \"summary\": {\n    \"npm\": {\n      \"total\": 5,\n      \"manifest\": 2,\n      \"lockfile\": 3,\n      \"unique_packages\": 4\n    }\n  },\n  \"findings\": [\n    {\n      \"ecosystem\": \"npm\",\n      \"finding_type\": \"manifest\",\n      \"file_path\": \"/project/package.json\",\n      \"package_name\": \"left-pad\",\n      \"version\": \"1.3.0\",\n      \"match_type\": \"range\",\n      \"declared_spec\": \"^1.3.0\"\n    }\n  ]\n}\n```\n\n## Use Cases\n\n### Incident Response\n\nWhen a new supply chain attack is announced:\n\n1. **Gather threat intelligence**: Collect list of compromised packages from security advisories\n2. **Create threat CSV**: Format as `ecosystem,name,version`\n3. **Deploy scanner**: Use Docker for rapid deployment across infrastructure\n4. **Scan all repos**: Identify which projects are affected\n5. **Share findings**: JSON reports for security team analysis\n\n### CI/CD Integration\n\nAdd scanning to your CI pipeline:\n\n```yaml\n# GitHub Actions example\n- name: Scan for supply chain threats\n  run: |\n    docker run --rm -v \"$PWD:/workspace\" \\\n      kitchencoder/package-scan:latest \\\n      --threat sha1-Hulud \\\n      --no-save || exit 1\n```\n\n### Security Team Workflows\n\n- **Threat database sharing**: Distribute CSV files to development teams\n- **Monorepo scanning**: Scan large codebases across multiple ecosystems\n- **Audit reports**: Generate JSON reports for compliance\n- **Custom integrations**: Transform JSON output for SIEM/ticketing systems\n\n## Creating Threat Databases\n\nWhen a new attack is discovered:\n\n1. **Gather compromised packages** from security vendor advisories\n2. **Create CSV file** with format:\n   ```csv\n   ecosystem,name,version\n   npm,malicious-package,1.0.0\n   maven,com.evil:library,2.0.0\n   ```\n3. **Test scanning**:\n   ```bash\n   package-scan --csv my-threat.csv --list-affected-packages\n   ```\n4. **Share with team** via git, shared drive, or internal repository\n\nSee [ROADMAP.md](ROADMAP.md) for future plans around centralized threat databases.\n\n## Architecture\n\npackage-scan uses a modular architecture:\n\n```\nsrc/package_scan/\n├── cli.py                  # Command-line interface\n├── core/                   # Shared components\n│   ├── models.py           # Data models\n│   ├── threat_database.py  # CSV loading\n│   └── report_engine.py    # Report generation\n└── adapters/               # Ecosystem scanners\n    ├── npm_adapter.py      # npm/yarn/pnpm\n    ├── java_adapter.py     # Maven/Gradle\n    └── python_adapter.py   # pip/Poetry/Pipenv\n```\n\n**Adding new ecosystems** is straightforward—see [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n## Development\n\n### Running from Source\n\n```bash\n# Clone repository\ngit clone https://github.com/thekitchencoder/package-scan.git\ncd package-scan\n\n# Create virtual environment\npython3 -m venv venv\nsource venv/bin/activate\n\n# Install with dev dependencies\npip install -e \".[dev]\"\n\n# Run scanner\npython -m package_scan.cli --help\n\n# Run tests\npytest\n\n# Build documentation\ncd docs \u0026\u0026 make html\n```\n\n### Project Structure\n\n- **pyproject.toml**: Package configuration\n- **src/package_scan/**: Source code\n- **tests/**: Unit tests\n- **docs/**: Sphinx documentation\n- **threats/**: Built-in threat databases\n- **examples/**: Test fixtures for all ecosystems\n\n## Troubleshooting\n\n**Command not found:**\n- Ensure virtual environment is activated\n- Try: `python -m package_scan.cli --help`\n\n**Missing optional dependencies:**\n- For pnpm: `pip install pyyaml`\n- For Maven: `pip install lxml`\n- For Python ecosystem: `pip install toml packaging`\n- Or install all: `pip install -e \".[all]\"`\n\n**No findings when expected:**\n- Check threat CSV format\n- Verify package names match ecosystem conventions\n- Use `--list-affected-packages` to inspect database\n\n## Contributing\n\nWe welcome contributions! Priorities:\n\n- **New ecosystem adapters** (Ruby, Rust, Go, .NET)\n- **Threat databases** from real-world attacks\n- **CI/CD examples** for additional platforms\n- **Output format scripts** (SARIF, HTML, etc.)\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines and [ROADMAP.md](ROADMAP.md) for planned features.\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Acknowledgments\n\n- Built in response to the sha1-Hulud supply chain attack\n- Inspired by the need for rapid incident response tools\n- Thanks to the security community for threat intelligence sharing\n\n## Links\n\n- **Documentation**: [https://thekitchencoder.github.io/package-scan/](https://thekitchencoder.github.io/package-scan/)\n- **GitHub Repository**: [https://github.com/thekitchencoder/package-scan](https://github.com/thekitchencoder/package-scan)\n- **Issues**: [GitHub Issues](https://github.com/thekitchencoder/package-scan/issues)\n- **Docker Hub**: [kitchencoder/package-scan](https://hub.docker.com/r/kitchencoder/package-scan)\n- **Roadmap**: [ROADMAP.md](ROADMAP.md)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthekitchencoder%2Fpackage-scan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthekitchencoder%2Fpackage-scan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthekitchencoder%2Fpackage-scan/lists"}