π¦ Dependencies & Licensing
π¦ Dependencies & Licensing
π Summary
The application depends on a small set of 15 direct runtime libraries, which is a healthy, low-sprawl position. However, the dependency audit reports 24 known vulnerabilities (3 critical, 13 high), 11 of which reach production code. The single most important item is the web framework itself: Next.js is pinned to exactly 16.2.0, a release affected by roughly 26 published advisories, including critical remote-code-execution issues in a feature the product actually uses (generated tab icons). A second production concern is the spreadsheet library xlsx, which has not been updated on npm since 2022, has unfixed vulnerabilities, and is used to parse uploaded files on the server. Two declared libraries are not used at all. On licensing the picture is clean for a commercial acquirer: everything shipped is permissive, with only weak-copyleft (LGPL, MPL) or dual-licensed components that are used unmodified, and the product's own code is proprietary to a single named individual β which makes clear IP assignment a contractual must.
π― Rating
π΄ βββββ 2 / 5 β Red. A small, sensible dependency set is undermined by a critically vulnerable, exact-pinned framework and an abandoned parser handling untrusted uploads, with no automated dependency scanning to catch either.
π Findings
Part A β Dependencies
A1. Direct runtime dependencies
| Package | In use | Latest | Purpose | Where used | Flags |
|---|---|---|---|---|---|
| next | 16.2.0 (exact) | 16.4.0 | Framework, routing, RSC, image/OG generation | Whole app | Critical advisories; exact pin |
| react / react-dom | 19.2.4 (exact) | 19.3.0 | UI | Whole app | β |
| @supabase/supabase-js | 2.99.3 | 2.117.2 | DB, storage, auth client | 18 files import directly; 154 files use a client wrapper | Behind |
| @supabase/ssr | 0.9.0 | 0.12.7 | Cookie-based auth in RSC/route handlers | 3 files (src/lib/supabase/*) | Pre-1.0 |
| resend | 6.20.0 | 6.32.1 | Transactional e-mail | 4 files | β |
| mammoth | 1.12.0 | 1.13.0 | Read copywriters' .docx decks (browser) | src/app/(app)/campaign/[id]/ads/import-copy-modal.tsx | Transitive moderate vulns (argparse/sprintf-js) |
| xlsx (SheetJS) | 0.18.5 | 0.18.5 (npm, 2022-03-24) | Parse uploaded spreadsheets (product sheets, schedules) | src/lib/product-sheet-file.ts, called server-side from src/app/api/campaigns/[id]/products/route.ts:60 and client-side from plan/schedule-import.tsx | Unmaintained on npm; high-severity prototype pollution + ReDoS, no fix |
| ag-psd | 31.0.2 | 31.0.2 | Flatten .psd to PNG in the browser | 1 file | β |
| fflate | 0.8.2 | 0.8.3 | Build handover zip | src/lib/handover-zip.ts | Moderate advisory (ZIP64 infinite loop on unzip; app only zips) |
| lucide-react | 0.577.0 | 1.52.0 | Icons | 55 files | A major behind |
| clsx, tailwind-merge | 2.1.1, 3.5.0 | 2.1.1, 3.7.0 | Class-name utilities | 1 file each | β |
| date-fns | 4.1.0 | 4.4.0 | β | Not imported anywhere | Unused |
| google-auth-library | 10.6.2 | 11.1.0 | β | Not imported anywhere | Unused |
[Observed] package.json, npm outdated, grep -rlE "from '<pkg>'" src.
Unmaintained (no release in 2+ years): xlsx only (npm release 0.18.5 dated 2022-03-24; the vendor now distributes newer builds from its own CDN rather than npm). [Observed] No deprecated direct dependency is reported by npm; node-domexception (transitive) is deprecated. [Observed] npm ci warnings.
A2. Vulnerability audit (npm audit, 2026-10-07)
| Scope | π΄ Critical | π High | Moderate | βͺ Low | Total |
|---|---|---|---|---|---|
| All (incl. dev) | 3 | 13 | 7 | 1 | 24 |
Production only (--omit=dev) | 1 | 5 | 5 | 0 | 11 |
Key items:
| Package | Severity | Scope | Issue (advisory titles, summarised) | Fix |
|---|---|---|---|---|
| next 16.2.0 | π΄ Critical | Prod | ~26 advisories: RCE in next/og ImageResponse (<16.3.6) β used by src/app/icon.tsx and src/app/apple-icon.tsx; RCE in Image Optimisation with AVIF (<16.3.3); several middleware/proxy bypass issues (<16.2.5 / <16.2.11); SSRF in rewrites and WebSocket upgrades; multiple DoS and cache-poisoning issues | Upgrade to β₯ 16.4.0 |
| postcss, sharp (via next) | π High | Prod | XSS in CSS stringify; libvips CVEs | Arrive with the Next upgrade |
| xlsx 0.18.5 | π High | Prod | Prototype pollution; ReDoS | No npm fix β replace |
| @xmldom/xmldom (via mammoth) | π High | Prod | XML fragment injection | npm audit fix |
| fflate, mammoth/argparse/sprintf-js | Moderate | Prod | DoS-class issues | Patch / minor bumps |
| vitest, tinypool, @vitest/mocker | π΄ Critical | Dev only | RCE/path traversal in the test runner | Vitest 5 (not shipped to users) |
| eslint-config-next tree (braces, micromatch, fast-glob) | π High | Dev only | ReDoS/DoS | Bump with Next |
[Observed] npm audit, npm audit --json, npm audit --omit=dev. Whether the production deployments are actually running 16.2.0 depends on the deployed lockfile. [Unavailable β requires Vercel deployment access to confirm the deployed build.]
A3. Vendored, forked or patched code
- No
patches/directory, nopatch-package, no forked git dependencies. [Observed] src/types/mammoth.d.tsis a hand-written type declaration (not a fork). [Observed]- Studio code was moved to a separate private repository (
FS002-dev/campaign-studio) on 2026-09-19;src/lib/artwork/(fit arithmetic, renderer) stayed here. This is in-house code, not a vendored library, but its counterpart lives in another repository the buyer should also obtain. [Observed] CLAUDE.md "Parked decisions"; [Unavailable] the other repository. - Two Python audit utilities (
audits/*.py) and Node scripts (scripts/) are development tooling with no declared dependency manifest (norequirements.txt). [Observed]
A4. Major dependency relationships
Part B β Licensing
B1. Direct dependency licences
All 15 direct runtime dependencies are permissive: MIT (11), Apache-2.0 (xlsx, google-auth-library), ISC (lucide-react), BSD-2-Clause (mammoth). [Observed] each package's package.json.
B2. Whole installed tree (license-checker --summary)
MIT 417 Β· Apache-2.0 41 Β· ISC 26 Β· BSD-2 11 Β· BSD-3 8 Β· BlueOak-1.0.0 6 Β· MPL-2.0 5 Β· LGPL-3.0-or-later 2 Β· MIT AND Zlib 2 Β· and singletons: Python-2.0, CC-BY-4.0, BSD*, Unlicense, (MIT OR GPL-3.0-or-later), CC0-1.0, MIT-0, 0BSD, UNLICENSED (the product itself).
| Licence of note | Package(s) | Shipped? | Implication for a commercial acquirer |
|---|---|---|---|
| LGPL-3.0-or-later | @img/sharp-libvips-* (via next β sharp) | Server runtime on Vercel, dynamically linked, unmodified | Low risk. LGPL permits use from proprietary software; obligations (allow relinking, provide notice) are met by using the stock binary. Matters more if the product is ever distributed on-premise. |
| MPL-2.0 | lightningcss (build), axe-core, @axe-core/playwright (test) | Build/test only | File-level copyleft only on modified MPL files; none are modified. Negligible. |
| (MIT OR GPL-3.0-or-later) | jszip (via mammoth) | Browser bundle | Dual-licensed; the acquirer elects MIT. No obligation. |
| CC-BY-4.0 | caniuse-lite | Build data | Attribution data; standard across the ecosystem. Negligible. |
| BSD* (unparsed) | duck (transitive of mammoth) | Browser bundle | Licence string not SPDX-clean; confirm manually. Low. |
| GPL / AGPL / SSPL (strong copyleft) | None | β | β |
B3. Product licence, notices and provenance
LICENSE: "Copyright (c) 2026 Matthew Prins, trading as Midshift. All rights reserved." β proprietary, owned by a named individual trading as Midshift, not a company. [Observed]LICENSEline 1. Any acquisition needs a written IP assignment from that individual (and from any other contributors whose work the squashed history hides). [Inferred]package.jsondeclares"license": "UNLICENSED"and"private": true, consistent with proprietary code. [Observed]- No
NOTICE/ third-party attribution file is produced for the shipped bundle. [Observed] - No licence policy or allow-list is enforced in CI. [Observed]
.github/workflows/ci.yml - Code of uncertain provenance: the git history has been squashed to one commit by "Matthew Prins", so authorship of individual lines cannot be established from the repository. CLAUDE.md and code comments refer to work carried out across multiple "sessions", consistent with heavy AI-assisted development. [Inferred] Provenance of AI-generated code is not itself a licence breach, but the buyer should obtain warranties covering originality and third-party code. [Unavailable β requires original history and a contributor list.]
scripts/scrub.jsenforces that no client-identifying material is tracked β a positive confidentiality control (passes: "nothing client-identifiable in 715 tracked files"). [Observed]
π§Ύ Evidence
npm ci(490 packages) βnpm audit,npm audit --json,npm audit --omit=devβ "11 vulnerabilities (5 moderate, 5 high, 1 critical)".node -eoveraudit.jsonlisting every Next.js advisory title and affected range.npm outdated;npm view xlsx 'time[0.18.5]'β 2022-03-24.license-checker --summary,license-checker --production --json.npm ls jszip sharpβmammoth@1.12.0 β jszip@3.10.1,next@16.2.0 β sharp@0.34.5.grep -n "ImageResponse" src/app/icon.tsx src/app/apple-icon.tsx;src/app/api/campaigns/[id]/products/route.ts:54β60(server-sidesheetRowson an uploaded file).- Mermaid diagram validated (valid: true).
β οΈ Risks
| Risk | Severity | Effort |
|---|---|---|
| Next.js 16.2.0 with critical RCE and middleware-bypass advisories in production; exact pin prevents patch uptake | π΄ Critical | S |
xlsx parses attacker-controllable uploads on the server with known, unfixable-on-npm prototype pollution / ReDoS | π High | SβM |
No automated dependency/vulnerability scanning (no Dependabot/Renovate config, no npm audit in CI), so new advisories go unnoticed | π High | S |
| IP held by an individual; squashed history prevents verifying authorship | π High (transactional) | S (legal) |
Unused date-fns, google-auth-library widen supply-chain surface | βͺ Low | S |
| Dev-only critical advisories (Vitest/tinypool) β affect developer and CI machines, not users | βͺ Low | S |
| No third-party NOTICE file for shipped bundle | βͺ Low | S |
β Recommendations
| Recommendation | Priority | Effort |
|---|---|---|
Upgrade next and eslint-config-next to β₯ 16.4.0 and redeploy every client deployment; verify the deployed version | P0 (before close) | S |
Replace xlsx (vendor CDN build β₯ 0.20.x or exceljs); at minimum, cap upload size and parse only in the browser | P1 | SβM |
Enable Dependabot or Renovate and add npm audit --omit=dev --audit-level=high to CI | P1 | S |
Run npm audit fix for the non-breaking transitive fixes; upgrade Vitest to 5 | P2 | S |
| Remove unused dependencies | P2 | S |
| Obtain a deed of IP assignment and originality warranties from the copyright holder; request unsquashed history | P0 (transactional) | S |
Add a licence allow-list check (e.g. license-checker --onlyAllow) and generate a NOTICE file | P3 | S |