Skip to main content

Documentation Index

Fetch the complete documentation index at: https://developer.upsun.com/llms.txt

Use this file to discover all available pages before exploring further.

AI agents are getting really good at reading code. Yours, your dependencies, the ones you forgot you depend on. The barrier to finding an exploitable bug in some random library 3 levels deep in your package.json keeps dropping. That’s a problem if your strategy for supply chain security is “I’ll patch when I hear about it”. You won’t hear about all of them, and you won’t hear in time. This post is about one small, concrete thing you can do today: fail your Upsun deployment when a high-severity vulnerability shows up in your dependencies. The mechanism is the build hook. This example uses Snyk, which has a free tier that’s enough for this, but any equivalent scanner works the same way. It’s not the whole answer. We’ll get to that. But it’s a real check that runs every time you push.

Why build-time matters

Dependency vulnerability scans usually live in 1 of 2 places: your CI pipeline, or your IDE. Both are fine, both are also avoidable. A developer can push a branch that skipped CI. A vulnerability database can publish a new advisory the day after your last green build. A build hook on Upsun runs on every deploy. If the scan fails, the deploy fails, and the new code never reaches an environment. That’s a different posture from “we hope someone runs the scan”. It’s also the same hook your npm install already runs in, so the cost of adding it is tiny.

Set up Snyk

You’ll need a Snyk account and an authentication token. The free plan is enough for this (capped at 200 scans per month though). Paid plans also scan your own application code, not only dependencies. Look at what each tier covers and pick what fits.
  1. Sign up at snyk.io and connect a personal account.
  2. Generate a personal access token (PAT) from your account settings.
  3. In Upsun, set the token as a project-level environment variable:
upsun variable:create --level project --name env:SNYK_TOKEN --value <YOUR_TOKEN> --visible-runtime false --sensitive true
The env: prefix exposes the value to your build container as a real environment variable. --visible-runtime false keeps it out of the runtime environment, since the build hook is the only place that needs it. --sensitive true hides the value in the Console and CLI output.

Add the scan to the build hook

Open your .upsun/config.yaml and add the scan to the hooks.build step:
.upsun/config.yaml
applications:
  app:
    type: "nodejs:20"
    hooks:
      build: |
        set -x -e
        npm install
        npx snyk test --all-projects --severity-threshold=high
A few things worth saying out loud:
  • npx is bundled with npm, which is bundled with the nodejs runtime. No separate install step.
  • --all-projects walks your repo and picks up every supported manifest it finds (package-lock.json, requirements.txt, composer.lock, and so on).
  • --severity-threshold=high is the lever that decides what counts as a deploy-blocking vulnerability. Drop it to medium if you want to be stricter, raise it to critical if you want to be quieter.
  • No explicit snyk auth call. The CLI picks up SNYK_TOKEN from the environment.
If the scan finds something at or above the threshold, snyk test exits non-zero, set -e kills the build, and your deploy fails. That’s the behavior you want. If you want to scan but not block (useful for the first week, while you triage what’s already in there), append || true:
npx snyk test --all-projects --severity-threshold=high || true
That makes the scan informational. Less useful as a permanent setting.

What this catches

Push a deploy with a known-bad dependency and Snyk reports something like this in your build log:
Tested 89 dependencies for known issues, found 1 issue, 1 vulnerable path.

Issues to fix by upgrading:

  Upgrade next@15.5.15 to next@16.1.5 to fix
  ✗ Allocation of Resources Without Limits or Throttling [High Severity]
    introduced by next@15.5.15
The build fails. The activity in the Upsun console shows the failure. You bump next, push again, deploy succeeds. Boring. Boring is the goal.

What this does not catch

A build-time scan only tells you what was vulnerable when you deployed. The hook runs at deploy time, not continuously. New CVEs land all the time, and the dependency you shipped on Monday can have an advisory published on Wednesday. If you don’t deploy in the meantime, your already-running production stays exposed until your next push. This check is necessary, not sufficient. You also want at least:
  • A scheduled scan against your production dependencies that notifies you when something new shows up. Snyk does this for projects you import into its dashboard. GitHub does it via Dependabot for repositories on GitHub. Pick whichever fits your setup.
  • A patching cadence. The scan finding a CVE only helps if someone actually upgrades the dependency. “We have alerts” without “we have an owner” is noise.
  • A view of your runtime stack, not only your application code. Base images, system packages, and runtime versions are part of your supply chain too. On Upsun, base images and system packages are bundled into the runtime versions themselves, and we keep them hardened and patched.
The build hook closes the door on shipping a known-bad version. Continuous monitoring catches the new known-bad versions of things you’ve already shipped. They’re different jobs.

Wrapping up

If you do nothing else after reading this, add 3 lines to your build hook and 1 project variable. That alone blocks a real category of deploys, and it costs you maybe 10 minutes. Then set up the alerting side. The half of supply chain security that runs on a schedule is the half that protects you tomorrow.
Last modified on April 30, 2026