
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
bun-plugin-javascript-obfuscator
Advanced tools
A Bun bundler plugin that integrates javascript-obfuscator for code obfuscation during builds
A Bun bundler plugin that integrates javascript-obfuscator for code obfuscation during builds.
bun add bun-plugin-javascript-obfuscator
obfuscatedBuild FunctionThe obfuscatedBuild function provides a complete build pipeline that:
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);
}
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,
}),
],
});
obfuscatedBuild(options)The main build function that provides full TypeScript support and vendor bundle separation.
| Option | Type | Default | Description |
|---|---|---|---|
entrypoints | string[] | required | Entry point files for the build |
outdir | string | required | Output directory for bundled files |
minify | boolean | false | Enable Bun's minification before obfuscation |
obfuscator | ObfuscatorOptions | {} | javascript-obfuscator options |
bundleNodeModules | boolean | true | Bundle node_modules into a separate file |
nodeModulesBundleName | string | "vendor.js" | Name of the vendor bundle file |
isExternal | (path: string) => boolean | (see below) | Custom function to identify external modules |
plugins | BunPlugin[] | [] | Additional Bun plugins to run before obfuscation |
external | string[] | [] | Modules to exclude from both main and vendor bundles (e.g., native modules) |
skipVendorBundleGeneration | boolean | false | Skip generating vendor bundle but still rewrite imports to use an existing one |
existingVendorBundlePath | string | undefined | Path to existing vendor bundle (for validation when using skipVendorBundleGeneration) |
Default isExternal behavior: Modules are considered external if they:
node_modules in the path., /, or ~ (bare imports like lodash)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.
| Option | Type | Default | Description |
|---|---|---|---|
include | RegExp | /\.(js|mjs)$/ | Files to include for obfuscation |
exclude | RegExp | undefined | Files to exclude from obfuscation |
Plus all javascript-obfuscator options.
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,
},
});
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",
});
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:
defaultlow-obfuscationmedium-obfuscationhigh-obfuscationIf 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,
},
});
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,
},
});
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:
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:
Phase 2 - Obfuscation: The bundled JavaScript output is passed through javascript-obfuscator with your specified options.
Phase 3 - Vendor Bundle: If bundleNodeModules is enabled:
import x from, import * as x from, import { a, b } from, and require()This approach keeps your application code obfuscated while:
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";
MIT
FAQs
A Bun bundler plugin that integrates javascript-obfuscator for code obfuscation during builds
We found that bun-plugin-javascript-obfuscator demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

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.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.