Skip to main content

Supply Chain Security

How the ReplayCI CLI protects your environment — dependency hygiene, network behavior, and build integrity.


Dependency profile

The @replayci/cli npm package has a minimal dependency footprint:

Direct dependencies

PackagePurpose
yamlParse .replayci.yml config files
tsxTypeScript execution for the CLI bin shim
openaiOpenAI provider adapter
@anthropic-ai/sdkAnthropic provider adapter
@prisma/clientDatabase client (optional, for --persist)
prismaSchema management (optional, for --persist)
pinoStructured logging
pino-prettyHuman-readable log output (dev only)
zodSchema validation

What's NOT included

  • No postinstall scripts — npm install never executes arbitrary code
  • No native binaries or node-gyp compilation
  • No telemetry or analytics collection
  • No background processes or daemons

Network behavior

The CLI makes zero network calls by default. Network access is opt-in:

TriggerDestinationWhen
--provider openaiapi.openai.comRunning live contracts against OpenAI
--provider anthropicapi.anthropic.comRunning live contracts against Anthropic
REPLAYCI_API_KEY setapp.replayci.comPushing results to hosted dashboard
--provider recordedNoneReplays from local fixtures — fully offline

Push is opt-in

Run results are only pushed to the ReplayCI API when REPLAYCI_API_KEY is set as an environment variable. Without it, all data stays local. The push destination can be overridden with REPLAYCI_API_URL for self-hosted deployments.

Push timeout

API push uses a 30-second AbortController timeout. If the push fails for any reason (network error, timeout, server error), the CLI warns to stderr but does not exit with an error code. Push failure never blocks your CI pipeline.


CI isolation (Lane A)

ReplayCI's two-lane CI system enforces strict isolation for merge-blocking tests:

Lane A (Hard Gate)

  • Uses --provider recorded only — no live API calls
  • Egress blocking via iptables (when running in container mode)
  • Deterministic corpus pinned via corpus_manifest_hash
  • No network access whatsoever

Lane B (Evidence Lane)

  • Allows live API calls for evidence collection
  • Results are advisory (annotate-by-default)
  • Shadow comparisons and drift detection run here
  • Never blocks merges

This separation ensures that your merge gate can never be affected by third-party API availability or network issues.


Package integrity

Lockfile

The package-lock.json is committed and pinned. npm ci (used in CI and production deploys) installs exact versions from the lockfile — no floating resolutions.

Published package contents

The npm package includes only what's specified in package.json "files":

bin/         — CLI entry point (replayci.mjs)
src/ — TypeScript source
packs/starter/ — Starter contract pack
tsconfig.json
tsconfig.container.json
artifacts/schema/

No test files, evidence artifacts, documentation, or development tooling is published.

No lifecycle scripts

The package defines no postinstall, preinstall, or install scripts. Installing @replayci/cli runs zero code beyond npm's own dependency resolution.


Container security

When running replay bundles in container mode, additional protections apply:

ControlImplementation
Bundle size limit50 MiB maximum (GR-19)
Path traversal protectionAll paths validated before extraction
Schema validationBundle manifest validated against expected schema
Non-root executionDocker container runs as non-root user
Egress blockingiptables rules block all outbound network access
Resource limitsContainer CPU and memory limits enforced

Replay bundles are treated as hostile input (GR-19: Replay Bundle Hardening). Every field is validated, every path is sanitized, and every size is checked before processing.


Build and release

CI pipeline

Every commit runs through GitHub Actions:

  1. Type check — TypeScript strict mode
  2. Full test suite — 2400+ automated tests
  3. SecurityGate verification — regression tests for secret scanning
  4. Dashboard build — production build verification

Docker image

The production Docker image:

  • Based on an official Node.js image
  • Runs as non-root user
  • Includes only production dependencies
  • No development tools or test fixtures

What you can verify

  1. Inspect the package before installing:

    npm pack @replayci/cli --dry-run
  2. Check for lifecycle scripts:

    npm pkg get scripts.postinstall scripts.preinstall scripts.install
  3. Audit dependencies:

    npm audit --production
  4. Run fully offline with recorded fixtures:

    npx replayci --provider recorded

    This makes zero network calls — verify with your network monitor.