SkillAgentSearch skills...

Packj

Packj stops :zap: Solarwinds-, ESLint-, and PyTorch-like attacks by flagging malicious/vulnerable open-source dependencies ("weak links") in your software supply-chain

Install / Use

/learn @ossillate-inc/Packj

README

<img src="https://packj.dev/static/img/icons/package.svg" width="45"/> <span style="font-size: 42px"> Packj flags malicious/risky open-source packages</span>

Packj (pronounced package) is a tool to help to mitigate software supply chain attacks. It can detect malicious, vulnerable, abandoned, typo-squatting, and other "risky" packages from popular open-source package registries, such as NPM, RubyGems, and PyPI. It can be easily customized to minimize noise. Packj started as a PhD research project and is currently being developed under various govt grants.

GitHub Stars Prs Welcome Github Commit Activity Discord License: AGPL v3 Docker

Note Self-hosted Packj webserver and several integrations coming later this month :punch: Watch this repo to stay up to date.

demo video

Contents

  • Get started - available as Docker image, GitHub Action, and packages
  • Functionality - deep static/dynamic code analysis and sandboxing
  • Supported ecosystems - NPM, PyPI, Rubygems, PHP, Rust
  • Our story - started as a PhD research project and is backed by govt grants
  • Why Packj - existing CVE scanners ASSUME code is BENIGN and not analyze its behavior
  • Customization - turn off alerts as per your threat model to reduce noise
  • Malware found - reported over 70 malicious PyPI and RubyGems packages
  • Talks and videos - presentations from PyCon, OpenSourceSummit, BlackHAT
  • Project roadmap - view or suggest new features; join our discord channel
  • Team and collaboration - lead by Cybersecurity researchers from academia/industry
  • FAQ - supported package managers, commonly asked questions on techniques, and more

Get started

We support multiple deployment models:

1. GitHub runner

Use Packj to audit dependencies in pull requests.

- name: Packj Security Audit
  uses: ossillate-inc/packj-github-action@v0.0.10-beta
  with:
    # TODO: replace with your dependency files in the repo
    DEPENDENCY_FILES: pypi:requirements.txt,npm:package.json,rubygems:Gemfile
    REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View on GitHub marketplace. Example PR run.

2. Docker image (recommended)

The quickest way to try/test Packj is using Docker. Podman is also supported for containerized (isolated) runs.

docker run -v /tmp:/tmp/packj -it ossillate/packj:latest --help

3. Source repo

Clone this repo,

git clone https://github.com/ossillate-inc/packj.git && cd packj

Install dependencies

bundle install && pip3 install -r requirements.txt

Start with help:

python3 main.py --help 

Supported ecosystems

Packj can vet pubished packages from NPM, PyPI, Rust, PHP, and Rubygems package registries. Rust and PHP support is WIP. We're actively adding support for registries. It also supports vetting local (unpublished) NPM and PyPI packages.

| Registry | Ecosystem | Supported | | --------- | ---------- | ------------------ | | NPM | JavaScript | :white_check_mark: | | PyPI | Python | :white_check_mark: | | Cargo | Rust | :white_check_mark: | | Rubygems | Ruby | :white_check_mark: | | Packagist | PHP | :white_check_mark: | | Docker | Docker | :x: | | Nuget | .NET | :white_check_mark: | | Maven | Java | :white_check_mark: | | Cocoapods | Swift | :x: |

Functionality

Packj offers the following tools:

  • Audit - to vet a package for "risky" attributes.
  • Sandbox - for safe installation of a package.

Auditing a package

Packj audits open-source software packages for "risky" attributes that make them vulnerable to supply chain attacks. For instance, packages with expired email domains (lacking 2FA), large release time gap, sensitive APIs or access permissions, etc. are flagged as risky.

Auditing the following is supported:

  • multiple packages: python3 main.py audit -p pypi:requests rubygems:overcommit
  • dependency files: python3 main.py audit -f npm:package.json pypi:requirements.txt

By default, audit only performs static code analysis to detect risky code. You can paas -t or --trace flag to perform dynamic code analysis as well, which will install all requested packages under strace and monitor install-time behavior of packages. Please see the example output below.

<details> <summary><h4>Show example run/output</h4></summary>
$ docker run -v /tmp:/tmp/packj -it ossillate/packj:latest audit --trace -p npm:browserify

[+] Fetching 'browserify' from npm..........PASS [ver 17.0.0]
[+]    Checking package description.........PASS [browser-side require() the node way]
[+]    Checking release history.............PASS [484 version(s)]
[+] Checking version........................RISK [702 days old]
[+]    Checking release time gap............PASS [68 days since last release]
[+] Checking author.........................PASS [mail@substack.net]
[+]    Checking email/domain validity.......RISK [expired author email domain]
[+] Checking readme.........................PASS [26838 bytes]
[+] Checking homepage.......................PASS [https://github.com/browserify/browserify#readme]
[+] Checking downloads......................PASS [2M weekly]
[+] Checking repo URL.......................PASS [https://github.com/browserify/browserify]
[+]    Checking repo data...................PASS [stars: 14189, forks: 1244]
[+]    Checking if repo is a forked copy....PASS [original, not forked]
[+]    Checking repo description............PASS [browser-side require() the node.js way]
[+]    Checking repo activity...............PASS [commits: 2290, contributors: 207, tags: 413]
[+] Checking for CVEs.......................PASS [none found]
[+] Checking dependencies...................RISK [48 found]
[+] Downloading package from npm............PASS [163.83 KB]
[+] Analyzing code..........................RISK [needs 3 perm(s): decode,codegen,file]
[+] Checking files/funcs....................PASS [429 files (383 .js), 744 funcs, LoC: 9.7K]
[+] Installing package and tracing code.....PASS [found 5 process,1130 files,22 network syscalls]
=============================================
[+] 5 risk(s) found, package is undesirable!
=> Complete report: /tmp/packj_54rbjhgm/report_npm-browserify-17.0.0_hlr1rhcz.json
{
    "undesirable": [
        "old package: 702 days old",
        "invalid or no author email: expired author email domain",
        "generates new code at runtime",
        "reads files and dirs",
        "forks or exits OS processes",
    ]
}
</details>

WARNING: since packages could execute malicious code during installation, it is recommended to ONLY use -t or --trace when running inside a Docker container or a Virtual Machine.

Audit can also be performed in Docker/Podman containers. Please find details on risky attributes and how to use at Audit README.

Sandboxed package installation

Packj offers a lightweight sandboxing for safe installation of a package. Specifically, it prevents malicious packages from exfiltrating sensitive data, accessing sensitive files (e.g., SSH keys), and persisting malware.

It sandboxes install-time scripts, including any native compliation. It uses strace (i.e., NO VM/Container required).

Please find details on the sandboxing mechanism and how to use at Sandbox README.

<details> <summary><h4>Show example run/output</h4></summary>
$ python3 main.py sandbox gem install overcommit

Fetching: overcommit-0.59.1.gem (100%)
Install hooks by running `overcommit --install` in your Git repository
Successfully installed overcommit-0.59.1
Parsing documentation for overcommit-0.59.1
Installing ri documentation for overcommit-0.59.1

#############################
# Review summarized activity
#############################

[+] Network connections
    [+] DNS (1 IPv4 addresses) at port 53 [rule: ALLOW]
    [+] rubygems.org (4 IPv6 addresses) at port 443 [rule: IPv6 rules not supported]
    [+] rubygems.org (4 IPv4 addresses) at port 443 [rule: ALLOW]
[+] Filesystem changes
/
└── home
    └── ubuntu
        └── .ruby
            ├── gems
            │   ├── iniparse-1.5.0 [new: DIR, 15 files, 46.6K bytes]
            │   ├── rexml-3.2.5 [new: DIR, 77 files, 455.6K bytes]
            │   ├── overcommit-0.59.1 [new: DIR, 252 files, 432.7K bytes]
            │   └── childprocess-4.1.0 [new: DIR, 57 files, 141.2K bytes]
            ├── cache
            │   ├── 
View on GitHub
GitHub Stars686
CategoryOperations
Updated3d ago
Forks37

Languages

Python

Security Score

100/100

Audited on Mar 29, 2026

No findings