Sefism is free for learners. We are here to help you grow, one step at a time.Join for free
Sefism.
Security

Vulnerable Function Reachability Checker for JavaScript and TypeScript Dependencies

Build a tool that tells a JavaScript or TypeScript team whether their code actually calls the vulnerable function behind each dependency alert, not just whether the package version is affected. Go has this built in with govulncheck; the npm world mostly does not have a free equivalent. The result is fewer, more trustworthy alerts, with a call path as evidence for each one that matters.

Difficulty

Advanced

Needs a team, real planning, and a supervisor who knows the area.
Effort

2 semesters · 2 to 3 students

Deliverables

7 to ship

4 optional extras

Suggested stack

TypeScriptTypeScript compiler API or JellyOSV and GitHub Advisory DatabaseNode.jsGitHub ActionsSQLite
A suggestion, not a requirement. Swap anything for what you already know.

What you should ship

  • A dependency reader for package-lock.json and pnpm-lock.yaml that lists affected packages from OSV
  • A curated mapping from at least 60 npm advisories to the exact vulnerable functions, built from fix commits
  • A call graph builder for an application and its node_modules that handles ES modules and CommonJS
  • A reachability verdict per advisory: reachable with a call path, not reachable, or unknown with a reason
  • A command-line tool and a GitHub Action that comment the reachable alerts on a pull request
  • An evaluation on at least 15 open source applications comparing alert counts with npm audit
  • A hand check of a sample of 'not reachable' verdicts to measure how often the tool is wrong

If you have time left

  • Semi-automatic extraction of vulnerable functions from fix commits for new advisories
  • Dynamic confirmation by running the test suite with instrumentation and recording calls
  • Python support using an existing call graph library
  • Export of verdicts as OpenVEX statements so other scanners can use them

The problem: hundreds of dependency alerts, most of them noise

A typical Node.js application pulls in hundreds or thousands of packages. Run npm audit or turn on Dependabot and you get a long list of advisories. Most of them concern a function your code never calls: a regular expression in a command-line helper you do not use, or a parser for a format you never parse. Teams learn to ignore the list, and the one alert that matters is ignored with the rest.

Upgrading everything is not always possible either. A breaking major version, a framework that pins an old dependency, or a release freeze can leave a team carrying a known vulnerable package for weeks. They need to know which ones are actually reachable from their code.

What already exists and the gap

  • npm audit, Dependabot and Trivy match package versions against advisories. They do not look at whether the vulnerable code is used.
  • govulncheck for Go builds a call graph and reports a vulnerability only when a vulnerable function is reachable, using symbol-level data in the Go vulnerability database. It is the model for this project.
  • Commercial software composition analysis tools offer reachability for JavaScript as a paid feature.
  • Research call graph tools such as Jelly from Aarhus University analyse JavaScript call graphs, but are not packaged as an everyday dependency checker.

The gap is a free, open tool that brings the govulncheck experience to npm: symbol-level advisory data for popular packages, a call graph, a verdict with a call path as evidence, and an honest "unknown" when JavaScript's dynamic features defeat the analysis.

Inspiration

"Beyond Metadata: Code-centric and Usage-based Analysis of Known Vulnerabilities in Open-source Software" by Serena Elisa Ponta, Henrik Plate and Antonino Sabetta (ICSME 2018) describes SAP's approach: identify the code changed by each fix, then use static and dynamic analysis to check whether an application can reach it. It was released as an open source tool for Java and Python. This project applies the same idea to the JavaScript ecosystem, where the need is larger and the analysis is harder.

What you build

  • Developers run one command and get a short list: these advisories are reachable, here is the call path from your code to the vulnerable function.
  • Security leads see the full list with each item marked reachable, not reachable or unknown, and can prioritise upgrades.
  • Reviewers get a pull request comment only when a change makes a vulnerable function newly reachable.

The technically interesting part

  • Symbol-level advisory data. Advisories name packages and versions, not functions. For each advisory, find the fix commit, diff it, and record the changed functions as the vulnerable symbols. Build this by hand for 60 or more advisories in popular packages, then try to automate it.
  • JavaScript call graphs. Dynamic property access, callbacks, require with computed paths, and re-exports make precise analysis impossible in general. Choose a sound-ish approach, measure where it breaks, and return "unknown" with the reason rather than a false "safe".
  • Scale. node_modules can hold millions of lines. Analyse only the packages on paths towards a vulnerable package, and cache results per package version, since the same version gives the same graph.
  • Evidence. Each reachable verdict carries a call path a developer can follow file by file. That is what makes people trust the tool.

How to evaluate it

  • Noise reduction: alerts per project from npm audit against reachable alerts from your tool.
  • Correctness of 'not reachable': for a random sample, try to trigger the vulnerable function by hand or by dynamic tracing. A false "not reachable" is the worst mistake, so report it prominently.
  • Unknown rate: share of advisories the tool could not decide, and why.
  • Speed: analysis time on small, medium and large applications, cold and cached.

Suggested plan

  • Weeks 1 to 3: study govulncheck's output and the SAP paper; read lock files and query OSV.
  • Weeks 4 to 8: build the symbol mapping for the first 30 advisories from fix commits.
  • Weeks 9 to 14: call graph construction and the first reachability verdicts.
  • Second semester: caching, GitHub Action, the remaining advisories, evaluation on open source applications and the write-up.

Path to a product

Alert fatigue is one of the main complaints about dependency scanning, and reachability is a feature people pay for. A free tool with an open symbol-level dataset could become a community project in its own right, and the dataset is useful to other scanners. The evaluation is publishable at a software engineering venue.

Scope warning

Do not build a JavaScript parser or call graph engine from scratch; use the TypeScript compiler API or an existing research tool. Support one package manager lock format first. Be strict about the meaning of "not reachable": when in doubt, the answer is "unknown".

Learn what you need on Sefism

Get help with this idea

The risk is an analysis that is either too slow or too eager to call things safe. Tauseef can help you choose the call graph approach, build the advisory dataset efficiently and design an evaluation that a sceptical reviewer would accept. If you are new here, create a free account first.

Ideas and guidance, not finished projects

These are project ideas and scoping guidance, published free for students to use as a starting point. I do not build, write, or sell final-year projects, and I do not complete coursework for anyone. Take an idea, make it yours, and build it.

Not sure this one fits you?

I help students pick an idea that matches their skills and their deadline, then scope it down until it is finishable. Guidance only, never done for you.

Discuss this idea
Work with me

Stuck on something specific?

Writing only gets you so far. If you want an answer to your situation rather than the general case, book a session and we will work through it together. Sessions are free for approved Sefism members, and a few slots open each week.