r/node • • 15h ago

PHP had to scramble last week - now it is Node's turn. Node2Shell, or Broccoli2Shell if you’re feeling leafy - RCE works in lab conditions.

Thumbnail ellio.tech
94 Upvotes

It’s got three names already - Node2Shell, HTTP2Shell, Broccoli2Shell - because of course it does. Whatever you call it, same compression bug, different runtime: PHP patched its pre-auth RCE wave last week, this is ours.

  • This one is quite less theoretical than PHP2Shell - PoC is working in the lab against Node 24.22.0 on x86-64, shell returned as the service account.
  • Meanwhile a scanner is already out there fingerprinting which hosts decompress Brotli - building the hit list before the exploit goes wide.
  • Patch to 22.23.4 / 24.22.1 / 26.12.1.

r/node • • 1h ago

libtmux-ts 0.1 - tmux library for Node.js, TypeScript, bun

Thumbnail github.com
• Upvotes

r/node • • 10h ago

Best practices for OpenAPI spec generation + validation with express.js?

6 Upvotes

I've recently started a TypeScript Express.js project and while I'm familiarizing myself, I'm struggling to know what the best way to support OpenAPI spec generation and how to streamline endpoint parameter validation.

For example, with Django & Django Rest Framework, you define your API endpoints, what they receive and return, and parameters are automatically validated and you can even generate OpenAPI specs from them with another library.

For Express, I'm seeing solutions like JSDoc, which require you to write specs in comments above function definitions, or express-openapi-validator, which require you to maintain the endpoints and spec separately, but performs the validation. I see tools for generating route code, but not vice versa.

Am I approaching this from the wrong angle? I really like having my source of truth lie in the actual code for an endpoint, with specs/validation coming from that definition, not the other way around. What packages/solutions do you recommend for this?


r/node • • 15h ago

I built a self-hosted OpenID Connect server: one container + Postgres, many tenants (release candidate)

Post image
0 Upvotes

I've been building Odudu, an OIDC / OAuth 2.0 server you can run yourself, and the first release candidates are out.

What it is:

one container plus PostgreSQL. Many tenants on one server, kept apart by the database itself. Passkeys, TOTP and recovery codes. Refresh tokens that rotate. Client credentials and token exchange for machines and agents. Per-tenant theming. An admin API and a console. An audit trail. An MCP server so an AI agent can use the admin API as tools, held to the same permissions.

What it is not (yet):

it has had no independent security review, and there is no SAML, LDAP or social login. The roadmap page lists what is planned and what was decided against.

Try it in a minute (Docker + curl):

curl -fsSLO https://github.com/wizzywit/odudu/releases/download/v0.1.0-rc.3/compose.yaml && docker compose up -d && docker compose logs setup

Repo: https://github.com/wizzywit/odudu

Docs: https://wizzywit.github.io/odudu/docs/

AGPL-3.0 for the server, Apache-2.0 for the guides and examples. I'd value blunt feedback: what would stop you trying it, and what is missing for your setup?


r/node • • 1d ago

Typescript Mock Interviews

Thumbnail
0 Upvotes

r/node • • 2d ago

reconnect logic for a node websocket client that filters posts by trading pair

2 Upvotes

Websocket clients that run for days have one problem nobody mentions in the readme. The socket drops every few hours, and when it comes back there’s no way to tell if posts were replayed or skipped. Most small bot repos just reconnect and hope.

One filter project on binance square shows the issue well. Binance has no public api for it, so the data comes from the client in the 1322io repo, where every message has a coin_pairs field. The filter checks if the list contains a pair like SOLUSDT and drops the rest, so no text parsing is needed. Reconnects are the weak spot, since logging post ids to a file is the only protection against duplicates and it was never tested properly.

For anyone who has built on a feed with no replay option, do you dedupe by post id or keep a last seen timestamp? And how do you test a reconnect without waiting for the socket to drop on its own?


r/node • • 2d ago

TIL jest.useFakeTimers() doesn't freeze your tests at a fixed date. it freezes them at right nowjest.useFakeTimers() freezes time at today, so your "deterministic" test still depends on the date

0 Upvotes

til the hard way: jest.useFakeTimers() freezes the clock, but at the current time. unless you call setSystemTime, your test still runs on today's date, it just looks deterministic. vitest does the same.

why i care: i made a cli that skips tests that already passed on the exact same code. tests that read the real clock break that idea, because they can pass today and fail next month on the same commit (a token that expires in 30 days, a date that's now in the past). so the tool watches which tests read the clock, and those passes only count until midnight.

i'd assumed fake timers were safe and let them through. they weren't. now it counts them too, unless the test sets a fixed time.

fixing it took me through some fun node internals, including node's own mock.timers breaking when i touched Date the wrong way. happy to go into that in the comments if anyone's curious.

do you freeze time in every test, or let some of them read the real clock?


r/node • • 2d ago

npmpulse: a new website to query npm package downloads data

Thumbnail
0 Upvotes

r/node • • 3d ago

Recently got a PR merged into TanStack Query

Thumbnail
3 Upvotes

r/node • • 4d ago

Google released patch for node22 0-day at 18:45 UTC

35 Upvotes

r/node • • 4d ago

Evolution Of HTTP: An Interactive Guide

Thumbnail prateeksurana.me
18 Upvotes

r/node • • 3d ago

I added more RAM to my server because I forgot where I put setInterval()

0 Upvotes

I’ve been building a small invoice reminder app after work. It had six users, including me, and was running as a Node app on serverspace cloud server.

One evening I noticed the memory usage slowly climbing. Restarting the app fixed it, but only for about half an hour.

I did what any tired developer would do and decided the infrastructure was the problem.

I added more ram.

The next morning, the memory was climbing again.

After going through the logs I finally found a setInterval() inside a function that ran whenever someone logged in. Every login started another background job to check for overdue invoices. None of the old ones ever stopped.

There wasn’t a sudden increase in users. There were just dozens of copies of my reminder job quietly running at the same time.

I moved the timer out of the login flow, restarted the app and returned the server to its original configuration. The memory graph has been almost completely flat since then.

The app didn’t need more ram. It needed me to stop creating immortal timers


r/node • • 4d ago

Next.js isr behaviour related confusion

Thumbnail
1 Upvotes

r/node • • 6d ago

PortFox - A lightweight CLI to find, inspect, and manage ports in use

Post image
86 Upvotes

Hey everyone,

PortFox 🦊 is a lightweight, open-source CLI that makes managing occupied ports simple.

No more manually searching for PIDs or figuring out which process is blocking your development server.

Features:

  • Find which process is using a specific port
  • List active TCP listening ports
  • Safely terminate processes with confirmation
  • Interactive terminal interface
  • Find available ports
  • JSON output for scripts and automation

Zero npm dependencies. Built with Node.js and supports macOS, Linux, and Windows.

Try it instantly:

npx portfox 3000

Or install it globally:

npm install -g portfox

 GitHub: https://github.com/merdanturan/portFox

 npm: https://www.npmjs.com/package/portfox

MIT licensed and open to contributions.

Feedback, suggestions, and contributions are welcome!


r/node • • 7d ago

Mimic: an MIT-licensed, self-hosted alternative to WebContainers for running Node.js in the browser

Thumbnail github.com
20 Upvotes

Mimic runs Node.js projects in a browser tab, similar to WebContainers but MIT-licensed and self-hosted. Programs run in Web Workers over an in-memory file system, real npm, pnpm and Yarn install from the registry, and a server's port becomes a URL you can load in an iframe.

It runs WASI Preview 1 executables as regular processes and implements node:wasi.

The playground has Vite, Angular, SvelteKit, Astro, Rspack and NestJS examples, and can open a public GitHub repo.

Repo: https://github.com/mimic-js/mimic


r/node • • 6d ago

Extensions privacy doubt

0 Upvotes

Any of us love the extensions, sure. A lot of us are real dev, somebody deeply, and obviously we love to share scripts and ideas, it's like a form of art for people like me.

Probably it is a silly idea but it is the same problem of supplies chain for dev software web and videogames for me, and I resolve with drastic solutions.

So...

If I could accept a "trust me bro" level for a simple idea, in something like agents, mail clients, calendars, note online (so, private data), debits cards... What are your parameters or checklist to understand "*ok, I have no problem with privacy about this extension*"?

Who really checks them? No one.

I think so... Do you have a personal checklist to make sure you've got them all ok?


r/node • • 8d ago

What’s your experience with SST.dev or Pulumi?

15 Upvotes

I’m working on a personal project, so 0 users, and I have worked with SST in the past, but having to upgrade SST was a pain. Not sure if pulumi is any different of an experience, or is less painful and wanted insight on different experiences with either tool


r/node • • 8d ago

How to Implement a Distributed Recovery Ramp in JavaScript

Thumbnail blog.gaborkoos.com
4 Upvotes

r/node • • 7d ago

Show Dev: Aegis//Agent – Secure Transaction Proxy & Compliance Layer for AI Bots (With M-Pesa & Crypto SDK)

1 Upvotes

Hey everyone,

I've been building a transaction-level firewall named Aegis//Agent to solve a critical issue: giving autonomous AI agents access to real money without risking catastrophic, runaway API loops or unchecked wallet drains.

The core architecture intercepts traffic, handles a micro-toll structure (currently configured at 1.00 KSh per task), and routes analytics straight to a live monitoring dashboard.

* Live Production Dashboard: https://aegis-agent-4u79.onrender.com (Note: Deployed on Render's free tier, so please give it about 50 seconds to spin up if it's currently sleeping!)

* Official GitHub SDK Repository: https://github.com

I just open-sourced the lightweight JavaScript SDK client file so other developers can test plugging their systems right into the compliance engine. I would love some brutal feedback from the developer community on the proxy architecture and the local M-Pesa/Crypto routing logic.

Check it out and let me know your thoughts!


r/node • • 8d ago

How to make use a temporary email service to send emails using nodemailer?

3 Upvotes

I am currently building the email verification part of an express server but can't get the service to use a temporary email to send a mail. Following is the code and error. I am also using mailtrip.io for SMTP and used xeramail.com for the mail address to send from.

Now I don't know if I need mailtrip too on top of nodemailer or not but it provides the things I need to use such as usernamw and password.

import { createTransport } from "nodemailer";
import { log_nm_working, subjectBody } from "../strings.js";


// // Create a transporter using SMTP
// const transporter = createTransport({
//   host: "smtp.example.com",
//   port: 587,
//   secure: false, // use STARTTLS (upgrade connection to TLS after connecting)
//   auth: {
//     user: process.env.SMTP_USER,
//     pass: process.env.SMTP_PASS,
//   },
// });


// Todo Currently using the mail for testing puropses from mailtrap.io . It will change later on.
const transporter = createTransport({
  host: process.env.SMTP_HOST,
  port: Number(process.env.SMTP_PORT),
  secure: false, // use STARTTLS (upgrade connection to TLS after connecting)
  auth: {
    user: process.env.SMTP_FROM,
    pass: process.env.SMTP_PASS,
  },
});


export async function sendVerificationEmail(email, url) {
  try {
    await transporter.verify();
    console.log(log_nm_working);
    console.log(process.env.SMTP_FROM);
    console.log(process.env.SMTP_PASS);
    var { ver_body, ver_subject } = subjectBody(url);


    await transporter.sendMail({
      from: process.env.SMTP_FROM,
      to: email,
      subject: ver_subject,
      html: ver_body,
      text: `Verify your email: ${url}`,
    });
  } catch (err) {
    console.error("Verification failed:", err);
  }
}

Verification failed: Error: Invalid login: 535 5.7.0 Invalid credentials
    at SMTPConnection._formatError (file: ///home/app/servers/app/node_modules/nodemailer/dist/esm/smtp-connection/index.js:914:19)
    at SMTPConnection._actionAUTHComplete (file: ///home/app/servers/app/node_modules/nodemailer/dist/esm/smtp-connection/index.js:1758:34)
    at SMTPConnection.<anonymous> (file: ///home/app/servers/app/node_modules/nodemailer/dist/esm/smtp-connection/index.js:612:26)
    at SMTPConnection._processResponse (file: ///home/app/servers/app/node_modules/nodemailer/dist/esm/smtp-connection/index.js:1143:20)
    at SMTPConnection._onData (file: ///home/app/servers/app/node_modules/nodemailer/dist/esm/smtp-connection/index.js:859:14)
    at SMTPConnection._onSocketData (file: ///home/app/servers/app/node_modules/nodemailer/dist/esm/smtp-connection/index.js:178:44)
    at TLSSocket.emit (node:events: 509: 28)
    at addChunk (node:internal/streams/readable: 563: 12)
    at readableAddChunkPushByteMode (node:internal/streams/readable: 514: 3)
    at Readable.push (node:internal/streams/readable: 394: 5) {
  code: 'EAUTH',
  response: '535 5.7.0 Invalid credentials',
  responseCode: 535,
  command: 'AUTH PLAIN'
}

r/node • • 9d ago

I threw 6,500 disguised swear words at the popular npm profanity filters. The best one caught 28% and also blocked Fukushima

44 Upvotes

I needed a profanity check for usernames and chat. Like everyone else, I started by installing a filter from npm. Then I got curious and built a proper test set: about 6,500 swears in disguise (leetspeak, look-alike letters from other alphabets, zero-width characters, f.u.c.k with dots in it, full-width letters, and so on), plus 505 completely innocent texts that happen to contain a bad string.

I ran four packages on default settings, the way most of us actually use them.

| package | disguised swears caught | innocent texts blocked |

|---|---|---|

| leo-profanity | 1.1% | 8.7% |

| bad-words | 4.4% | 12.5% |

| @2toad/profanity | 4.4% | 11.5% |

| obscenity | 27.9% | 21.2% |

The interesting part is that there are two kinds of failure, and you can only pick one.

Whole-word lists (bad-words, leo-profanity, 2toad) look each word up in a list. Change one character and the word is gone. bad-words caught 3% of leetspeak, 1% of dotted spellings and 0% of full-width letters. `f.u.c.k` passes all four packages.

Substring matchers (obscenity) look inside words, so they catch a lot more. They also catch:

- Fukushima, Fukuoka, Fukui

- Shiitake mushroom

- Fire retardant

- Cockpit

- Penistone and Shitterton (real English places)

- Cummerbund

And then there are the ones every package blocks: "sex education", "anal cancer", "blue tit" (it's a bird), "Moby Dick", "Dick Van Dyke". A word list can't tell a medical question from an insult, because the string is the same.

If you're staying on a list, three things helped more than swapping packages:

  1. Normalize before you match: Unicode NFKC (kills full-width), strip zero-width characters (U+200B to U+200D, U+2060, U+FEFF), and map look-alike letters with a confusables table. Cyrillic `а` and Latin `a` are different characters to your regex.

  2. Collapse separators and repeats inside a token before the lookup, so `f.u.c.k` and `fuuuuck` become `fuck`.

  3. Keep an allow list of the innocent words your list hits, and test it against real place names and surnames, not just the ones you think of.

That gets you part of the way. The rest is the reason I ended up building something.

Disclosure: I make Unprofane, a profanity API that came out of this. On the same test it caught 96.9% of the disguised swears and blocked 0 of 529 innocent texts. The test set is public, so you can run your own filter on it: github.com/unprofane/scunthorpe-test. Full results: unprofane.com/bench

Happy to share the normalization code if anyone wants it.


r/node • • 9d ago

acr-node: render PDF/PNG business reports in Node.js/Electron without Chromium or a subprocess

2 Upvotes

We just released `@acrossreport/acr-node`, a native Node.js/Electron binding (via napi-rs) that renders PDF/PNG reports in-process, backed by a Rust/Skia engine.

Most Node apps generate PDF reports either by launching headless Chromium (Puppeteer) or shelling out to a CLI tool. Both add real overhead. This links the renderer directly into the Node process instead — no Chromium, no subprocess.

- Prebuilt binaries for 6 platforms (Windows/Linux/macOS, x64/ARM64)

- Pixel-identical output across OSes

- Works in a bare Node server or an Electron main process

Write-up: https://dev.to/maskedridersystem/rendering-pdfpng-reports-in-nodejs-without-chromium-or-a-subprocess-napi-rs-b4

npm: https://www.npmjs.com/package/@acrossreport/acr-node

Repo: https://github.com/acrossreport/acr-node

Happy to answer questions about the implementation.


r/node • • 9d ago

yq.rs ported to Rust to use with JavaScript via WASM

0 Upvotes

I ported yq to Rust so that it can be used in Node via WASM. You can install the package via npm install yq.rs or run it via npx yq.rs


r/node • • 10d ago

pboss vs pm2 on Node: cluster mode is a blowout, and the fork-mode "losses" are noise

7 Upvotes

We ran pboss 1.8.0 against pm2 5.4.3 on Node 24. Same server.mjs, same binary, same machine, same autocannon profile (10/100/500 connections, 60s, 5 repeats). Cold start of the whole manager stack every run, manager order alternating, CPU and RAM sampled across the entire process tree. The numbers below measure the cost of managing a server, not Node's raw HTTP performance.

Cluster mode: pboss wins almost every row

Both managers cluster Node apps natively through node:cluster, same worker count, same sharing mechanism. The only variable is the manager itself. And under that fair fight pboss pulls away at every load level.

100 connections, 2 workers:

Metric pm2 pboss
req/sec 55,954 58,539 (+4.6%)
latency (mean) 1.25 ms 1.18 ms (-5.6%)
p90 latency 4 ms 3 ms (-25%)
RPS stdev 1,355 660 (-51%)
CPU (tree) 76.0% 75.3%
cold start 624 ms 427 ms (-32%)

At 10 connections pboss is still ahead: median RPS +5.6%, p99 latency 2ms vs 3ms. At 500 connections it holds: +1.7% mean RPS, better latency at p50/p90, steadier RPS. Not one row of lost throughput. Plus lower CPU across the board.

Crash recovery and restart storms, where "production ready" actually gets decided

  • SIGKILL the whole fork-mode server: pboss brings /health back to 200 in 68ms median vs 128ms for pm2. Worst case across all runs: 70ms vs 194ms.
  • SIGKILL one of two cluster workers: pboss respawns it in 93ms vs 151ms, worst case 103ms vs 199ms. /health never dropped on either, as it shouldn't with a survivor holding the port.
  • 50-restart storm, fork: median restart 181ms vs 376ms (52% faster). Zero failures, zero orphans on both sides. But the app RSS after the storm: 58MB for pboss vs 71MB for pm2, and pboss's memory shrank 0.3MB over the storm while pm2's grew.
  • 50-restart storm, cluster: 300ms vs 498ms (40% faster), workers' RSS around 20% lower, growth of -0.1MB vs +1.6MB. Again zero failures, zero orphans.

Faster recovery, tighter memory, no leaks under punishment. Fifty restarts later the tree is clean.

Startup time deserves its own section honestly

Metric pm2 pboss
cold, fork 520 ms 396 ms
warm, fork 270 ms 174 ms
cold, cluster 637 ms 419 ms
warm, cluster 422 ms 242 ms

Warm cluster restarts are 43% faster. For anyone doing rolling deploys or watch-mode dev, that adds up all day.

Fork mode: mostly pboss, and here's the scoreboard

Fork mode at 100 connections, one managed process:

Metric pm2 pboss
Median req/sec 56,278 57,517 (+2.2%)
Mean req/sec 57,512 57,519 (tie)
RPS stdev 2,696 1,180 (-56%)
latency (mean) 1.44 ms 1.40 ms (-2.8%)
p50 latency 1.00 ms 1.00 ms (tie)
p90 latency 1.00 ms 1.00 ms (tie)
p99 latency 26.00 ms 26.00 ms (tie)
CPU avg (tree) 73.9% 74.0% (+0.1%)
CPU peak (tree) 79.6% 78.8% (-1.0%)
memory avg (tree) 179.1 MB 168.3 MB (-6.0%)
memory median (tree) 184.3 MB 174.2 MB (-5.5%)
cold start 520 ms 395 ms (-24%)
errors / timeouts / non-2xx 0 / 0 / 0 0 / 0 / 0

Clean sweep where it counts: tied throughput at the mean, +2.2% at the median, RPS stdev cut in half, 6% less memory, 24% faster cold start. The only row pm2 takes is average CPU by 0.1%, which is a tie wearing a mustache.

Across the other load levels it's the same story: pboss uses 2 to 8% less tree memory and starts 23 to 26% faster at every one.

Where pm2 actually beat us

Two-ish rows, and they're small:

  • At 10 connections (a nearly idle server) pm2's median RPS was 1.5% higher and its RPS spread was tighter. On a box where the load generator shares the CPUs, that's inside the noise.
  • At 500 connections, fork mode, pm2's median RPS was 1.2% higher and mean latency 1.9% better (8.58ms vs 8.74ms). Mixed row, tiny margins both ways.
  • Cluster mode tree memory is 11% higher under pboss. This one is real and it's architectural: pboss runs a supervised wrapper primary above the workers, so there's one more small process in the tree. You buy it back in startup speed (30 to 35% faster) and respawn speed (38 to 48% faster). Idle daemon memory is actually 5% lower than pm2's.

That's the honest list. Everything else across the whole report goes to pboss.

Everything around it

Health checks, cron restarts, log rotation with gzip, web dashboard, Prometheus /metrics, namespaces, dependency-ordered startup, replace-first rolling reloads. Built directly on node:child_process, node:http, node:fs. Open source, GPLv3.

Don't take our word for it. Every number traces to a raw file in results/raw/, the load generator shared CPUs with the servers so compare the columns rather than quoting absolutes, and the benchmark script is three commands:

cd benchmarks/node && npm install
bash scripts/benchmark.sh

Rerun it on your own hardware and tell us what changes.


r/node • • 11d ago

Asking about CommonJS, ESM and the Node.js event loop

15 Upvotes

Hi everyone

I just started learning Node.js just a few hours ago, and I'm really confused (wanted to cry too). Could someone help me clarify a few things?

After I initialized a Node.js project, I see the following in package.json:

"type": "commonjs"

Then I run this code:

console.log('sync');
process.nextTick(() => console.log('nextTick'));
Promise.resolve().then(() => console.log('promise'));

The output is:

sync
nextTick
promise

Then I installed TypeScript and executed the same code again, but in a .ts file. This time, the output is:

sync
promise
nextTick

Interestingly, I get the same output when I set "type": "module" in package.json.

So I asked ChatGPT:

1. Does the TypeScript compiler change the execution order to behave like an ES module?

ChatGPT answered:

"Your tsx example produced ESM-style ordering, but you shouldn't assume every tsx file or situation will behave the same way."

Now I'm even more confused! Could someone help me clarify this?

ChatGPT's answer seems that the output when using TypeScript with CommonJS does not necessarily match the output of either CommonJS or ESM....

I also have a few related questions about the Node.js event loop:

2. As far as I know, the Node.js event loop has several phases, including:

1. Timers (setTimeout callback)

2. Poll (I/O-related callbacks, such as reading files or receiving network data)

3. Check (setImmediate callback)

Is this correct? If so, which phase runs first?

3. Are Promise callbacks handled separately from the Node.js event loop? Is the following execution sequence correct?

1. Drain the process.nextTick() queue.
2. Drain the Promise microtask queue.
3. Execute the next event loop callback (setTimeout, readFile, setImmediate, etc.)

4. Back to 1