Safeguard
Open Source

nyc on npm: A Security Review and Safe Usage Guide

nyc is the Istanbul command-line coverage tool for Node.js. Here is its security profile and how to run it without leaking source or slowing your pipeline.

Yukti Singhal
Platform Engineer
5 min read

The nyc npm package is a low-risk, test-time-only code coverage tool, and its main security consideration is making sure the coverage reports and instrumented source it produces do not leak out of CI. nyc is the command-line client for Istanbul, maintained under the istanbuljs organization, and it works with most JavaScript test runners including Mocha, tap, and AVA. This review covers what it does, where the sharp edges are, and how to keep it scoped correctly.

What nyc does

nyc instruments your JavaScript before tests run, records which lines, branches, and functions execute, and then prints or writes a coverage report. A typical invocation wraps your test command:

npx nyc --reporter=text --reporter=lcov mocha

You install it as a dev dependency, because coverage instrumentation has no place in a production runtime:

npm install --save-dev nyc

If you already use jest or tap, you usually do not need nyc at all, since those runners bundle Istanbul themselves. Adding npm nyc on top of a runner that already provides coverage just gives you a second, redundant instrumentation path to maintain. Check what your runner already does before installing.

Where the actual risk lives

nyc does not process untrusted input or open network connections, so it has no classic exploit surface of its own. The security work is about the artifacts it generates and the environment it runs in.

Coverage reports contain your source. An lcov or HTML report maps directly back to file paths and, in the HTML case, embeds annotated source code. If your CI publishes the coverage/ directory to a public artifact store or a world-readable pages site, you may be exposing internal code layout, comments, and logic you meant to keep private. Treat the coverage output like source: keep it inside authenticated CI storage unless the repository is genuinely public.

The .nyc_output directory is intermediate state. It holds raw coverage data keyed by absolute file paths from the build machine. There is no secret in it by design, but it should be gitignored and cleaned between runs so stale data does not skew a report or leak build-host paths into a published artifact.

Instrumentation runs your code. Coverage works by executing your test suite, which executes your application code. That is expected, but it means a compromised test or a malicious dev dependency has the same reach during a coverage run as during any other test run. Keeping the dev dependency tree vetted matters here.

Keeping the toolchain vetted

Because nyc pulls in the Istanbul instrumentation libraries, it brings a modest transitive tree. The same discipline that applies to any dev dependency applies here:

  • Commit a lockfile so coverage tooling is reproducible and a compromised patch release cannot slip in unnoticed.
  • Read release notes before bumping the major version; instrumentation internals do change between majors.
  • Run SCA scanning in CI so a disclosed advisory in nyc or one of its Istanbul dependencies surfaces automatically. An SCA tool such as Safeguard can track the whole tree, including the transitive packages you never named directly.

A safe CI configuration

Coverage tooling is where a lot of pipelines quietly overshare. A safer setup looks like this:

  1. Install nyc under devDependencies only.
  2. Add coverage/ and .nyc_output/ to .gitignore.
  3. Store reports as private CI artifacts, or gate any public publishing behind an explicit decision for public repos.
  4. Do not enforce a coverage threshold so aggressive that developers disable tests to hit it; a high number with skipped security paths is worse than an honest lower one.
  5. Fail the build on the test result, not merely on the coverage percentage, so a passing coverage report never masks a failing assertion.

Coverage is a signal about which code your tests actually exercise. That signal is most useful when it points at untested error handling and input validation, which is exactly where security defects hide. Our academy has more on turning coverage gaps into a testing backlog rather than a vanity metric.

FAQ

Is the nyc npm package safe?

Yes. nyc is a test-time coverage tool with no runtime footprint and no untrusted-input surface of its own. Keep it in devDependencies, gitignore its output directories, and its risk is limited to ordinary supply-chain hygiene.

Do I need nyc if I use jest?

No. jest and tap already bundle the Istanbul libraries and produce coverage themselves. Adding npm nyc on top gives you a redundant instrumentation path. Only reach for nyc with runners like Mocha that do not include coverage.

Can nyc coverage reports leak sensitive information?

They can leak your source layout and, in HTML form, annotated source code. If CI publishes the coverage/ directory to a public location, that content is exposed. Keep reports in authenticated storage unless the repository is already public.

Is nyc still maintained?

Yes. nyc is maintained under the istanbuljs organization on GitHub and remains the standard CLI for Istanbul-based coverage. Check the latest published version and its release notes before upgrading across a major.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.