Skip to content

feat: add Snyk dependency scanning and Netlify deployment config - #1753

Open
magic-peach wants to merge 1 commit into
mainfrom
feat/snyk-and-netlify
Open

feat: add Snyk dependency scanning and Netlify deployment config#1753
magic-peach wants to merge 1 commit into
mainfrom
feat/snyk-and-netlify

Conversation

@magic-peach

Copy link
Copy Markdown
Collaborator

Adds Snyk vulnerability scanning and makes the site deployable on Netlify (for the Open Source plan), alongside the existing Vercel deployment.

Part 1 — Snyk

  • snyk as a devDependency (installed with bun — this repo uses bun.lock, not npm)
  • .snyk policy with no ignores, and a commented template showing the reason/expiry shape for future exceptions
  • bun run security for local pre-PR checks
  • .github/workflows/snyk.yml on push to main and PRs, --severity-threshold=high, expecting a SNYK_TOKEN secret

Separate workflow, not a job in main.yml — it needs a different trigger gate and a different secret, and a security finding failing "CI" would read as a broken build. It also matches how this repo already splits concerns (lint.yml, typecheck.yml, chromatic.yml each stand alone).

Two things the obvious setup would have got wrong:

Snyk cannot read bun.lock. Its Node scanner resolves dependency trees from package-lock.json, yarn.lock or pnpm-lock.yaml. With only bun.lock present, snyk test falls back to package.json version ranges, which can't pin transitive versions — so it would have reported clean while seeing almost nothing. CI and the local script both generate a throwaway lockfile first via npm install --package-lock-only. It's never committed (gitignored, and CLAUDE.md forbids it); bun.lock stays the source of truth.

Fork PRs get no secrets. Same gate as the Chromatic workflows, for the same reason — otherwise SNYK_TOKEN is empty and every contributor PR fails red.

Part 2 — Netlify

netlify.toml with publish = "out" and an explicit bun install && bun run build. Explicit because Netlify's package-manager detection keys off bun.lockb, and this repo uses the newer text-format bun.lock — relying on detection would have silently fallen back to npm.

Headers (the load-bearing part)

All seven headers from vercel.json are mirrored into both netlify.toml and public/_headers, byte-for-byte identical (verified programmatically). Netlify's docs don't state which wins when both define a header, so keeping them in agreement means precedence can't matter.

X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Strict-Transport-Security: max-age=31536000; includeSubDomains
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

The last two are load-bearing: ffmpeg.worker.ts branches on self.crossOriginIsolated and loads the multi-threaded core only when true. Verified rather than assumed — served the real out/ with the real headers in headless Chrome:

crossOriginIsolated = true
SharedArrayBuffer available = true

The COEP trap this nearly walked into

require-corp blocks cross-origin subresources that send no CORP/CORS headers — and netlify.com serves its badge SVG with neither. A hotlinked badge would have been silently blocked on the live site, i.e. exactly where the OSS plan needs it visible. Confirmed with a control test:

Badge source Result under require-corp
Hotlinked from netlify.com BLOCKED
Self-hosted (/badges/…svg) LOADED

So the SVG is vendored at public/badges/netlify-badge-color-accent.svg. The link still points to netlify.com, which is what the plan actually asks for.

Badge + Code of Conduct link added to the site footer and the README.

Drive-by fixes

  • README.md had an unresolved merge conflict committed to main (lines 44–61) rendering literal <<<<<<< HEAD markers on GitHub. HEAD's side was empty, so the fix is dropping the markers.
  • Its CI badge pointed at Sneha079-codes/reframe — a fork — instead of this repo.

Verified

bun run build, bunx tsc --noEmit, bun run lint all pass; out/_headers and the badge both land in the publish directory.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NhT15Aq6XUyhZSHa2HAh57

── Snyk ─────────────────────────────────────────────────────────────────────

snyk added as a devDependency (via bun — this repo uses bun.lock, not npm),
a .snyk policy with no ignores, a `bun run security` script, and a dedicated
snyk.yml workflow.

Separate workflow rather than a job in main.yml: it needs a different trigger
gate and a different secret, and a security finding failing "CI" would read as
a broken build. It also matches how this repo already splits concerns, with
lint.yml, typecheck.yml and chromatic.yml each standing alone.

Two things the obvious setup would have got wrong:

  * Snyk's Node scanner resolves dependency trees from package-lock.json,
    yarn.lock or pnpm-lock.yaml. bun.lock is not a supported target file, so
    `snyk test` here would fall back to package.json ranges and miss
    transitive vulnerabilities entirely. Both CI and the local script generate
    a throwaway lockfile first with `npm install --package-lock-only`. It is
    never committed — package-lock.json is gitignored and CLAUDE.md forbids it.

  * Fork PRs get no repository secrets, and nearly all contributions here come
    from forks, so the job is gated to pushes and same-repo PRs. Otherwise
    SNYK_TOKEN would be empty and every contributor PR would fail red.

Requires a SNYK_TOKEN repo secret, which does not exist yet.

── Netlify ──────────────────────────────────────────────────────────────────

netlify.toml with an explicit `bun install && bun run build` and publish = out.
Explicit because Netlify's package-manager detection keys off bun.lockb, while
this repo uses the newer text-format bun.lock — relying on detection would
have silently fallen back to npm.

Security headers are mirrored into netlify.toml AND public/_headers, byte for
byte identical to vercel.json (verified programmatically). Netlify's docs do
not state which source wins when both define a header, so keeping them in
agreement means precedence cannot matter. Collapse to one once verified live.

COOP: same-origin + COEP: require-corp are load-bearing, not hygiene:
ffmpeg.worker.ts branches on self.crossOriginIsolated and loads the
multi-threaded core only when it is true. Verified by serving the real out/
directory with the real headers: crossOriginIsolated = true and
SharedArrayBuffer available = true.

That same COEP setting would have broken the Netlify badge. netlify.com serves
the badge SVG with neither Cross-Origin-Resource-Policy nor CORS headers, so a
hotlinked <img> is blocked outright — confirmed with a control test that
rendered RESULT-BLOCKED. The SVG is self-hosted at
public/badges/netlify-badge-color-accent.svg instead; same-origin assets are
exempt from COEP. The link still points at netlify.com, which is what their
open source plan actually asks for.

Footer gains the badge and a Code of Conduct link; README gains both too.

── Drive-by fixes ───────────────────────────────────────────────────────────

README.md had an unresolved merge conflict committed to main (lines 44-61),
which renders literal <<<<<<< HEAD markers on GitHub. The HEAD side was empty,
so the resolution is to drop the markers. Its CI badge also pointed at
Sneha079-codes/reframe, a fork, rather than this repo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NhT15Aq6XUyhZSHa2HAh57
@vercel

vercel Bot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
reframe Ready Ready Preview Aug 27, 2026 2:21am

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@github-actions

Copy link
Copy Markdown
Contributor

👋 Thanks for your PR, @magic-peach!

Welcome to Reframe — a browser-based video editor built for everyone 🎬

What happens next

  1. 🤖 Automated checks — build & TypeScript typecheck will run automatically
  2. Vercel preview — a preview deployment will be created (requires maintainer authorization for fork PRs)
  3. 👀 Code review — a maintainer will review your changes
  4. 🚀 Merge — once approved, your PR will be merged!

Quick checklist

  • PR title follows Conventional Commits (e.g. feat: add dark mode)
  • Linked the issue this PR closes (e.g. Closes #123)
  • Tested the changes locally (bun run dev)
  • Build passes (bun run build)

Useful links

Happy coding! 🎉

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ PR Format Issues — @magic-peach

Please fix the following before your PR can be reviewed:

  • ⚠️ No linked issue found. Add Closes #<issue-number> to your PR description.

Push new commits after fixing — this comment will update automatically.

📖 CONTRIBUTING.md

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error —— View job


I'll analyze this and get back to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

level:advanced Advanced level - 55 pts type:bug Bug fix type:docs Documentation type:security Security type:testing Testing

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant