{"id":16329051,"url":"https://github.com/cs-au-dk/jelly","last_synced_at":"2025-05-13T12:51:16.263Z","repository":{"id":66974683,"uuid":"594013768","full_name":"cs-au-dk/jelly","owner":"cs-au-dk","description":"JavaScript/TypeScript static analyzer for call graph construction, library usage pattern matching, and vulnerability exposure analysis","archived":false,"fork":false,"pushed_at":"2025-04-10T11:11:07.000Z","size":1415,"stargazers_count":363,"open_issues_count":4,"forks_count":29,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-22T17:13:46.883Z","etag":null,"topics":["call-graph-analysis","javascript","library-usage","typescript","vulnerability-detection"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cs-au-dk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-27T11:49:49.000Z","updated_at":"2025-04-22T09:20:43.000Z","dependencies_parsed_at":"2023-02-27T22:00:26.371Z","dependency_job_id":"aea65576-a926-4456-be2d-ef39e9735f95","html_url":"https://github.com/cs-au-dk/jelly","commit_stats":{"total_commits":12,"total_committers":2,"mean_commits":6.0,"dds":0.08333333333333337,"last_synced_commit":"4b95271f96108d0edc502cfe9220682eb8470b8e"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cs-au-dk%2Fjelly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cs-au-dk%2Fjelly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cs-au-dk%2Fjelly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cs-au-dk%2Fjelly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cs-au-dk","download_url":"https://codeload.github.com/cs-au-dk/jelly/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253947456,"owners_count":21988939,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["call-graph-analysis","javascript","library-usage","typescript","vulnerability-detection"],"created_at":"2024-10-10T23:14:39.997Z","updated_at":"2025-05-13T12:51:16.249Z","avatar_url":"https://github.com/cs-au-dk.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Jelly\n\n[![MIT License](https://img.shields.io/github/license/cs-au-dk/jelly)](LICENSE)\n[![npm version](https://img.shields.io/npm/v/@cs-au-dk/jelly)](https://www.npmjs.com/package/@cs-au-dk/jelly)\n\n#### Copyright © 2023-2025 Anders Møller \u0026 Oskar Haarklou Veileborg\n\nJelly is a static analyzer for performing\n\n* *call graphs construction*,\n* *library usage pattern matching*, and\n* *vulnerability exposure analysis*\n\nfor JavaScript (and TypeScript) programs that use the Node.js platform.\n\nThe analyzer design is based on ideas from JAM [1], TAPIR [2] and ACG [3] with support for approximate interpretation [4]\nand indirection-bounding [5].\nIts core is a flow-insensitive control-flow and points-to analysis, together with access paths for tracking library usage.\nIt models the main parts of the ECMAScript language and standard library (intentionally not fully soundly!),\nand (for now) treats the Node.js standard library as unknown code.\n\n[1] Benjamin Barslev Nielsen, Martin Toldam Torp, Anders Møller:\n[Modular call graph construction for security scanning of Node.js applications](https://dl.acm.org/doi/10.1145/3460319.3464836).\nProc. ISSTA 2021: 29-41\n\n[2] Anders Møller, Benjamin Barslev Nielsen, Martin Toldam Torp:\n[Detecting locations in JavaScript programs affected by breaking library changes](https://dl.acm.org/doi/10.1145/3428255).\nProc. ACM Program. Lang. 4(OOPSLA): 187:1-187:25 (2020)\n\n[3] Asger Feldthaus, Max Schäfer, Manu Sridharan, Julian Dolby, Frank Tip:\n[Efficient construction of approximate call graphs for JavaScript IDE services](https://ieeexplore.ieee.org/document/6606621/).\nProc. ICSE 2013: 752-761\n\n[4] Mathias Rud Laursen, Wenyuan Xu, Anders Møller:\n[Reducing Static Analysis Unsoundness with Approximate Interpretation](https://dl.acm.org/doi/10.1145/3656424).\nProc. ACM Program. Lang. 8(PLDI): 194:1-194:24 (2024)\n\n[5] Madhurima Chakraborty, Aakash Gnanakumar, Manu Sridharan, Anders Møller:\n[Indirection-Bounded Call Graph Analysis](https://doi.org/10.4230/LIPIcs.ECOOP.2024.27)\nProc. ECOOP 2024: 27:1-27:27\n\n## Installing\n\n```bash\nnpm install -g @cs-au-dk/jelly\n```\n\nOther options are described below at [How to build](#how-to-build).\n\n## Usage\n\nSee the full usage:\n```bash\njelly --help\n```\n\nWhen running the Jelly static analyzer, one or more entry files are given as input.\nDirectories are expanded (using heuristics to skip certain files and directories, see [files.ts](src/misc/files.ts)).\nAll files reachable from entry files are analyzed, except\nif option `--ignore-dependencies` is used, in which case only entry files are analyzed,\nand only files within the base directory (auto-detected or specified using option `--basedir` or `-b`) are included.\n\nAs an example, generate a call graph for the `winston` package and all its dependencies, both in JSON format and for HTML visualization:\n```bash\njelly -j cg.json -m cg.html node_modules/winston\n```\n\nViewing `cg.html` in a browser:\n\n![call graph visualization](misc/winston-cg.png)\n\nTo set the heap limit, prefix commands by, for example:\n```bash\nNODE_OPTIONS=--max-old-space-size=8192\n```\n\nOn Linux, the `vm.max_map_count` system setting also affects how much memory can be used. If changing `--max-old-space-size` in the Node.js options doesn't help,\ntry running `sysctl vm.max_map_count` to see the current setting. On a machine with, for example, 64GB RAM, you can change the limit with `sudo sysctl -w vm.max_map_count=524288`.\n\nNote that analyzing with all dependencies (i.e., not using `--ignore-dependencies`) can take a long time.\nThe options `--max-indirections` or `--timeout` can be used to terminate the analysis early to provide partial (unsound) results.  \nSpecific packages can also be included or excluded using `--include-packages` or `--exclude-packages`.\n\n## How to build\n\nInstall dependencies:\n```bash\nnpm install\n```\n\nCompile TypeScript code:\n```bash\nnpm run build\n```\n\nAfter compilation, Jelly can be run like this:\n```bash\nnode lib/main.js\n```\n\nBuild binary executables (optional), placed in `dist/`:\n```bash\nsudo npm install -g pkg\nnpm run pkg\n```\nNote that the binary executables do not support dynamic call graph construction.\n\n##  Docker\n\nBuild Docker image (including support for dynamic call graph construction):\n```bash\nnpm run build-docker\n```\n\nRun Jelly in Docker with the directory specified as first argument as current working directory:\n```bash\n./bin/jelly-docker . tests/helloworld/app.js --callgraph-html cg.html\n```\n\n## Server-mode\n\nJelly can be run in server-mode as an alternative to the command-line interface:\n```bash\njelly-server\n```\nor\n```bash\nnode lib/server.js\n```\nSee also the instructions above for how to build binary executables.\n\nRequests to the server are sent on stdin using the JSON format described in `src/typings/ipc.ts`.\nResponses are returned (asynchronously) on stdout with the two-line header (including the empty line)\n```\nContent-Length: \u003cbytes\u003e\n\n```\nwith `\\r\\n` linebreaks.\n\n## Approximate interpretation\n\nTo enable static analysis with approximate interpretation (see reference [4] above), use option `--approx`:\n```bash\njelly --approx tests/helloworld/app.js\n```\n(This example assumes you have first installed test dependencies by running `npm run tests-install`.)\nAlternatively, you can run approximate interpretation and static analysis separately using options `--approx-only` and `--approx-load`:\n```bash\njelly --approx-only hints.json tests/helloworld/app.js\njelly --approx-load hints.json tests/helloworld/app.js\n```\n\n## Indirection bounding\n\nTo enable indirection bounding (see reference [5] above), use option `--max-indirections`:\n```bash\njelly --max-indirections 2 tests/helloworld/app.js\n```\n\n## Dynamic call graph construction\n\nJelly supports dynamic call graph construction via [NodeProf](https://github.com/Haiyang-Sun/nodeprof.js/),\nwhich can be used for measuring recall (or unsoundness) of the static analysis.\n\nInstall NodeProf (see also the information about Docker above):\n```bash\nsudo dnf install g++ libstdc++-static\nmkdir -p ~/tools; cd ~/tools\ngit clone --depth 1 --branch 6.0.4 https://github.com/graalvm/mx.git\nexport PATH=$PATH:$HOME/tools/mx\nmx -y fetch-jdk --java-distribution labsjdk-ce-17\nexport JAVA_HOME=$HOME/.mx/jdks/labsjdk-ce-17-jvmci-22.2-b01\ngit clone --depth 1 https://github.com/Haiyang-Sun/nodeprof.js.git\ncd nodeprof.js\nmx sforceimports\nmx --dy /compiler build\n```\n\nAs an example, run `tests/micro/classes.js` or `tests/helloworld/app.js` with instrumentation for call graph construction:\n```bash\nexport GRAAL_HOME=$HOME/tools/graal/sdk/latest_graalvm_home\n\njelly tests/micro/classes.js -d cg.json\njelly tests/helloworld/app.js -d cg.json\n```\nExtra arguments to the JavaScript program can be added after `--`.\n\nIt is also possible to run `npm test` with instrumentation:\n```bash\njelly --npm-test tests/mochatest -d cg.json\n```\n\nAnother approach is to add `$JELLY_HOME/lib/bin/node` to `PATH` and set `JELLY_OUT`, for example to run Mocha directly:\n```bash\ncd tests/mochatest\nPATH=$JELLY_HOME/bin:$PATH JELLY_OUT=cg.json node_modules/.bin/mocha\n```\nwhere `JELLY_HOME` is the home directory of Jelly.\nThis results in a file `cg.json-\u003cPID\u003e` for each instrumented file that is executed.\n\nCall graphs (generated either statically or dynamically) can be compared for precision and recall:\n```bash\njelly --compare-callgraphs cg1.json cg2.json\n```\n\n## For developers\n\nCompile TypeScript code in watch mode:\n```bash\nnpm run build-watch\n```\n\nInstall as scripts (`jelly` and `jelly-server`) for development:\n```bash\nsudo npm link\n```\n\nInstall dependencies for tests:\n```bash\nnpm run tests-install\n```\n\nRun all tests:\n```bash\nnpm test\n```\n\nRun individual tests (specified by regex), for example:\n```bash\nnpm test -- -t tests/helloworld\n```\n\nTo enable source map transformation of stack traces, prefix commands by:\n```bash\nNODE_OPTIONS=--enable-source-maps\n```\n\n### Differential testing\n\nDifferential testing can be used to test if updated code results in lower recall than the previous version by comparing the dataflow graph and call graphs of the two versions.\n\nRun the following command to test the testing framework:\n```bash\nTAG=\u003ctag\u003e npm run differential -- -t tiny\n```\nwhere `\u003ctag\u003e` is the git tag of the previous version you want to compare to.\n\nThen run the following commands to start full test:\n```bash\nTAG=\u003ctag\u003e npm run differential\n```\n\nDuring the test, the old version of Jelly will be installed in `tests/node_modules/jelly-previous` and test packages will be installed in `tmp/packages`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcs-au-dk%2Fjelly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcs-au-dk%2Fjelly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcs-au-dk%2Fjelly/lists"}