Summary
Togoder Security scanned the npm package crossws@0.3.5 on Oct 4, 2026. An AI review of 14 source files produced 2 medium, 6 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 8
Missing origin/URL validation
NPS-7499141F70C2
The constructor accepts a URL and immediately uses it for EventSource and fetch without validating that it is a trusted origin. This could lead to connections to malicious servers if an attacker can influence the URL (e.g., via query parameters or stored data).
Potential data exfiltration via bidirectional stream
NPS-2DFE2C528C62
When the 'bidir' option is enabled (default true), the code opens a POST request to the same URL with a ReadableStream body that is tied to the send() method. This allows arbitrary data to be sent to the server via the stream. While this is the intended functionality of a WebSocketSSE polyfill, it could be abused if the URL is attacker-controlled or if the library is used in a context where data is automatically sent without user awareness.
Durable Object WebSocket handling
NPS-7BC1D691C44E
This adapter is designed for Cloudflare Durable Objects, using the platform's WebSocket Hibernation API. It attaches state (subscriptions, peer ID, URL) to WebSocket objects via serializeAttachment/deserializeAttachment. No external network calls, credential access, or obfuscation are present.
State serialization on WebSocket objects
NPS-8E980C39F008
Peer state (topic subscriptions, peer ID, URL) is persisted via Cloudflare's serializeAttachment API. This is standard for Durable Object WebSocket hibernation and does not transmit data to external parties.
Insecure header encoding
NPS-C16A6BE6AEB1
The sendResponse function uses encodeURIComponent() on HTTP header names and values. HTTP header names/values are not URL-encoded in normal HTTP responses, and percent-encoding them corrupts the headers (e.g. 'Content-Type' becomes 'Content-Type' only if no special chars). This can break responses or, worse, if a header value contains characters that are encoded, it may not be interpreted correctly by clients. More importantly, it does not properly sanitize against header injection (CRLF) because encodeURIComponent does not encode CR/LF in all cases (it does encode them, but this is not the standard way to prevent header injection). This is a functional/security weakness but not malicious.
Potential trust boundary issue with X-Forwarded-Proto
NPS-052127A10D03
NodeReqProxy.url constructs the request URL using the 'x-forwarded-proto' header without validation. If the application is behind a proxy that does not strip this header from external clients, an attacker can spoof it to influence URL scheme detection. This could lead to incorrect security decisions if the URL is used for CORS/origin checks. However, this is a common pattern in WebSocket adapters and not inherently malicious.
Unvalidated upgrade headers
NPS-EA0FF4CA43B0
In the handleUpgrade method, upgradeHeaders from hooks.upgrade are stored on the request object and later used in the 'headers' event to push raw strings into outgoing headers without validation. If an attacker can control the hook's output (e.g., via configuration or custom hooks), they could inject arbitrary headers or CRLF sequences. This is a design risk but not evidence of malicious code.
Suspicious network request/endpoint manipulation
NPS-FD392463BD65
The constructor modifies the URL by replacing 'ws' prefix with 'http' and creates an EventSource connection. If the original URL was 'wss://' (secure WebSocket), this replacement would produce 'https://' only if the regex is applied carefully. The regex /^ws/ only replaces the first occurrence at the start, so 'wss://' becomes 'https://' which is acceptable. However, the code also establishes a secondary POST fetch to the same URL with a custom header 'x-crossws-id', potentially leaking data to the server if the URL is user-controlled and not validated.
Files reviewed
| File | Verdict | What the reviewer saw |
|---|---|---|
| dist/adapters/node.mjs | medium | The code is a legitimate WebSocket adapter implementation with no clear malicious intent, though it has minor security weaknesses in header handling and trust of proxy headers. |
| dist/websocket/sse.mjs | medium | The code implements a WebSocket-over-SSE polyfill with no obvious malicious patterns, but lacks URL validation and could be abused for data exfiltration if the URL is attacker-controlled. |
| dist/adapters/bun.mjs | safe | No malicious patterns detected; the code implements a WebSocket adapter with standard upgrade, message, open, and close handling. |
| dist/adapters/cloudflare-durable.mjs | safe | No malicious patterns detected; the file implements a legitimate WebSocket adapter for Cloudflare Durable Objects using standard platform APIs. |
| dist/adapters/cloudflare.mjs | safe | No malicious patterns detected; the code is a legitimate Cloudflare WebSocket adapter for crossws with no data exfiltration, credential harvesting, obfuscation, or other red flags. |
| dist/adapters/deno.mjs | safe | No malicious patterns detected; the code is a standard Deno WebSocket adapter with no exfiltration, obfuscation, or suspicious activity. |
| dist/adapters/sse.mjs | safe | No malicious patterns detected; the code implements a Server-Sent Events adapter without data exfiltration, credential harvesting, obfuscation, or other suspicious behaviors. |
| dist/adapters/uws.mjs | safe | No malicious patterns detected; the code is a legitimate WebSocket adapter for the uWebSockets.js library with no signs of exfiltration, credential harvesting, or dynamic code execution. |
| dist/index.mjs | safe | The file only re-exports symbols from an internal shared module with no executable or suspicious code. |
| dist/shared/crossws.By9qWDAI.mjs | safe | No malicious patterns detected |
| dist/shared/crossws.D9ehKjSh.mjs | safe | No malicious patterns detected |
| dist/shared/crossws.DfCzGthR.mjs | safe | No malicious patterns detected; the code is a WebSocket message/peer utility library with standard encoding and proxy logic, no external network, filesystem, env, or dynamic execution behavior. |
| dist/websocket/native.mjs | safe | No malicious patterns detected; the file only re-exports the global WebSocket constructor. |
| dist/websocket/node.mjs | safe | This is a minimal ES module wrapper that simply re-exports a WebSocket implementation using the global WebSocket if available, with no malicious patterns detected. |
Frequently asked questions
Is crossws safe to use?
No confirmed malware was found in crossws@0.3.5, but the review flagged 2 medium, 6 low severity findings for risky patterns worth checking before you rely on it.
Does crossws contain malware?
No malware was identified in crossws@0.3.5 when Togoder Security scanned it on Oct 4, 2026. A new version can still introduce malicious code, so scan the exact versions in your lockfile.
How was crossws checked?
Togoder Security downloaded the published npm package and had an AI model read its 14 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 crossws 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 crossws@0.3.5, cost nothing.