# readable-stream@4.7.0 security report (npm)

- Verdict: **Needs review** (risk level: medium)
- Scanned: 2026-10-04T16:31:15.000Z
- Files reviewed: 32
- Findings: 1 high, 2 medium, 7 low severity findings
- Report: https://security.togoder.click/npm/readable-stream
- Source: Togoder Security (https://security.togoder.click), AI source-code review

## Summary

Togoder Security scanned the npm package readable-stream@4.7.0 on Oct 4, 2026. An AI review of 32 source files produced 1 high, 2 medium, 7 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.

## Findings

### [high] Suspicious module path manipulation

Finding ID: `NPS-1824D882271C`

File: `lib/internal/streams/pipeline.js:3`

The file replaces the standard 'process' module import with require('process/'), a trailing-slash path that can resolve to an attacker-controlled local package named 'process' instead of the Node.js built-in. This is a dependency-confusion / module hijacking vector that may execute arbitrary code from a malicious 'process' package at import time.

### [medium] Suspicious module resolution

Finding ID: `NPS-0CEF5FA2CB30`

File: `lib/internal/streams/duplexify.js:3`

The module is required as `require('process/')` instead of the standard `require('process')`. The trailing slash could be an attempt to load a local or shadowed module rather than the built-in, potentially allowing execution of malicious code if such a module exists in the resolution path. This is unusual for a legitimate internal stream helper and warrants scrutiny.

### [medium] Import-time module loading

Finding ID: `NPS-7FD832266A44`

File: `lib/internal/streams/pipeline.js:3`

Top-level require() of process, aggregates, validators, utils, and abort-controller executes on import. The process/ override in particular causes side effects before any pipeline logic runs, making it an install/import-time execution surface.

### [low] Use of process.nextTick for deferred execution

Finding ID: `NPS-F89DBC7105A7`

File: `lib/internal/streams/destroy.js`

process.nextTick is used throughout for deferred callback scheduling. This is standard Node.js core stream behavior for error/close emission ordering, not a malicious pattern.

### [low] Dynamic module loading

Finding ID: `NPS-81EF2F94EC74`

File: `lib/internal/streams/destroy.js:5`

Uses require('process/') with a trailing slash and require('../../ours/errors'), '../../ours/primordials', and './utils'. These are internal path references typical of Node.js core stream implementation, not external malicious module loading.

### [low] Dynamic code execution via Function.prototype.call

Finding ID: `NPS-20074A840E21`

File: `lib/internal/streams/duplexify.js`

FunctionPrototypeCall is used to invoke `.then` and generator functions dynamically. While this pattern is common in Node.js internals to avoid prototype pollution, it can also be abused to call arbitrary functions. In this context it appears to be legitimate stream handling, but it represents a dynamic invocation pattern that could be a vector if the inputs are attacker-controlled.

### [low] Top-level code execution on import

Finding ID: `NPS-C4DB8976E507`

File: `lib/internal/streams/duplexify.js`

The file performs module resolution and initialization at import time (requires, globalThis access, class definition). Legitimate for a library, but any package imported by a project will execute this code when the module is loaded, so it is a potential attack surface if the package is compromised.

### [low] Dynamic require of internal modules

Finding ID: `NPS-A32A96B2E995`

File: `lib/internal/streams/pipeline.js`

Multiple conditional require() calls load core stream internals (./readable, ./passthrough) and '../../ours/util' lazily at runtime. While these are expected in Node core, in a third-party/repackaged context this pattern can be redirected to attacker-controlled paths if the module layout is manipulated.

### [low] Duplicate module export assignment

Finding ID: `NPS-B47129BF5052`

File: `lib/ours/browser.js:20`

The `destroy` export is assigned twice: first to `CustomStream.destroy` and then immediately overwritten with `originalDestroy` (which is `CustomStream.Readable.destroy`). This is likely a bug or accidental copy/paste issue that could lead to unexpected behavior. It is not malicious per se, but indicates potential code quality issues.

### [low] Potential prototype pollution or unexpected behavior

Finding ID: `NPS-A9B5F4D26F58`

File: `lib/ours/browser.js:25`

The `Object.defineProperty` call on `CustomStream` adds a `promises` getter with `configurable: true`. If `CustomStream` is a shared object, modifying it could affect other modules. However, this appears to be a deliberate API design, not malicious.

## Files reviewed

- `lib/internal/streams/duplexify.js` (medium): The code appears to be a modified/patched version of Node.js's internal duplexify with a suspicious `require('process/')` resolution, but contains no clear evidence of data exfiltration, credential theft, or backdoor installation.
- `lib/internal/streams/pipeline.js` (medium): The file appears to be a repackaged Node.js internal stream pipeline implementation, but the substitution of require('process/') for the built-in process module is a suspicious module-resolution hijack that could load attacker-controlled code, warranting caution despite the rest of the logic being standard stream plumbing.
- `lib/ours/browser.js` (medium): The code appears to be a legitimate wrapper for the Node.js stream module, with no malicious patterns such as data exfiltration, credential harvesting, obfuscation, or network requests. Minor concerns include a duplicate export and a property definition, but these are not security threats.
- `lib/_stream_duplex.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/_stream_passthrough.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/_stream_readable.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/_stream_transform.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/_stream_writable.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/internal/streams/add-abort-signal.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/internal/streams/buffer_list.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/internal/streams/compose.js` (safe): No malicious patterns detected; the code is a legitimate Node.js stream composition module with no network, filesystem, or process manipulation.
- `lib/internal/streams/destroy.js` (safe): This is a standard Node.js internal streams destroy implementation with no malicious code, exfiltration, credential harvesting, obfuscation, or backdoor patterns detected.
- `lib/internal/streams/duplex.js` (safe): No malicious patterns detected; this is the standard Node.js internal Duplex stream implementation with only expected require calls and no network, filesystem, process spawning, or obfuscated code.
- `lib/internal/streams/end-of-stream.js` (safe): No malicious patterns detected; the code is a legitimate Node.js internal stream utility with standard validation and cleanup logic.
- `lib/internal/streams/from.js` (safe): No malicious patterns detected; the code implements a standard Readable stream adapter for iterables with no network, filesystem, process, or credential access.
- `lib/internal/streams/lazy_transform.js` (safe): No malicious patterns detected; this is a legitimate internal Node.js stream utility implementing a lazy Transform stream with no network, file system, process, or dynamic code execution behavior.
- `lib/internal/streams/legacy.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/internal/streams/operators.js` (safe): No malicious patterns detected; the code implements standard stream operators with proper validation and error handling.
- `lib/internal/streams/passthrough.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/internal/streams/readable.js` (safe): This is a legitimate, well-known Node.js internal module (readable streams implementation) with no malicious patterns detected.
- `lib/internal/streams/state.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/internal/streams/transform.js` (safe): No malicious patterns detected; this is the standard Node.js internal Transform stream implementation with no exfiltration, credential harvesting, obfuscation, or process/network operations.
- `lib/internal/streams/utils.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/internal/streams/writable.js` (safe): No malicious patterns detected; this is the standard Node.js internal Writable stream implementation from the official Node.js source.
- `lib/internal/validators.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/ours/errors.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/ours/index.js` (safe): No malicious patterns detected; the code conditionally exports Node.js stream APIs and does not perform any suspicious network, filesystem, or process operations.
- `lib/ours/primordials.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/ours/util.js` (safe): This is a standard Node.js utility module that provides common functions like once, promisify, debuglog, and abort signal handling with no malicious patterns detected.
- `lib/ours/util/inspect.js` (safe): Cleared by Jev triage; no further analysis needed
- `lib/stream.js` (safe): No malicious patterns detected; the code is a standard Node.js stream module implementation with typical module imports and exports.
- `lib/stream/promises.js` (safe): No malicious patterns detected; code is a standard promise-based stream pipeline wrapper with no data exfiltration, credential harvesting, obfuscation, or unauthorized system access.

## Version ranges

None of the 3 scanned versions of readable-stream are flagged high or critical. The latest scanned version, 4.7.0, is medium risk. Only versions we have scanned are listed; unscanned versions between them are not covered.

- 4.7.0 (`4.7.0`): medium (Suspicious module path manipulation +2 more)
- 2.3.8 – 3.6.2 (`>=2.3.8 <=3.6.2`): clean
- 2.3.7 (`2.3.7`): not scanned

## Scanned versions

- [4.7.0](https://security.togoder.click/npm/readable-stream@4.7.0): medium, 2026-10-04T16:31:15.000Z
- [3.6.2](https://security.togoder.click/npm/readable-stream@3.6.2): safe, 2026-10-04T16:07:31.000Z
- [2.3.8](https://security.togoder.click/npm/readable-stream@2.3.8): safe, 2026-10-04T16:39:58.000Z

AI analysis is guidance, not a guarantee. Methodology: https://security.togoder.click/methodology
