Togoder security

npm package security report

jiti@2.7.0 security report

Risky patterns found that deserve a look.

Needs review Version 2.7.0 Files reviewed 7 Size 194.9 KB Scanned

Summary

Togoder Security scanned the npm package jiti@2.7.0 on Oct 6, 2026. An AI review of 7 source files produced 8 medium, 12 low severity findings. The overall verdict is medium: the findings flag risky but common patterns (dynamic code, unsafe defaults, broad file or network access) rather than confirmed malware.

0
critical
0
high
8
medium
12
low

Findings 20

medium

Dynamic import with computed path

NPS-A75858848440

The script dynamically imports a module using a relative path ('./jiti.cjs') and later dynamically imports a user-supplied script via jiti.import(resolved). While typical for a CLI tool, dynamic imports based on user input can pose a risk if the resolved path is not properly validated, potentially leading to arbitrary code execution.

lib/jiti-cli.mjs:24
medium

Arbitrary code execution via module hook

NPS-A7EA70FFD422

The exported resolve/load hooks intercept all non-builtin, non-.mjs/.cjs module loads and transpile/execute them through the jiti runtime, including JSON modules converted to executable code (export default/module.exports). This allows code from any resolved file to run at import time.

lib/jiti-hooks.mjs:20
medium

Dynamic code execution

NPS-B0FB75ACE841

The loader uses jiti.transform to transpile arbitrary source files, which effectively evaluates/executes untrusted code during module loading. This is the intended behavior of a runtime transpiler but represents a code execution vector if a malicious module is resolved.

lib/jiti-hooks.mjs:60
medium

Environment access via import.meta.resolve

NPS-9B289770378E

jiti.esmResolve uses import.meta.resolve with a parent URL, which can resolve modules relative to arbitrary paths. Combined with dynamic import, this could be used to load modules from outside the intended scope if an attacker controls the id or parentURL. However, this is standard ESM resolution behavior and not malicious on its own.

lib/jiti-native.mjs:41
medium

Dynamic import with computed input

NPS-7E23E2C5E434

The jiti.import function constructs module specifiers dynamically from user-provided 'id', suffix, and extension values, then calls dynamic import(resolved). While this is expected behavior for a module loader, it allows loading arbitrary modules based on external input. This is a potential vector if untrusted input is passed to jiti.import, but it is the intended functionality of the package and not inherently malicious.

lib/jiti-native.mjs:62
medium

Dynamic module registration at import time

NPS-E0107379E763

The file uses top-level code with node:module register() to install a custom ESM loader hook from './jiti-hooks.mjs' at import time. This executes automatically whenever the module is imported and changes how subsequent modules are resolved/loaded. While this is a common legitimate pattern for runtime TypeScript/ESM loaders, custom loaders can intercept and alter module resolution and execution, so it warrants review of jiti-hooks.mjs.

lib/jiti-register.mjs:4
medium

Dynamic module loading with computed input

NPS-B8C752B94C66

The nativeImport helper calls the native import() function with a caller-supplied id. While this file only re-exports a factory function (createJiti) and does not itself trigger a load, the underlying _createJiti will resolve and execute modules based on runtime input. This is the intended behavior of a jiti runtime transpiler/loader, but it means any consumer passing attacker-controlled specifiers could cause arbitrary code execution.

lib/jiti-static.mjs:11
medium

Dynamic module loading with external input

NPS-E6E61F5E849A

The function createJiti accepts a dynamic 'id' parameter and passes it to _createJiti for module resolution/loading. Additionally, nativeImport dynamically imports modules by id. While this is the intended purpose of a JITI (Just-In-Time Importer) library, it means the package can load arbitrary modules based on user input, which could be abused if inputs are not properly validated.

lib/jiti.cjs:20
low

Module resolution from user input

NPS-ACA6F2631C45

The script resolves a user-provided script path using jiti.resolve and then imports it. If an attacker can control the script argument, they could potentially execute arbitrary code. However, this is the intended functionality of a CLI tool, so the risk is inherent to the tool's purpose.

lib/jiti-cli.mjs:26
low

Dynamic import / module loading with computed input

NPS-4E85DF3B85CD

createJiti() is invoked with the current filename, and jiti.import is passed as jitiImport into generated modules. Resolved specifiers from external input are passed to jiti.esmResolve, enabling dynamic module resolution based on runtime input.

lib/jiti-hooks.mjs:24
low

File system access

NPS-B0610DF7C378

readFile is used on arbitrary resolved file paths and recursively walks parent directories to locate package.json, reading file contents and parsing JSON. This is expected for a loader but accesses files outside the immediate package scope.

lib/jiti-hooks.mjs:30
low

Code generation / string interpolation into executable source

NPS-8F2CAEF1CF82

_wrapSource constructs a JavaScript module string via template literal interpolation of the transpiled source and filename, then returns it as a module format for execution. While not eval() literally, it is dynamic code construction executed by the ESM loader.

lib/jiti-hooks.mjs:84
low

Potential bug: undefined variable reference

NPS-12F9AC3B6A36

In normalizeParentURL, the check 'typeof filename !== "string"' references an undeclared variable 'filename' instead of the function parameter 'input'. If 'filename' is not defined in the enclosing scope, this will throw a ReferenceError at runtime. This appears to be a bug, not a security issue, but could lead to unexpected behavior.

lib/jiti-native.mjs:125
low

Dynamic import of local module

NPS-1AF5CAFE9C4A

register('./jiti-hooks.mjs', import.meta.url, {}) loads a relative module dynamically via Node's loader mechanism. The target is local and relative to import.meta.url rather than a computed external input, which reduces risk, but the actual behavior depends entirely on the contents of jiti-hooks.mjs.

lib/jiti-register.mjs:4
low

Top-level execution on import

NPS-86215B5210AD

Importing this module immediately creates a createRequire reference and binds a Babel transform (_babelTransform) at module scope. This is not an install-time script and does not perform I/O by itself, but it does pull in ../dist/babel.cjs and ../dist/jiti.cjs, both of which execute at import time. These files are outside the scope of this snippet and would need separate review.

lib/jiti-static.mjs:3
low

Transform function injection surface

NPS-9391DAB44494

createJiti replaces opts.transform with _babelTransform whenever the caller does not supply one. Any caller who can influence opts can instead supply an arbitrary transform function, which jiti will invoke on module source. This is a legitimate configuration point, but it is a code-execution vector if opts is ever built from untrusted input.

lib/jiti-static.mjs:15
low

Error handling rethrow

NPS-778DBBF496DB

onError simply rethrows errors. This is benign and does not introduce security concerns.

lib/jiti.cjs:4
low

Lazy require of internal module

NPS-B758FEDDDE66

lazyTransform lazily requires '../dist/babel.cjs' at runtime. This is a standard pattern to avoid loading heavy dependencies until needed, but it means code execution occurs upon first use. The referenced file is part of the package's own dist directory and is not suspicious per se.

lib/jiti.cjs:11
low

Dynamic import with computed input

NPS-77CC5C3A22A3

The nativeImport function uses a dynamic import with the variable 'id' passed from external callers. This could allow loading arbitrary modules if an attacker can control the id value. In the context of Jiti, this is expected behavior for a runtime module loader, but it is a potential vector if the input is not properly validated by callers.

lib/jiti.mjs:7
low

Lazy loading of native addon/transformer

NPS-30A5AE524C9B

The lazyTransform function uses createRequire to dynamically load '../dist/babel.cjs' at runtime when no transform option is provided. While common in Jiti for lazy-loading Babel, this pattern can be abused if the package is compromised to load malicious code. The path is relative and within the package, but the lazy loading means it isn't evaluated at import time.

lib/jiti.mjs:10

Files reviewed

FileVerdictWhat the reviewer saw
lib/jiti-cli.mjs medium The code is a legitimate CLI tool (jiti) with expected dynamic import behavior, but the use of computed dynamic imports from user input carries an inherent risk of arbitrary code execution if the script path is untrusted.
lib/jiti-hooks.mjs medium This is a legitimate jiti ESM loader hook that intentionally transpiles and executes arbitrary module source at import time, which is expected for its purpose but constitutes an inherent dynamic code execution surface with no evidence of exfiltration, credential harvesting, or backdoors.
lib/jiti-native.mjs medium The file implements a native ESM-only version of the jiti module loader with dynamic imports and resolution based on caller-provided identifiers; no overtly malicious patterns such as exfiltration, credential harvesting, obfuscation, or process spawning were found, but the dynamic import capability and a potential undefined-variable bug warrant caution.
lib/jiti-register.mjs medium No direct malicious behavior is present in this file, but it installs a custom module loader hook at import time, so the referenced jiti-hooks.mjs must be reviewed to fully assess risk.
lib/jiti-static.mjs medium No direct malicious behavior in this file, but it exposes a dynamic import/transform loader whose safety depends entirely on the caller-controlled inputs and the separate dist/jiti.cjs and dist/babel.cjs bundles.
lib/jiti.cjs medium The code appears to be a legitimate JITI (Just-In-Time Importer) wrapper with no obvious malicious patterns, though its inherent dynamic module loading capability warrants caution.
lib/jiti.mjs medium No clear malicious intent detected; the code uses dynamic imports and lazy loading typical of a runtime module loader like Jiti, but these patterns warrant caution if the package is compromised.

Frequently asked questions

Is jiti safe to use?

No confirmed malware was found in jiti@2.7.0, but the review flagged 8 medium, 12 low severity findings for risky patterns worth checking before you rely on it.

Does jiti contain malware?

No malware was identified in jiti@2.7.0 when Togoder Security scanned it on Oct 6, 2026. A new version can still introduce malicious code, so scan the exact versions in your lockfile.

How was jiti checked?

Togoder Security downloaded the published npm package and had an AI model read its 7 source files, looking for install scripts, credential access, network exfiltration, obfuscation, backdoors and crypto-wallet theft. The results are cached by file hash and shown here.

How do I scan jiti together with the rest of my dependencies?

Upload your lockfile at https://security.togoder.click/scan or call the API documented at https://security.togoder.click/api-docs. Files that have already been scanned, like the ones in jiti@2.7.0, cost nothing.

Related security reports