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.,
axoisinstead ofaxios) - 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
AxiosErrorwhenaxios.get()fails - Whether your Prisma query catches
P2002on a unique constraint violation - Whether your Stripe integration handles
StripeCardErroron 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 (throwsAxiosErroron 4xx, 5xx, and network failures)prisma.user.create()without catchingPrismaClientKnownRequestError(throws P2002 on duplicate records)stripe.charges.create()without catchingStripeCardError(silent payment failures)redis.get()without.on('error')handler registration (process crash on disconnect)openai.chat.completions.create()without handlingRateLimitError(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
| Capability | Socket.dev | Nark |
|---|---|---|
| Detects malicious npm packages | Yes | No |
| Detects typosquatting | Yes | No |
| Detects known CVEs | Yes | No |
| Checks install script behavior | Yes | No |
| Checks runtime error handling | No | Yes |
| Knows what axios throws | No | Yes |
| Knows what Prisma throws | No | Yes |
| Knows what Stripe throws | No | Yes |
| Profiles for 160+ npm packages | No | Yes |
| Analyzes your source code | No | Yes |
| Analyzes your lockfile/dependencies | Yes | No |
| GitHub PR integration | Yes | Yes |
| CI integration | Yes | Yes |
| Free tier | Yes | Yes (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.
| Tool | Focus | Overlap with Socket.dev | Overlap with Nark |
|---|---|---|---|
| Snyk | CVE detection, license compliance | High | None |
| npm audit | Known vulnerabilities in installed packages | High | None |
| Dependabot | Automated dependency updates for CVE fixes | High | None |
| Socket.dev | Malicious package detection, behavior analysis | - | None |
| Nark | Runtime error handling verification | None | - |
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.