← Back to Blog

Socket.dev vs Nark: Supply Chain Security vs Runtime Error Checking for TypeScript

By Nark Team

Socket.dev and Nark solve two different problems in the npm dependency lifecycle. Socket.dev answers "is this package safe to install?" by detecting malicious code, typosquatting, and known vulnerabilities before a package enters your project. Nark answers "did I handle the errors this package throws?" by scanning your TypeScript code against 160+ Nark Profiles — covering axios, prisma, stripe, redis, and more — that encode what legitimate packages do at runtime. They do not overlap. A complete TypeScript CI pipeline runs both.

Quick Answer: Socket.dev catches malicious and vulnerable npm packages before you install them. Nark catches missing error handling for the safe packages you already depend on. Socket stops bad packages from getting in. Nark stops good packages from crashing your app because you forgot a try-catch. Run both: Socket in your lockfile workflow, Nark with npx nark --tsconfig ./tsconfig.json.


What Does Socket.dev Do?

Socket.dev is a supply chain security tool for npm (and other package registries). It analyzes packages before they enter your dependency tree, looking for signals that a package is malicious, compromised, or risky.

What Socket.dev catches:

  • Malicious packages with install scripts that exfiltrate environment variables
  • Typosquatting (e.g., axois instead of axios)
  • Known CVEs in package versions
  • Packages with suspicious network access, filesystem writes, or shell execution
  • Maintainer account takeovers (new publisher on a popular package)
  • Obfuscated code in published npm tarballs

What Socket.dev does not catch:

  • Whether your code handles AxiosError when axios.get() fails
  • Whether your Prisma query catches P2002 on a unique constraint violation
  • Whether your Stripe integration handles StripeCardError on declined cards
  • Whether your Redis client registers an .on('error') handler

Socket.dev's job ends once the package is in your node_modules. It verified the package is not malicious. It does not verify that your code uses the package correctly.


What Does Nark Do?

Nark is a Nark Profile scanner for TypeScript. It uses the TypeScript compiler to parse your code and checks it against a library of profiles that specify what npm packages throw at runtime, what error types they produce, and what handling your code needs.

What Nark catches:

  • axios.get() without try-catch (throws AxiosError on 4xx, 5xx, and network failures)
  • prisma.user.create() without catching PrismaClientKnownRequestError (throws P2002 on duplicate records)
  • stripe.charges.create() without catching StripeCardError (silent payment failures)
  • redis.get() without .on('error') handler registration (process crash on disconnect)
  • openai.chat.completions.create() without handling RateLimitError (silent AI feature failures)

What Nark does not catch:

  • Malicious packages in your dependency tree (Socket.dev's domain)
  • Known CVEs in package versions (Socket.dev's and Snyk's domain)
  • Typosquatting or supply chain attacks (Socket.dev's domain)

Nark assumes your packages are safe. It checks whether your code handles the runtime behavior of those safe packages correctly.


Side-by-Side Comparison

CapabilitySocket.devNark
Detects malicious npm packagesYesNo
Detects typosquattingYesNo
Detects known CVEsYesNo
Checks install script behaviorYesNo
Checks runtime error handlingNoYes
Knows what axios throwsNoYes
Knows what Prisma throwsNoYes
Knows what Stripe throwsNoYes
Profiles for 160+ npm packagesNoYes
Analyzes your source codeNoYes
Analyzes your lockfile/dependenciesYesNo
GitHub PR integrationYesYes
CI integrationYesYes
Free tierYesYes (open source)

The two tools check entirely different things. Socket.dev inspects the package itself. Nark inspects your code that calls the package.


Where Socket.dev Stops and Nark Starts

Consider this real-world scenario with axios:

Step 1: You install axios.

Socket.dev checks the axios package. It verifies there are no malicious install scripts, no known CVEs in the version you pinned, and no suspicious code in the published tarball. Socket gives you a green check. axios is safe to use.

Step 2: You write code that calls axios.

import axios from 'axios';

async function fetchUserProfile(userId: string) {
  const response = await axios.get(`https://api.example.com/users/${userId}`);
  return response.data;
}

Socket.dev has nothing to say about this code. The package is safe. Socket's job is done.

Nark flags this:

ERROR  axios     axios.get() called without try-catch
       src/api/users.ts:4  in fetchUserProfile()
       axios throws AxiosError on 4xx/5xx/network error
       Fix: wrap in try-catch, handle AxiosError

The package is safe. The code is not. axios.get() throws AxiosError on any non-2xx response, on network timeouts, and on DNS failures. Without a try-catch, this function crashes your API endpoint and returns a 500 to users.

Step 3: You fix the code.

import axios from 'axios';

async function fetchUserProfile(userId: string) {
  try {
    const response = await axios.get(`https://api.example.com/users/${userId}`);
    return response.data;
  } catch (error) {
    if (axios.isAxiosError(error)) {
      if (error.response?.status === 404) {
        return null; // user not found
      }
      throw new ApiError(error.response?.status ?? 500, error.message);
    }
    throw error;
  }
}

Nark passes. Socket.dev already passed in step 1. Both tools green. Your dependency is safe AND correctly handled.


Why You Need Both in CI

Supply chain security and runtime error handling are two distinct failure modes:

Failure mode 1: Bad package gets in. A compromised version of a popular package runs a postinstall script that sends your .env to an external server. Socket.dev catches this. Nark does not, because Nark never inspects the package itself.

Failure mode 2: Good package, bad usage. A trusted version of axios is called without a try-catch. Your API returns 500 when the upstream service is slow. Nark catches this. Socket.dev does not, because the package is legitimate.

Both of these are production incidents. Both are preventable with the right tool in CI.

# .github/workflows/code-safety.yml
name: Code Safety

on: [pull_request]

jobs:
  supply-chain:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Socket.dev — supply chain security
        uses: SocketDev/socket-security-action@v1

  runtime-errors:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - name: nark — runtime error handling
        run: npx nark --tsconfig tsconfig.json

Each job runs independently. Socket checks your lockfile diff for risky packages. Nark checks your source code for missing error handling. Together they cover two layers that no single tool addresses.


What About Snyk, npm audit, and Dependabot?

These tools occupy the same layer as Socket.dev: supply chain security.

ToolFocusOverlap with Socket.devOverlap with Nark
SnykCVE detection, license complianceHighNone
npm auditKnown vulnerabilities in installed packagesHighNone
DependabotAutomated dependency updates for CVE fixesHighNone
Socket.devMalicious package detection, behavior analysis-None
NarkRuntime error handling verificationNone-

All of these tools answer variations of "is this package safe?" None of them answer "did I handle the errors this package throws?" That question lives in a different layer entirely. Nark is the tool for that layer.


The Three Layers of npm Dependency Safety

A production-grade TypeScript project needs three layers of checks on its npm dependencies:

Layer 1: Is the package safe to install? Tools: Socket.dev, Snyk, npm audit, Dependabot. Checks: CVEs, malicious code, typosquatting, license compliance.

Layer 2: Is the code written securely? Tools: Semgrep, ESLint security plugins, CodeQL. Checks: SQL injection, XSS, hardcoded secrets, insecure patterns.

Layer 3: Does the code handle runtime errors correctly? Tools: Nark. Checks: Missing try-catch on axios, unhandled Prisma P2002, uncaught StripeCardError, missing Redis error handler.

Most teams have Layer 1 (Dependabot is on by default in GitHub). Many teams have Layer 2 (Semgrep or ESLint). Almost no teams have Layer 3. That is the gap Nark fills.


Frequently Asked Questions

Is Socket.dev an alternative to Nark?

No. They solve different problems. Socket.dev is a supply chain security tool. Nark is a runtime error handling checker. Choosing between them is like choosing between a lock on your front door and a smoke detector inside your house. You need both.

Does Socket.dev check how I use packages?

No. Socket.dev analyzes the package code itself (install scripts, published source, network behavior). It does not read your application source code or check whether you handle errors correctly.

Does Nark check for malicious packages?

No. Nark trusts that your packages are legitimate. It reads your application source code and checks it against Nark Profiles that describe what those packages throw at runtime.

Can I run Socket.dev and Nark together?

Yes. They run in separate CI jobs. Socket.dev checks your lockfile. Nark checks your TypeScript source. There is no conflict or overlap between them.

What if I already use Snyk?

Snyk and Socket.dev overlap on CVE detection. Nark does not overlap with either. If you run Snyk for supply chain security, you still need Nark for runtime error handling. They check completely different things.

Does Nark replace any security tools?

No. Nark is not a security tool. It is a completeness checker. It verifies that your code handles the runtime behavior of your dependencies. Security tools (Socket.dev, Snyk, Semgrep) remain necessary for their respective domains.


Try It Now

npx nark --tsconfig ./tsconfig.json

Nark checks 160+ packages — including axios, prisma, stripe, and redis — for correct error handling, resource cleanup, and runtime Nark Profiles. Pair it with Socket.dev in your CI pipeline to cover both supply chain security and runtime error handling in a single workflow.