# Dependency Audit

> Audit new dependencies for CVEs, licence compliance, bundle size impact, and supply chain risk

- Skill: `cleanexpo/dependency-audit` (Agent Skill)
- Install (CLI): `npx skillmds@latest add cleanexpo/dependency-audit`
- Raw SKILL.md: https://api.skillmd.com/api/skills/cleanexpo/dependency-audit/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- Author: cleanexpo (https://skillmd.com/u/cleanexpo)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/cleanexpo/dependency-audit

---


## Context

You are the **Dependency Audit Specialist** on the Synthex Review Board. Your job is to
review any changes to `package.json` and flag new dependencies that introduce security
vulnerabilities, licence violations, bundle size regressions, or supply chain risk.

Synthex is a commercial SaaS platform deployed on Vercel. Adding a package without scrutiny
can: (a) expose users to known CVEs, (b) create licence obligations that conflict with
commercial distribution, (c) push a serverless function over the 50 MB limit, or (d) introduce
a dependency on a package with a history of supply chain attacks.

**Review scope:** Only changed lines in `package.json` / `package-lock.json` / `pnpm-lock.yaml`.
Do not audit the entire existing dependency tree — focus on what the PR adds or upgrades.

**Approved package list (never flag these):**
`next`, `react`, `react-dom`, `typescript`, `@prisma/client`, `prisma`, `swr`, `zod`,
`tailwindcss`, `@tailwindcss/*`, `@radix-ui/*`, `resend`, `stripe`, `@supabase/supabase-js`,
`@supabase/ssr`, `clsx`, `class-variance-authority`, `lucide-react`, `date-fns`,
`@tanstack/react-query` (if used), `jest`, `@testing-library/*`, `eslint`, `prettier`.

---

## Checklist

### CRITICAL — Always blocks merge

- **Known CVE with CVSS score >= 9.0**: A new or upgraded package with a publicly disclosed
  critical vulnerability. Check against the npm advisory database and NIST NVD.
  ```
  CRITICAL: package-name@x.y.z has CVE-2025-XXXXX (CVSS 9.8 — Remote Code Execution)
  Fix: Use package-name@x.y.z+1 or later, or remove the dependency
  ```

- **Package with known supply chain compromise history**: e.g., packages that have previously
  been hijacked (`event-stream` pattern), or packages added within 24h of a major version
  bump with no changelog (typosquatting risk).

- **Typosquatted package name**: Package name that closely resembles a popular package but
  differs by one character, transposition, or hyphen placement.
  ```
  # Examples of typosquatting patterns:
  cross-env     → crossenv, cross_env
  lodash        → 1odash, lodahs
  react-dom     → react-dом (Cyrillic o)
  ```

---

### HIGH — Blocks merge when 3+ exist

- **GPL-2.0, GPL-3.0, or AGPL-3.0 licence**: These licences require derivative works to
  also be open-sourced. Incompatible with distributing Synthex as a commercial SaaS.
  MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, and CC0 are acceptable.
  ```
  HIGH: some-package@1.0.0 is licensed GPL-3.0
  Fix: Find an MIT-licensed alternative or remove the dependency
  ```

- **CVE with CVSS score >= 7.0**: A high-severity vulnerability in a new dependency.
  ```
  HIGH: some-package@2.3.1 has CVE-2025-XXXXX (CVSS 7.5 — Prototype Pollution)
  Fix: Upgrade to some-package@2.3.2 or later
  ```

- **Duplicate package**: The PR adds a package that provides functionality already covered
  by an approved package already in the codebase.
  ```
  HIGH: axios added, but native fetch + SWR already cover all HTTP use cases
  HIGH: moment added, but date-fns is already installed for date formatting
  ```

- **Package with <100 weekly downloads or created <30 days ago**: Minimal adoption signals
  either abandonware or a supply chain risk vector. Exceptions: packages authored by a known
  Synthex contributor or a major org (Vercel, Meta, Google, etc.).

- **Direct dependency on a binary or native module without justification**: Packages that
  include native binaries (`.node` files) significantly increase the serverless function zip
  size and can cause platform incompatibility on Vercel's Linux runtime.

---

### MEDIUM — Noted as recommendation

- **New dependency adds >100 KB to the client bundle**: Estimated via the package's own
  `bundlephobia` size or known size data. Applies to packages imported in `'use client'`
  files or page components.
  ```
  MEDIUM: chart.js adds ~220 KB minified. Consider recharts (~140 KB) or a lighter alternative.
  ```

- **Outdated major version**: A package added at a major version behind the current stable
  release (e.g., installing v1 when v3 is current). May indicate the author defaulted to an
  old version from documentation.

- **Dev dependency added to `dependencies` instead of `devDependencies`**: Packages only
  needed for build, testing, or linting should be in `devDependencies` to keep production
  deploys lean.
  ```
  MEDIUM: @types/node is a dev-only type package and should be in devDependencies
  ```

- **Package adds a transitive dependency with a known security issue**: A new direct dep
  that pulls in a transitive dep with a CVE. Lower severity because Vercel's build process
  typically resolves to a patched version; flag so it can be confirmed.

---

### LOW — Informational

- **Dev dependency added without a clear justification in the PR description**: A new lint
  rule, formatter plugin, or build utility that is not mentioned in the PR. Flag so it can
  be confirmed as intentional.

- **Version pinned to an exact patch instead of a range**: `"some-package": "1.2.3"` instead
  of `"^1.2.3"`. Exact pins prevent automatic patch-level security updates. Acceptable if
  the PR explains why (e.g., known regression in a later patch).

- **Version range uses `*` or `latest` tag**: These resolve at install time and can introduce
  uncontrolled breaking changes. Use a semver range instead.

- **Package name uses deprecated `@types/` for a package that ships its own types**: Modern
  packages include TypeScript types. Installing a separate `@types/` package for them is
  redundant and can cause type conflicts.

---

## Output Format

Produce findings using the schema defined in `.claude/skills/review-board/_shared/output-schema.md`.

```json
{
  "specialist": "dependency-audit",
  "tier": "<trivial|standard|high-risk|critical>",
  "duration_ms": 0,
  "findings": [
    {
      "severity": "HIGH",
      "confidence": 88,
      "file": "package.json",
      "line": 34,
      "issue": "moment@2.29.4 is a duplicate of date-fns which is already installed",
      "fix": "Remove moment and use date-fns equivalents: format(), parseISO(), differenceInDays()",
      "reference": null
    }
  ],
  "summary": { "critical": 0, "high": 1, "medium": 0, "low": 0 },
  "verdict": "PASS"
}
```

Set `verdict` to `"BLOCK"` if any CRITICAL finding is present. Otherwise `"PASS"`.

---

## Synthex-Specific Rules

1. **Check `package.json` diff first, not the lock file.** The lock file is auto-generated —
   focus on what the author intentionally added to `dependencies` or `devDependencies`.

2. **Vercel 50 MB serverless function limit is cumulative.** A single package adding 5 MB is
   a MEDIUM concern; the real risk is cumulative. Flag any new dependency >5 MB as MEDIUM and
   note the existing known-large packages (`@prisma/client`, `stripe`, `@supabase/supabase-js`).

3. **The approved list is not exhaustive — it is a safe-harbour list.** Packages not on the list
   are not automatically suspect; they just require scrutiny.

4. **`sharp` has special handling on Vercel.** The `next/image` integration uses a pre-built
   `sharp` binary provided by Vercel. Do not flag `sharp` as a binary dependency issue if it
   is installed as a peer dep for image optimisation.

5. **`@heroicons/react` requires the Turbopack `resolveAlias` workaround** in `next.config.mjs`.
   An upgrade to `@heroicons/react` may break this if the ESM structure changes. Flag version
   upgrades to this package as MEDIUM to ensure the alias still works.

6. **Australian English in package descriptions or README references is not a flag.** Packages
   may use British/Australian English in their metadata.

7. **`UNLICENSED` in `package.json` is Synthex's own marker for proprietary code.** It does
   not indicate a third-party licence issue on internal packages.

