Safeguard
Application Security•

How do you secure JavaScript applications from the command line?

Lock installs with npm ci, run npm audit in CI, inspect new packages before adding them, and gate builds on results. All of it works from a terminal.

Safeguard Security Team
4 min read

Secure a JavaScript app from the terminal by committing a lockfile, installing with npm ci, running npm audit on every build, reviewing each new dependency before you add it, and failing the pipeline on findings you have agreed to block. Each step is a single command and scripts well.

Why start with the lockfile?

Your code is a small part of what runs. Most of it arrives through package.json and everything those packages pull in. The lockfile records the exact versions resolved, so everyone installs the same tree.

The npm documentation says npm ci is similar to npm install but meant for automated environments such as test platforms, continuous integration and deployment. It requires an existing package-lock.json or npm-shrinkwrap.json, and exits with an error if the lock does not match package.json, instead of updating it. That behavior is the point: the build never silently picks up a different version.

What does npm audit do?

Per the npm documentation, npm audit submits a description of the dependencies in your project to your registry and asks for a report of known vulnerabilities. If any are found, it calculates the impact and the remediation. With the fix argument it applies remediations to the package tree. The command exits with 0 when no vulnerabilities are found, which makes it usable as a gate. The docs also note that some issues cannot be fixed automatically and need manual review.

Two practical flags matter. You can set an audit level so that the command fails only at or above a severity you choose, and you can omit dev dependency types if you want to audit only what ships. Decide which, write it into the pipeline and document why.

How should you vet a new package?

Before npm install some-package, look at it. Who maintains it, when was the last release, how many dependencies does it bring, and does it do something you could write in ten lines? Fewer dependencies mean a smaller surface. Also check install scripts: packages can run code at install time, so be careful with the setting that disables scripts when you do not need them.

Safeguard's CLI, the npm package @safeguard-sh/cli (it needs Node 18 or later), can generate an SBOM, scan and gate from the terminal, with CI output in SARIF or JUnit format. Follow the install instructions at cli.safeguard.sh. Gold's free in-browser scan at gold.safeguard.sh/scan can check up to 100 dependencies without installing anything.

What about your own code?

Dependencies are one half. For your own code, use static analysis in the pipeline and a linter with security rules for the common JavaScript mistakes: building SQL or shell commands from user input, using eval, and unsafely inserting user text into pages. OWASP's Node.js security cheat sheet collects practical advice for server code, including validating input and handling errors without leaking details. Keep secrets out of the repo by loading them from the environment, and scan for committed secrets before pushing.

What does a simple pipeline look like?

A constructed example: a team adds three lines to their CI job. The first runs npm ci. The second runs npm audit with an audit level of high, failing the build for high and critical issues in production dependencies. The third runs their scanner and uploads the result. In the first week the build fails on a transitive dependency. They update the parent package and the gate passes. Two weeks later a developer proposes a small date library; the review shows it would add forty transitive packages, so they use the built-in date functions instead.

How to check or apply this

  1. Commit package-lock.json and install with npm ci in CI and in container builds.
  2. Run npm audit in CI with an agreed audit level, and fail the job on it.
  3. Review each new dependency for maintenance, size of its tree and install scripts.
  4. Add a static analysis step and a secret scan for your own code.
  5. Generate an SBOM at build time so you can answer "do we use this?" quickly.
  6. Re-run the checks on a schedule, since new advisories appear after you ship.

Quick check

Is npm audit enough?

No. It reports known vulnerabilities in dependencies. It does not review your own code, secrets or risky install behavior.

Why npm ci instead of npm install in CI?

Because it installs exactly what the lockfile says and fails if the lockfile and package.json disagree, so builds are repeatable.

Sources

Last reviewed: 18 October 2026.

Never miss an update

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

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.