JSPM

@epilot/lockfile-checker

1.1.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 176
  • Score
    100M100P100Q91978F
  • License MIT

CLI that fails if any package version in (or newly added to) a lockfile is younger than a configurable threshold on the npm registry. Defends against supply-chain attacks via a quarantine window.

Package Exports

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@epilot/lockfile-checker) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    @epilot/lockfile-checker

    A CLI that fails if any package version in (or newly added to) a lockfile is younger than a configurable threshold on the npm registry. Defends against npm supply-chain attacks (Shai-Hulud-style malicious releases of legitimate packages) by enforcing a quarantine window.

    Works with pnpm-lock.yaml, package-lock.json, and yarn.lock (both v1 and berry), in single-package and workspace repos. For pnpm workspaces with shared-workspace-lockfile=false, the tool also discovers per-member pnpm-lock.yaml files automatically.

    Install

    Run on demand via npx (recommended — pins to a single version per invocation):

    npx @epilot/lockfile-checker [options]

    Or add as a dev dependency:

    pnpm add -D @epilot/lockfile-checker

    Requires Node ≥ 20.

    Two modes

    Diff mode — gate a change

    Supply --base <ref> to check only the packages newly introduced relative to that ref. This is the natural fit for MR/PR gate pipelines.

    # Fail if anything added on this branch was published less than a week ago.
    npx @epilot/lockfile-checker --base origin/main

    Requires the working directory to be inside a git repository and the base ref to be resolvable. If your CI does a shallow clone, deepen it first (git fetch --deepen=50) or fetch the base ref explicitly.

    Scan mode — audit the whole tree

    Omit --base (or leave BASE_REF empty) to check every package in the lockfile(s). Use this for repo onboarding, one-off audits, and scheduled re-scans that catch packages compromised after they entered your tree.

    npx @epilot/lockfile-checker

    Scan mode does not require a git repository.

    Flags

    Every flag has an environment-variable equivalent. Precedence: CLI flag > env var > default.

    Flag Env var Default What it does
    --base <ref> BASE_REF (unset → scan mode) Git ref to diff against. Presence selects diff mode.
    --min-age <hours> MIN_PACKAGE_AGE_HOURS 168 Minimum allowed age of any package version, in hours.
    --allow <list> ALLOWED_PACKAGES (empty) Comma-separated package names to skip.
    --allow-scope <list> ALLOWED_SCOPES (empty) Comma-separated scopes to skip (include the leading @).
    --registry <url> NPM_REGISTRY https://registry.npmjs.org Registry to query for publish times. Must return standard npm metadata.
    --concurrency <n> REGISTRY_CONCURRENCY 8 Max in-flight registry requests.
    --fail-on-registry-error FAIL_ON_REGISTRY_ERROR=true false Treat HTTP/network errors as failures instead of warnings.
    --quiet QUIET=true false Suppress the progress line. Warnings and offenders still print.
    --help Print usage and exit 0.
    --version Print the package version and exit 0.

    Exit codes

    Code Meaning
    0 No offenders.
    1 At least one offender. Or a registry error if --fail-on-registry-error is set.
    2 Invalid configuration: unknown flag, diff mode in a non-git directory, unresolvable base ref, or no lockfile present at the working directory.

    Distinguishing 1 (legitimate "blocked" outcome) from 2 (misconfiguration) lets callers handle them differently — a typical CI gate fails the job on 1 and quarantines the runner / pings infra on 2.

    Output

    Standard format on a successful run:

    Found 3 newly added package@version pair(s).
    ✅ All packages are at least 168h old.

    On failure, offenders are printed on stderr, sorted ascending by age:

    Found 4 newly added package@version pair(s).
    
    ❌ 1 package(s) younger than 168h:
    
       suspicious-pkg@2.0.1  —  0.3h old  (2026-05-18T23:42:11.000Z)
    
    Allow via --allow <name>,<name> (or ALLOWED_PACKAGES=…), or wait until they age past 168h.

    Warnings (e.g. a package not found on the configured registry, or a malformed lockfile) print on stderr above the offender list but do not fail the run by themselves.

    What is not covered

    This tool checks publish-time only. It is one defensive layer; not a replacement for:

    • CVE scanning (Snyk, Dependabot, npm audit) — known vulnerabilities, not novel attacks.
    • Lockfile integrity (lockfile-lint) — that the resolved/integrity fields are honest.
    • Provenance / signature verification (npm provenance, sigstore).

    It also does not detect packages that were yanked, unpublished, or republished without a version bump.

    Limitations

    • The tool always queries the registry referenced by --registry (default: the public npm registry) for every package not filtered by --allow or --allow-scope. Internal packages must be added to one of those lists.
    • The working directory must contain a lockfile (or a pnpm-workspace.yaml whose members do). The tool does not recursively walk arbitrary nested directories looking for lockfiles — invoke it from the project root.

    License

    MIT