New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

bun-plugin-javascript-obfuscator

Package Overview
Dependencies
Maintainers
1
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bun-plugin-javascript-obfuscator

A Bun bundler plugin that integrates javascript-obfuscator for code obfuscation during builds

latest
npmnpm
Version
1.0.1
Version published
Maintainers
1
Created
Source

bun-plugin-javascript-obfuscator

A Bun bundler plugin that integrates javascript-obfuscator for code obfuscation during builds.

Features

  • TypeScript Support: Works seamlessly with TypeScript files - Bun handles compilation before obfuscation
  • Separate Vendor Bundles: Automatically bundles node_modules separately (not obfuscated) and rewrites imports so everything works at runtime
  • Recursive Dependency Scanning: Automatically discovers all external dependencies by scanning your entire codebase
  • Comment-Aware: Ignores imports in commented-out code
  • Minification Support: Apply Bun's minification before obfuscation for optimal code size
  • Full Obfuscator Options: All javascript-obfuscator options are supported

Installation

bun add bun-plugin-javascript-obfuscator

Usage

The obfuscatedBuild function provides a complete build pipeline that:

  • Uses Bun to compile TypeScript to JavaScript and apply minification
  • Applies obfuscation to your application code
  • Bundles node_modules into a separate vendor file (not obfuscated)
  • Rewrites imports in the main bundle to use the vendor bundle
import { obfuscatedBuild } from "bun-plugin-javascript-obfuscator";

const result = await obfuscatedBuild({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",
  minify: true, // Bun handles minification before obfuscation

  obfuscator: {
    compact: true,
    controlFlowFlattening: true,
    stringArray: true,
    stringArrayThreshold: 0.75,
  },

  // Bundle node_modules separately (default: true)
  bundleNodeModules: true,
  nodeModulesBundleName: "vendor.js",
});

if (result.success) {
  console.log("Build completed!");
  console.log("Main bundle (obfuscated):", result.outputs);
  console.log("Vendor bundle:", result.vendorOutput?.outputs);
}

Alternative: Plugin API (for simple use cases)

For simpler use cases where you don't need TypeScript support or separate vendor bundling, you can use the plugin API directly:

import { javascriptObfuscator } from "bun-plugin-javascript-obfuscator";

await Bun.build({
  entrypoints: ["./src/index.js"], // Note: .js files only
  outdir: "./dist",
  plugins: [
    javascriptObfuscator({
      compact: true,
      controlFlowFlattening: true,
    }),
  ],
});

API Reference

obfuscatedBuild(options)

The main build function that provides full TypeScript support and vendor bundle separation.

Options

OptionTypeDefaultDescription
entrypointsstring[]requiredEntry point files for the build
outdirstringrequiredOutput directory for bundled files
minifybooleanfalseEnable Bun's minification before obfuscation
obfuscatorObfuscatorOptions{}javascript-obfuscator options
bundleNodeModulesbooleantrueBundle node_modules into a separate file
nodeModulesBundleNamestring"vendor.js"Name of the vendor bundle file
isExternal(path: string) => boolean(see below)Custom function to identify external modules
pluginsBunPlugin[][]Additional Bun plugins to run before obfuscation
externalstring[][]Modules to exclude from both main and vendor bundles (e.g., native modules)
skipVendorBundleGenerationbooleanfalseSkip generating vendor bundle but still rewrite imports to use an existing one
existingVendorBundlePathstringundefinedPath to existing vendor bundle (for validation when using skipVendorBundleGeneration)

Default isExternal behavior: Modules are considered external if they:

  • Contain node_modules in the path
  • Don't start with ., /, or ~ (bare imports like lodash)

Return Value

interface ObfuscatorBuildResult {
  success: boolean;
  logs: BuildLog[];
  outputs: BuildArtifact[];      // Main bundle (obfuscated)
  vendorOutput?: BuildOutput;    // Vendor bundle (not obfuscated)
}

javascriptObfuscator(options)

Creates a Bun plugin for direct integration with Bun.build().

Note: This plugin works at the source file level and is best suited for JavaScript files. For TypeScript support, use obfuscatedBuild instead.

Options

OptionTypeDefaultDescription
includeRegExp/\.(js|mjs)$/Files to include for obfuscation
excludeRegExpundefinedFiles to exclude from obfuscation

Plus all javascript-obfuscator options.

Examples

Full Obfuscation with TypeScript

import { obfuscatedBuild } from "bun-plugin-javascript-obfuscator";

await obfuscatedBuild({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",
  minify: true,
  target: "bun",

  obfuscator: {
    compact: true,
    controlFlowFlattening: true,
    controlFlowFlatteningThreshold: 0.75,
    deadCodeInjection: true,
    deadCodeInjectionThreshold: 0.4,
    debugProtection: true,
    disableConsoleOutput: true,
    identifierNamesGenerator: "hexadecimal",
    renameGlobals: false,
    selfDefending: true,
    stringArray: true,
    stringArrayCallsTransform: true,
    stringArrayEncoding: ["base64"],
    stringArrayThreshold: 0.75,
  },
});

With Native Module Exclusions

When using native modules that can't be bundled (e.g., modules with .node files), exclude them:

await obfuscatedBuild({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",
  minify: true,

  obfuscator: {
    compact: true,
    stringArray: true,
  },

  // These modules will remain as external requires
  external: [
    "argon2",           // Native crypto module
    "nodejs-polars",    // Has .node files
    "better-sqlite3",   // Native SQLite bindings
  ],

  bundleNodeModules: true,
  nodeModulesBundleName: "vendor.js",
});

Using Presets

import { obfuscatedBuild } from "bun-plugin-javascript-obfuscator";
import JavaScriptObfuscator from "javascript-obfuscator";

// Get preset options
const presetOptions = JavaScriptObfuscator.getOptionsByPreset("high-obfuscation");

await obfuscatedBuild({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",
  obfuscator: presetOptions,
});

Available presets:

  • default
  • low-obfuscation
  • medium-obfuscation
  • high-obfuscation

Without Vendor Bundle

If you want node_modules to remain external (not bundled at all):

await obfuscatedBuild({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",
  bundleNodeModules: false, // node_modules imports remain as external requires
  obfuscator: {
    compact: true,
  },
});

Custom External Detection

await obfuscatedBuild({
  entrypoints: ["./src/index.ts"],
  outdir: "./dist",

  // Only treat specific packages as external
  isExternal: (path) => {
    return path.startsWith("react") || path.startsWith("lodash");
  },

  obfuscator: {
    compact: true,
  },
});

Shared Vendor Bundle (Multiple Builds)

When building multiple entrypoints separately (e.g., main app and worker scripts), you can share a single vendor bundle:

const outdir = "./dist";
const obfuscatorConfig = { compact: true, stringArray: true };

// First build: generates vendor.js
const mainResult = await obfuscatedBuild({
  entrypoints: ["./src/index.ts"],
  outdir,
  minify: true,
  obfuscator: obfuscatorConfig,
  bundleNodeModules: true,
  nodeModulesBundleName: "vendor.js",
});

// Second build: reuses existing vendor.js
const workerResult = await obfuscatedBuild({
  entrypoints: [
    "./src/workers/worker1.ts",
    "./src/workers/worker2.ts",
  ],
  outdir,
  minify: true,
  obfuscator: obfuscatorConfig,
  bundleNodeModules: true,
  nodeModulesBundleName: "vendor.js",
  // Skip generating vendor.js, just rewrite imports to use the existing one
  skipVendorBundleGeneration: true,
  existingVendorBundlePath: `${outdir}/vendor.js`,
});

This approach:

  • Generates the vendor bundle only once (from the first build)
  • Rewrites imports in all builds to reference the shared vendor bundle
  • Avoids duplicating dependencies across multiple output files

How It Works

  • Dependency Analysis: The build function recursively scans all your source files (starting from entrypoints) for import/require statements to identify external dependencies. Comments are stripped before scanning to avoid false positives from commented-out code.

  • Phase 1 - Bun Compilation: Your TypeScript/JavaScript code is compiled and bundled by Bun with node_modules marked as external. This phase handles:

    • TypeScript to JavaScript compilation
    • Minification (if enabled)
    • Tree shaking
    • Bundle optimization
  • Phase 2 - Obfuscation: The bundled JavaScript output is passed through javascript-obfuscator with your specified options.

  • Phase 3 - Vendor Bundle: If bundleNodeModules is enabled:

    • External dependencies are bundled into a separate vendor file (not obfuscated)
    • The main bundle is rewritten to import from the vendor bundle instead of the original package names
    • All import styles are handled: import x from, import * as x from, import { a, b } from, and require()

This approach keeps your application code obfuscated while:

  • Third-party code remains readable (it's already public anyway)
  • Avoiding issues that can occur when obfuscating already-minified library code
  • Making debugging easier by keeping vendor code readable

TypeScript Support

The plugin is written in TypeScript and exports all necessary types:

import {
  obfuscatedBuild,
  javascriptObfuscator,
  type ObfuscatorBuildOptions,
  type ObfuscatorBuildResult,
  type BunObfuscatorPluginOptions,
  type ObfuscatorOptions,
} from "bun-plugin-javascript-obfuscator";

License

MIT

Keywords

bun

FAQs

Package last updated on 11 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts