Aran is a npm module for instrumenting JavaScript code. Aran was designed as a generic infra-structure for building various development-time dynamic program analyses such as: objects and functions profiling, debugging, control-flow tracing, taint analysis and concolic testing. Aran is a JavaScript library without any dependencies that only export functions for manipulating estree. Hence, additional work is required to actually conduct program analysis.
Disclaimer Aran started as an academic research project, and is used at SOFT lab to support publications and run experiments. Although Aran supports almost entirely ECMAScript2024 and is well-tested against test262, it has been rarely used to instrument large-scale programs. The performance overhead and even the increase size of the instrumented code may cause issues.
Aran is a npm module that can be installed
as any other npm module with: npm install aran
. It exports two main functions:
generateSetup
: generates an estree that should be executed before any instrumented code.instrument
: instruments an estree and expects the advice to be defined as a global variable.
npm install aran acorn astring
import { generate } from "astring";
import { parse } from "acorn";
import { instrument, generateSetup } from "aran";
globalThis._ARAN_ADVICE_ = {
"apply@around": (_state, callee, this_, arguments_, path) => {
console.dir({ callee, this: this_, arguments: arguments_, path });
return Reflect.apply(callee, this_, arguments_);
},
};
globalThis.eval(generate(generateSetup()));
globalThis.eval(
generate(
instrument(
{
kind: "eval",
root: parse("console.log('Hello!');", { ecmaVersion: 2024 }),
},
{
advice_variable: "_ARAN_ADVICE_",
standard_pointcut: ["apply@around"],
},
),
),
);
Of particular interest are:
- instrumentation source input
- instrumentation configuration
- standard aspect
- flexible aspect
- reporting system
- aran language
Beside performance overhead, Aran has some known issues that may cause instrumented programs to no behave as their pre-instrumented version.
- Corrupt error stack
- Corrupt function string representation
- Duplicate super prototype access
- Early module declaration
- Early script declaration
- Internal deep eval declaration
- Missing iterable return call in pattern
- No arguments two-way binding
- No dynamic function property
- Path membrane break local eval
- Weave membrane miss deep eval
- Wrong realm for default prototype
- Wrong this parameter in with in eval
In practice, the issue that is most susceptible to cause a program to behave differentially is early script declaration. Other issues require fairly convoluted code to arise.
I'm Laurent Christophe a phd student at the Vrij Universiteit of Brussel. My promoters are Coen De Roover and Wolfgang De Meuter.