Library / SDK
CapacitorSet/box-js avatar
CapacitorSet/box-js

box-js: emulating Windows JScript to read malicious JavaScript

A tool for studying JavaScript malware.

675 stars89 forksJavaScriptMIT

At a glance

What is it?
box-js runs a suspicious script inside a simulated Windows scripting environment and reports what it did, which files it wrote, which URLs it reached and which of those look like payload drops. It is a static-plus-dynamic analysis helper for malware analysts, and it prints conclusions in a folder of JSON rather than making them for you.
Who is it for?
box-js fits a malware analyst who needs a readable trace of what a JScript dropper does on a Windows box, without a full sandbox, and who is willing to read the JSON output and judge it. It is the wrong tool if you need a verdict, since it reports behaviours rather than classifying them, and it is the wrong tool if your samples are not JScript, since the emulated environment is a specific one.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 113 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A Windows JScript environment simulated in Node

The README describes box-js as a utility to analyse malicious JavaScript, and the repository description says it is a tool for studying JavaScript malware. The approach is emulation rather than static reading: the tool emulates a Windows JScript environment, prints a summary of the emulation to the console, and writes a results folder to disk.

The audience is an analyst facing a dropper or downloader that only runs its payload logic under Windows scripting hosts, usually with WScript and ActiveXObject style calls that mean nothing outside a Windows box. Rather than a Windows machine, box-js provides the pieces such a script expects, so the interesting branches execute and can be observed.

The repository layout shows how much of this is a JavaScript rewriting problem rather than an emulator in the virtual machine sense. There are rewriter files named equality_rewriter.js and loop_rewriter.js, a patch.js with a patches directory, an appended-code.js, a require_override.js, a boilerplate.js of stubbed browser objects, a decoder.c compiled into the package, and an emulator directory holding the environment. The dependencies tell the rest of the story: vm2 provides the sandbox in which the sample runs, jsdom and xmldom supply DOM and XML objects, acorn and escodegen and uglify-es handle parsing and code generation, and system-registry emulates the Windows registry.

The results folder is the deliverable

Running the tool on a sample called `sample.js` creates a folder called `sample.js.results`, or `sample.js.1.results` and so on if that already exists. The contents are the analysis, in machine-readable form.

There is `analysis.log`, a log of the analysis as it was printed on screen, and a series of files identified by UUIDs, which are the artefacts the sample wrote. `snippets.json` lists pieces of code executed by the sample, including JavaScript and shell commands. `urls.json` is the list of URLs contacted, and `active_urls.json` is the subset that seems to drop active malware. `resources.json` holds the ADODB streams, meaning the files the script wrote to disk, with their file types and hashes. `IOC.json` lists behaviours identified as indicators of compromise, and the README names registry accesses, written files and HTTP requests among them.

That last file is where the real work starts for a user. The tool flags registry accesses and file writes as suspicious, which in a legitimate script can look identical to what a dropper does. Deciding which of the collected indicators matter is left to you, and the README says as much when it offers the results for your own analysis, with automatic submission to Malwr, VirusTotal or a Cuckoo sandbox as an alternative handled by the separate `box-export` command. Run `box-export --help` for the details of that export path.

npm install, and a second binary for exporting

Installation is a single global npm install, and the README says exactly that:

bash
npm install box-js --global

The package manifest declares two executables, not one, which is worth noticing because the README refers to both:

json
    "bin": {
        "box-js": "run.js",
        "box-export": "integrations/export/export.js"
    }

So `box-js` runs the analysis and `box-export` handles the submission side. The manifest also pins the engines field at node >= 6.0.0, and the runtime dependencies are an older generation: jsdom at ^16.2.2, uuid at ^3.2.1 and acorn at >=8.8.0 sit alongside the more current vm2 requirement of >=3.9.19.

The analysis itself is a one-liner once installed:

bash
box-js sample.js

The name of the tool comes from the fact that it emulates a Windows box, so the sample believes it is running inside one rather than on a Linux terminal.

Without --download the payload URL returns a simulated 404

One flag changes what the analysis actually observes, and it is the most interesting thing in the tool. The README states that you will often also want to download any payloads, and that the `--download` flag enables downloading. Without it, the engine simulates a 404 error, so the script is tricked into thinking the distribution site is down and contacting any fallback sites.

That is a deliberate design decision about what to observe. A downloader with a primary and a backup host behaves differently when the primary fails, and the failure path is where the second, and often more suspicious, infrastructure shows up. Running without `--download` therefore yields the fallback contact list without fetching the payload, and running with it yields the payload as well.

The trade is that with `--download` you are pulling a live artefact onto your machine, which is why the README recommends further isolation by running the analysis in a temporary Docker container, and points at `integrations/README.md` for how to set that up. The download is a deliberate action, and the default is the safer one.

Missing document objects are fixed with boilerplate.js

A common failure when emulating a sample is that the script throws because some object it expects is missing, and the README devotes a section to exactly that, titled Analysis Fails Due to Missing 'document' Object or Other Objects/Functions.

The fix is the boilerplate. The box-js repository from git includes a `boilerplate.js` file that defines stubbed versions of common browser objects such as document, and the README suggests rerunning the analysis with `--prepended-code=DIR/boilerplate.js`, where DIR is the directory of the cloned box-js repository, or with `--prepended-code=default`. The option tells box-js to prepend the JavaScript in the given file to the sample being analysed.

The design is that you can copy boilerplate.js and add your own stubbed classes and objects as needed, and the `--prepended-code=show-default` option prints the full path to the default boilerplate.js file so you know what to copy. The alternative is to pass a directory, in which case the contents of all files in the directory are prepended.

This is the mechanism by which the environment grows to fit the sample, and it explains why the tool reports what it observed rather than what it concluded. The analyst supplies the missing pieces, and the analysis reflects the environment the analyst built.

Batch mode runs one analysis per core by default

box-js is typically used on single files, but it accepts a list of files or folders:

bash
box-js sample1.js sample2.js /var/data/mySamples ...

By default it processes samples in parallel, running one analysis per core, and `--threads` overrides that, with 0 removing the limit so box-js spawns as many analysis threads as possible. The README is explicit about the consequence: that setting results in very fast analysis but possibly overloading the system, and that analyses are usually CPU-bound, not RAM-bound. That last point is the useful one, since it tells you what to expect when you scale past your core count.

Two more flags shape the output. `--loglevel=warn` silences analysis-related messages and shows only progress information, and `--timeout` sets the number of seconds after which the script times out, with a default of 10.

The results are meant to be aggregated afterwards. The README shows extracting the active URLs once the analysis has finished:

bash
cat ./*.results/active_urls.json | sort | uniq

For automation there is a documented convention: the return codes are meant to be used to distinguish between different types of errors, with the details in `integrations/README.md`.

Isolation and integrations are the reason to install it globally

The README lists where box-js is available besides npm, and the list is a good summary of how the tool is used in practice. It is a Cuckoo module, with the `integrations` directory and a separate Cuckoo_Boxjs project referenced. It is a Dockerfile, described in `integrations/README.md`. It is packaged in Linux distributions aimed at security professionals, with REMnux and BlackArch named. It is part of open source applications, with Intel Owl named, and part of commercial third-party services, with any.run named.

That list also answers the question of where the tool sits in a workflow. It is a component inside larger analysis systems rather than a destination in itself, and the same is true of the export path, which hands results to Malwr, VirusTotal or a Cuckoo sandbox.

One caveat is not stated in the README but follows from the design. The tool emulates a Windows environment, executes the sample inside it, and with `--download` fetches whatever the sample asks for. That is untrusted code running on your machine, which is why the isolation recommendation exists, and why a Docker container rather than a local run is the sensible default for a hostile sample.

A version 1.9.29 tool with a Travis badge and no releases

The maintenance picture is straightforward. The repository is not archived and the last push was on 2026-07-02, so there is recent activity, but the project has no GitHub releases. The repository does contain a RELEASE_NOTES.txt file, and the manifest version is 1.9.29.

The build tooling shows its age. Continuous integration runs on Travis, with a.travis.yml at the root and a Travis build badge in the README, and the development dependencies are eslint with the Google config, babel-eslint and mocha, with the test script running `mocha test/`. The lint script covers run.js, analyze.js, the test directory and the emulator directory. There is a.gitmodules file, which means part of the tree comes from other repositories, and the presence of a decoder.c file means at least one piece of the package is native code that has to be compiled.

The licence is MIT, with the LICENSE file at the root and the author recorded as CapacitorSet. The topic list names es6, es6-proxies, javascript, malware, malwareanalysis and nodejs, and the es6-proxies tag points at the specific technique the emulator relies on, since a proxy-based object model is what lets a stubbed environment intercept and record the calls a sample makes.

Editorial conclusion

box-js fits a malware analyst who needs a readable trace of what a JScript dropper does on a Windows box, without a full sandbox, and who is willing to read the JSON output and judge it. It is the wrong tool if you need a verdict, since it reports behaviours rather than classifying them, and it is the wrong tool if your samples are not JScript, since the emulated environment is a specific one. Verify first that your Node version satisfies the engines field, that you read the flags list before running with --download on a hostile sample, and that you run it in the temporary Docker container the README recommends.

Frequently asked questions

How do I install box-js and analyse a sample?

Install it with npm install box-js --global, then run box-js sample.js on the script you want to study. The tool emulates a Windows JScript environment, prints a summary and creates a sample.js.results folder with analysis.log, snippets.json, urls.json, active_urls.json, resources.json and IOC.json.

What does the --download flag do in box-js?

It actually downloads the payloads the sample asks for. Without it the engine simulates a 404 error so the script believes the distribution site is down and contacts its fallback sites, which is how you collect the secondary infrastructure without fetching the payload.

How do I fix a box-js analysis that fails with a missing document object?

Rerun with --prepended-code=DIR/boilerplate.js, where DIR is the directory of the cloned box-js repository, or with --prepended-code=default. You can copy boilerplate.js and add your own stubbed objects, and --prepended-code=show-default prints the path of the default file.

Can box-js analyse many samples at once?

Yes. Pass a list of files or folders, for example box-js sample1.js sample2.js /var/data/mySamples, and it processes them in parallel with one analysis per core by default. The --threads option changes that, and 0 means unlimited, which the README warns can overload the system since analyses are usually CPU-bound rather than RAM-bound.

Where can box-js analysis results be submitted?

The README says you can analyse the results yourself or automatically submit them to Malwr, VirusTotal or a Cuckoo sandbox, using the separate box-export command. For more information on that, run box-export --help.

Official sources

  1. CapacitorSet/box-js on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/capacitorset-box-js.svg)](https://hysenlabs.com/projects/capacitorset-box-js)

Was this useful?