Security

Security is becoming an increasing concern with open source software, especially in this ecosystem.

Our goal is to be aware of the risks and attack vectors being used on npm package and protect against these as much as practically possible.

Dependencies

On npm, pacwich reports having 0 dependencies. This is technically true but isn't the whole picture.

In reality, pacwich uses commander for CLI parsing, jiti and sucrasefor loading TypeScript/JavaScript config files, yaml for parsing pnpm config files, shell-quote for shell string parsing and preventing shell injection, and semver for version string parsing.

The code of these dependencies is bundled into pacwich, so they are not installed as separate dependencies when pacwich is installed.

Why bundle?

One practical reason to bundle dependencies is so that they're isolated in pacwich's build so that they don't conflict with other dependencies in a project.

Security-wise, we've recently seen several attacks on npm packages that use lifecycle scripts such as postinstall to run arbitrary code on install.

Bundled dependencies cannot introduce surprise lifecycle scripts to pacwich installers and provide code locked to pacwich's release. In general, this approach prevents surprise attacks from a dependency's patch version bump.

Tradeoff Mitigation

The tradeoff here is that an insecure dependency bundled into pacwich does not trigger something like npm audit in consumers that installed pacwich, and consumers can't just receive a patch/minor bump for a dependency directly, meaning pacwich itself would need its own security issue declared and patched if one arises with a bundled dependency that is relevant to users.

Care is put into choosing dependencies with positive reputation and maturity.

On top of this, these bundled dependencies are locked to a specific patch version. Vetted upgrades are only performed on pacwich's side if a fix or feature is needed from one of these, so stability is prioritized instead of allowing frequent bumps to latest.

GitHub's Dependabot is also used on the source repository to help catch issues with the current dependencies, so issues with current versions of bundled dependencies are more likely to be caught quickly.

GitHub Actions

Publishing

pacwich is published with OIDC trusted publishing to npm for provenance attestation via Actions.

Long-lived legacy npm tokens are never used for publishing, something seen in recent attacks.

No Insecure Context for Forks

We avoid using any triggers where a fork's code may run in the main repo's security context.

For example, the pull_request_target is often exploited when a fork's code is checked out to perform PR checks, in which case the fork's code may substitute a malicious script for something like a lint command defined in the repo.

While it's possible to use pull_request_target securely, we simply avoid workflows where forks are ever checked out in the main repo's security context.

SHA-pinned Actions

We use external actions for purposes like installing Bun, Node, etc.

We pin the version of each action used to a specific SHA to prevent supply chain attacks from this surface. This is enforced in the repository's settings so that this pattern cannot be neglected.

Dependabot is used again here to validate the security of currently used action versions.