Your CI artifacts and preview deployments can leak unprotected JavaScript
Many teams start obfuscating or VM-protecting client JavaScript in the production Vite or webpack build, then assume the problem is solved. The production CDN may be clean. Meanwhile, the unprotected bundle is sitting in a CI artifact, a preview URL, a GitHub Actions zip retained for 90 days, or a leftover object from last week's deploy. This article is about the places unprotected JavaScript…
Many teams assume that protecting client JavaScript in production builds is enough to secure their code. However, unprotected JavaScript can still leak through various channels, such as CI artifacts, preview deployments, GitHub Actions zip files, or leftover objects from previous deploys. The article discusses how to identify and close these leaks without making preview URLs inconvenient.
During a typical pipeline, code is first built using "npm run build," which generates an obfuscated JavaScript bundle. This bundle is then uploaded as an artifact, often accessible to anyone with repo access or even anyone with a link, depending on visibility and retention settings. The preview deployment step typically skips the slow or paid protection process to speed up checks, making the preview URL a publicly accessible website with the actual algorithms.
Old production deploys, CloudFront versions, un-overwritten asset folders, or public Docker images can also expose unprotected code. If a competitor can't access the protected production bundle, they might opt for the unprotected preview. Preview URLs are public by default on platforms like Vercel, Netlify, and Cloudflare Pages, leaving your company's VPN requirements aside.
To protect previews, authentication policies must be implemented. This could be through Vercel Deployment Protection, a Netlify password, Cloudflare Access, or basic authentication. Alternatively, you could run the same protection step on previews, accepting the additional build time. Another option is to ship a reduced preview that mocks proprietary functions or uses stub solvers.
CI artifacts, registries, and even GitHub Releases can unintentionally retain unprotected JavaScript. Public or organization-visible GitHub Releases attached with dist.zip or npm pack tarballs containing source code are common cases. Public images in registries may also include build output layers with sensitive information. Storybook or Chromatic builds that import proprietary modules can also lead to leaks if not handled carefully.
To check for leaks after pipeline changes, search for JavaScript files in dist, .next/static, .output/public, or any publicly accessible paths. If you upload artifacts, verify their contents before publication. If a file were posted publicly for a week, would you be comfortable with it? If not, restrict access or protect it first.
Source maps and debug builds are another source of leaks. Source maps with sourcesContent, unminified chunks, and development bundles can be published alongside preview URLs or attached as artifacts named sourcemaps.zip. Keep these maps separate from your client JavaScript, and do not upload unprotected source maps as public workflow artifacts.
Finally, treat every output containing client JavaScript as a shipping surface. Minify everything, obfuscate your modules, and reserve VM-style protection for critical algorithms. A JS VM obfuscator can compile selected functions to custom bytecode, providing a higher security floor for sensitive code.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.