AI Frontier Post
Tutorials

Blind the agent reading your code: hands-on with BLA, the open-source shield against AI reverse-engineering

BLA, a five-day-old MIT-licensed shield created on October 25, 2026, hardens your shipped JavaScript against AI reverse-engineering agents: one audit, one protect command, and the demo file's exposure score fell from 81 to 2 while its output stayed identical. This guide runs every command and shows the real numbers, including the caveats.

TL;DR: BLA hardens your own shipped code against AI reverse-engineering agents by planting decoys and tripping the analyzer's resource budgets. Verified here with bla-agents 1.1.0 on Node 24: a 332-byte demo scored 81/100 exposed, then 2/100 after protect, with attacker token estimates rising 1,215x — while the program printed identical output. The token figures are the tool's internal estimates, not measured agent runs, and the one-command defend path at the bankrupt preset reached 3,172x.
  • Who: qybaihe/bla (MIT) — 1,093 stars, 148 forks, 178 commits, created October 25, 2026; gaining roughly 770–824 stars a day per Trendar and RepoAlerts on October 30, 2026.
  • What: the bla-agents 1.1.0 CLI (npm): doctor, audit, protect, verify, defend, benchmark, setup, and an MCP server for agent wiring.
  • When: verified October 30, 2026, on Node v24.22.1: audit 81/100 → protect → 2/100, 1,215x token amplification, identical program output.
  • Requirement: Node.js 22.23.4 or newer (24.x used here) and npx. No account, no API key, no GPU; a file you own to harden.
A small robot halted before a huge translucent shield wall covering a maze of glowing code paths
Illustration generated by AI Frontier Post.

Why this shield is blowing up now

Shipping software used to mean handing an attacker a binary and trusting that reading it would take longer than it was worth. That assumption broke when reverse-engineering agents arrived: point one at a shipped app and it reconstructs features, APIs, and logic in a single run, with every claim backed by evidence it pulled from the artifact itself. This blog covered that side of the story with REA, the open-source toolkit that does exactly that. BLA is the counter-move, and it appeared five days ago: created on October 25, 2026, MIT-licensed, it passed 1,000 stars within the week — 1,093 stars and 148 forks when checked on October 30, 2026, after gaining roughly 770 to 824 stars a day according to two independent trending trackers. Developers are not starring it for novelty. They are starring it because it answers a question that got urgent very fast: what do you do when the thing reading your shipped code is not a person with a disassembler, but an agent with a budget?

BLA's answer is to attack the budget, not the reader. Its slogan is "Poison, Exhaust, Hallucinate": plant decoys that look like real evidence, push the artifact past the analyzer's documented resource limits, and leave the agent with truncated inventories and ambiguous rabbit holes — while the program itself keeps running exactly as before. The project is explicit about what that means and what it does not. The token and dollar figures it reports are internal estimates derived from its catalog of the analyzer's limits, not measurements of a live agent run. The live-analyzer validation it publishes covers specific formats, and everything else is labelled designed-for, not verified. This guide keeps that distinction in every step below, and every number quoted from a command run is a number this sandbox actually produced.

What you'll need

  • Node.js 22.23.4 or newer, or Node 24.x. The steps below ran on Node v24.22.1, the same major version the project's own validation used. Check with node --version.
  • npx, which ships with Node. No global install is required; every command here runs through npx -y bla-agents, pinned to version 1.1.0.
  • A JavaScript file you own. The demo below is eight lines long. Never run a hardening tool against code you do not own or have no right to modify — BLA plants decoy credentials and honey metadata, and that is only legitimate in your own artifacts.
  • No account, no API key, no GPU. The whole pipeline runs locally. The optional agent wiring in Step 8 touches your coding agent's config files, and is previewed before it writes anything.
  • About 20 minutes. The commands take seconds; the reading takes the rest.

Step 1: Check that the tool is ready

Start with the readiness check. It reports the health of every protection engine and which coding agents it can see on your machine, without changing anything:

npx -y [email protected] doctor

On this machine the headline was BLA Doctor Readiness: HEALTHY (v1.1.0 on Node v24.22.1, linux-x64), with six subsystems ready: JavaScript/TypeScript AST and semantic budget breaking, Electron .asar unpacking and repacking, WebAssembly custom and name section shielding, Python marshal tarpits, native binary section shielding, and archive shielding. It also detected four coding agents — Claude Code, Codex CLI, Gemini CLI, and OpenCode — all with MCP unregistered and the skill not installed. That last line matters: detection is not registration. Nothing has been wired into your agents yet, and Step 8 shows how to preview that wiring before applying it.

Pin the version. The project's README describes a newer 1.4.0 run with a 14-target benchmark, but the version npm actually serves at the time of writing is 1.1.0, with an 8-target benchmark. Every command in this guide was run against 1.1.0, and every output below is 1.1.0 output. If a later version changes the benchmark or the flags, your output will differ in the details, not in the shape of the workflow.

Step 2: Build a demo target you own

Make a small directory and a small file. The file needs one real function with real control flow — a price calculator with a bulk-discount branch is enough for the analyzer to have something to find:

mkdir bla-demo && cd bla-demo
cat > sample.js <<'EOF'
// Tiny demo target: a price calculator with a "secret" discount rule.
function price(units, unitPrice) {
  let total = units * unitPrice;
  if (units >= 100) total *= 0.9; // bulk discount
  return Math.round(total * 100) / 100;
}
console.log("price(120, 2.5) =", price(120, 2.5));
console.log("price(10, 2.5) =", price(10, 2.5));
EOF
node sample.js

The baseline output, which you will compare against later, is:

price(120, 2.5) = 270
price(10, 2.5) = 25

Keep that output somewhere. The entire point of a hardening tool is that this output must not change, and "it still prints the same numbers" is the test you will run, not a feeling about the code.

Step 3: Audit the target before you protect it

Run the pre-flight scan. It measures how exposed the file is, in the tool's own scoring, before any protection exists:

npx -y [email protected] audit sample.js

For the 332-byte demo, the audit reported Protection Status: UNPROTECTED (REA Exposure Score: 81/100), REA Examination: COMPLETE (100% Exposed to Static Pass), and a verdict of TRIVIAL_CLONE. Its cost model estimated a Claude Opus 4 reconstruction at 3,980 tokens, 4 calls, 30 seconds, and $0.17 — and flagged the one surface item, the price function, as [CRITICAL] because its body and control flow are directly readable. That is the honest baseline: an eight-line file is trivially reconstructable, and the tool says so rather than flattering you. The exposure score is BLA's own metric, not an industry standard, so treat it as a before/after gauge on the same tool, not as a score you can compare with other products.

An abstract diagram of the three-stage pipeline: a parcel gains decoy markers, stretches past a limit line, then dissolves into fog
Illustration generated by AI Frontier Post.

Step 4: Protect the file

Now inject the shield. Give the output as a file path, not a directory — passing a directory path fails with an "unable to audit target" error even though it still writes a file by that name, a rough edge worth knowing before you script around it:

npx -y [email protected] protect sample.js -o sample.protected.js

The run took under half a second and reported BLA Adversarial Shield Successfully Injected! with the balanced preset and the default deterministic seed. The before/after block is the core result of this guide:

REA Exposure Score:       81/100 (UNPROTECTED)  -->  2/100 (BLA_PROTECTED)
REA Examination Status:   COMPLETE              -->  LIMITED
Obligation Graph Nodes:   1 nodes               -->  105 nodes
Attacker Token Burn:      3,980 tokens          -->  4,835,723 tokens (1215.0x)
Attacker API Bill:        $0.17                 -->  $78.80 (463.5x)
Agent Verdict:            TRIVIAL_CLONE         -->  AGENT_HALLUCINATION_AND_BANKRUPTCY

The mechanism behind those numbers is visible in the defense metrics: 44 decoy tarpit functions with 138 fake cross-references, 512 primitive-candidate branches against the analyzer's 256-candidate limit, 4,194,304 alias-selection states against its 512-state limit, 26 IPC ambiguity sites with 12 decoy routes, and 8 embedded chaff manifests. The file grew from 332 bytes to 51,384 bytes. That growth is the weapon and the cost at once: the analyzer must wade through it, and so must anyone else who opens the file, including you. Keep your original source; the protected file is a build artifact, not source code you edit.

Step 5: Prove the program still works, then verify the shield

Run both files and compare, byte for byte in spirit:

node sample.js
node sample.protected.js

Both printed price(120, 2.5) = 270 and price(10, 2.5) = 25. Runtime equivalence on a toy is not proof for a real application — your test suite is the real check, and it must run against the protected build before you ship it — but the mechanism held on the first attempt with no adjustment, which is the minimum a hardening tool must clear.

Then run the verifier, passing the protected file and the original:

npx -y [email protected] verify sample.protected.js sample.js

It reported Defense Score: 99/100 (ALL COUNTER-REA GATES PASSED) and Amplification: 1215x tokens | 463.5x API cost | 105x call-graph expansion, with five passing invariant checks: static and semantic examination degraded to LIMITED on the four tripped budgets (alias-selections, primitive-candidates, primitive-bytes, getter-expansion), the tarpit and call-graph labyrinth active, defensive chaff and honey context embedded, IPC pairing ambiguity present, and token amplification above the 10x gate. A 99 rather than 100 is worth noting rather than rounding away: the tool's own verifier leaves one point on the table, and the guide does not know which gate costs it, because the output does not say. Do not quote 99/100 as perfection; quote it as all gates passed with one point unexplained.

Step 6: Use the one-command pipeline for real builds

The audit, protect, and verify steps are the teaching path. The shipping path is one command, defend, which runs the full pipeline — release-exposure scan, pre-flight audit, protection at the strongest preset, and verification — and writes a .shielded.js file next to your target:

npx -y [email protected] defend sample.js

On the same demo, defend reported Intensity Preset: BANKRUPT (Defense Score: 99/100), Token amplification: 3172x, and an attacker bill of about $198.86, with 92 tarpit and shadow procedures, 306 mutually-recursive call-graph edges, 20 evidence-contract lures, and an obligation ledger expanded from 1 node to 209. The output file was 94,070 bytes, nearly twice the balanced preset's size. That is the trade the preset names honestly: balanced is the default for a reason, and bankrupt buys a bigger multiplier with a bigger artifact. Pick the preset per artifact — a small shipped bundle tolerates bankrupt; a large one may not — and measure the artifact size and your test suite on each. The presets are stealth, balanced, maximum, and bankrupt, selected with --intensity; --seed makes protection deterministic and reproducible, which you want in a build pipeline so the same input produces the same protected output.

An abstract chart showing one very short bar beside one towering bar, suggesting a cost explosion
Illustration generated by AI Frontier Post.

Step 7: Run the showcase benchmark — and read it correctly

BLA ships a benchmark that runs its showcase targets through the same pipeline and checks runtime equivalence:

npx -y [email protected] benchmark

Version 1.1.0 runs 8 targets, not the 14 the README's newer run describes. The aggregate result here was 1054.4x token amplification and 447.6x cost multiplication, with all 8 targets 100% Runtime-Equivalent. The individual rows tell you where the multiplier comes from and where it does not: the JavaScript and Electron targets amplify past 2,500x, the WebAssembly and model targets sit near 376x, and the SQLite target is the lowest at 161.9x. The pattern is consistent with the mechanism — the tool is strongest where the analyzer's budgets are tightest — and it is a reason to benchmark your own artifact type rather than borrowing the headline aggregate.

Read the benchmark the way the project itself tells you to. Its own documentation separates two kinds of number: the empirical analyzer failures recorded against real REA paths for specific formats, and the benchmark's token and dollar columns, which are internal estimates from its catalog of limits. The README states this distinction plainly, and so does this guide: the 1,215x on your demo file and the 1,054.4x aggregate are estimates of what reconstruction would cost an agent, not invoices from an agent that tried. What was actually measured here is narrower and stronger in its own way: the audit scores, the byte sizes, the gate passes, and the identical program outputs. If a vendor quotes you the multiplier without the caveat, you now know which sentence is missing.

Step 8: Wire it to your coding agent (preview first)

BLA can register itself as an MCP server and install a blind-llm-agents skill into your coding agents, so you can say "Harden my software against REA" instead of remembering the CLI. Preview that wiring before it writes anything:

npx -y [email protected] setup --dry-run

The dry run planned 4 agent registrations — Claude Code, Codex CLI, Gemini CLI, and OpenCode — each getting the skill file and an MCP entry pointing at npx -y bla-agents@latest mcp, and it wrote nothing. Applying it is your step, with --yes, and it edits real config files (for Claude Code, your .claude.json and the skills directory). This guide did not apply it on the sandbox machine, because mutating agent configuration is a reader-side decision, not a demo step. After setup, doctor is how you confirm the registrations landed.

When to use this vs the alternatives

Use BLA when your threat is specifically an AI agent reconstructing a shipped artifact: a JavaScript bundle, an Electron app, a WebAssembly module, a model file, or a database you distribute. It complements, rather than replaces, the older defenses. A minifier or obfuscator makes code harder for a human to read; BLA makes it more expensive for an agent's budgeted analyzer to finish, which is a different mechanism with a different failure mode. Stripping source maps and symbols removes evidence; BLA adds misleading evidence and budget trips on top of a clean artifact. A commercial packer wraps the whole binary; BLA works format-natively with no external packer or LLVM toolchain, and its own documentation draws that line explicitly. None of these replace keeping secrets out of shipped code in the first place — a key baked into a bundle is compromised no matter how expensive the bundle is to read, and a decoy credential is only safe because it is not real.

Do not use BLA as a reason to ship code you would not otherwise ship, or on code you do not own. Its disclaimer says it plainly: this is a defensive tool for protecting your own software. Running it against someone else's app to test whether the shield works is testing on a target you have no right to modify, and the canary credentials it plants could pollute someone else's incident response. The legitimate test targets are your own builds, the project's own examples, and the benchmark suite it ships.

The limits, stated plainly

  • The multipliers are estimates. Token and dollar amplification figures come from BLA's catalog of analyzer limits. They are useful for comparing presets and artifact types, not for predicting a real agent's bill.
  • Live-analyzer validation is format-specific. The project's published empirical results cover the formats it lists (JavaScript, Electron .asar and fuses, WASM with Wabt, SQLite, Safetensors, GGUF, Go buildinfo, BEAM, EVM, PCAP, Flutter pools). Other formats are designed-for and covered by unit tests, not by a recorded analyzer run.
  • Protected output is bigger and uglier. The demo grew 155x at the balanced preset and 283x at bankrupt. That is fine for a shipped bundle and terrible for anything a human maintains, which is why the protected file is a build artifact, never source.
  • Version drift is real. The README describes 1.4.0 and 14 benchmark targets; npm serves 1.1.0 with 8. Pin the version in your pipeline and re-run the benchmark when it moves.
  • One rough edge: -o with a directory path errors out while still writing a file by that name. Always pass a file path.
  • The verifier's 99/100 is unexplained. All gates pass, but the missing point is not attributed in the output. Treat the score as "all gates passed", not as a perfect grade.

The takeaway

BLA does one thing, and this guide verified that it does it: it takes a file an agent could reconstruct for $0.17 and turns it into a file the same tool estimates would cost $78.80 at the balanced preset or about $198.86 at bankrupt — while the program prints exactly the same numbers. Whether that multiplier survives contact with a real agent on your real artifact is the question the tool's own documentation leaves open for formats outside its validated list, and the honest way to answer it is to run the pipeline on your build, run your test suite against the protected output, and read the verify gates instead of the headline. The shield is free, MIT-licensed, five days old, and already past a thousand stars because the problem it addresses — agents that read shipped code faster than humans ever could — is not going away. Install it with npx -y [email protected] doctor, audit something you own, and look at the before/after numbers before you decide how much of your build deserves the bankrupt preset.

Sources and further reading