AgentStack
SKILL unreviewed MIT Self-run

Nodejs

skill-xobotyi-cc-foundry-nodejs · by xobotyi

>-

No reviews yet
0 installs
17 views
0.0% view→install

Install

$ agentstack add skill-xobotyi-cc-foundry-nodejs

Open-source listing — not yet scanned by AgentStack. Follow the source repository for install instructions.

Security review

⚠ Flagged

1 finding(s); flagged for manual review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures
  • high Dangerous shell/eval execution.

What it can access

  • Network access No
  • Filesystem access Used
  • Shell / process execution Used
  • Environment & secrets Used
  • Dynamic code execution Used

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Nodejs? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Node.js

Respect the event loop. Every blocking operation is a scalability bug.

Node.js rewards async-first, stream-oriented code. If your Node.js code fights the event loop, it's wrong.

References

  • Module system — [${CLAUDE_SKILL_DIR}/references/modules.md]: ESM/CJS comparison tables, file extension rules,

conditional exports patterns

  • Event loop — [${CLAUDE_SKILL_DIR}/references/event-loop.md]: Phase order, execution priority, blocking

operations table, worker pool

  • Streams — [${CLAUDE_SKILL_DIR}/references/streams.md]: Stream types table, pipeline patterns, backpressure

details

  • Error handling — [${CLAUDE_SKILL_DIR}/references/errors.md]: Error categories table, global handlers,

centralized error handling

  • Security — [${CLAUDE_SKILL_DIR}/references/security.md]: Supply chain threats table, HTTP security headers,

process hardening

Module System

  • Use ESM. Set "type": "module" in package.json. Use .mjs/.cjs only when mixing module systems within one

package.

  • Use node: prefix for all built-in imports: import fs from 'node:fs'. Prevents package name collision attacks

and is unambiguous.

  • Import process explicitly. import process from 'node:process'. Never rely on the process global — explicit

imports make dependencies visible.

  • Define "exports" in package.json for libraries. Encapsulates internals — only paths listed in "exports" are

importable by consumers.

  • Imports at module top. No dynamic import() for statically-known dependencies.
  • Use import.meta.dirname/import.meta.filename instead of __dirname/__filename.
  • Use import.meta.resolve() instead of require.resolve() in ESM.
  • Always set "type" explicitly in package.json, even in CJS packages — future-proofs the package and helps

tooling.

  • Use conditional exports for dual CJS/ESM packages. Order: types > import > require > default. Always

include "default" as fallback.

  • Place "types" first in conditional exports when publishing TypeScript declarations.
  • Use # imports ("imports" in package.json) for clean internal paths without ../../../. Supports conditional

resolution for platform-specific implementations.

  • Keep "main" alongside "exports" only for backward compatibility with old Node.js or bundlers. Never use

"main" alone for new packages.

  • JSON imports in ESM require with { type: 'json' } attribute.
  • Use createRequire() from node:module only when you must require() in ESM (e.g., native addons).
  • CJS interop: default import from CJS always works. Named imports work if CJS uses static export patterns;

otherwise destructure the default.

  • require() can load synchronous ESM (no top-level await). For ESM with top-level await, use dynamic

import().

  • Self-referencing: a package can import its own exports by name when "exports" is defined.

File extension rules and ESM vs CJS comparison tables: see ${CLAUDE_SKILL_DIR}/references/modules.md.

Event Loop

Node.js uses a single-threaded event loop for JavaScript and a libuv worker pool for expensive I/O and CPU tasks.

Core Rules

  • Never block the event loop. No sync I/O in servers (readFileSync, execSync, crypto.pbkdf2Sync,

zlib.inflateSync). Sync APIs are acceptable only in CLI scripts, startup code, or build tools.

  • Offload CPU-intensive work to worker_threads or child processes. For main-thread CPU work, partition into chunks

with setImmediate() between iterations.

  • Bound input sizes. Unbounded JSON.parse, JSON.stringify, regex, or iteration = DoS vector. A 50MB JSON string

blocks the loop for ~2 seconds.

  • Avoid vulnerable regex. No nested quantifiers (a+)*, no overlapping alternations (a|a)*, no backreferences

with repetition. Use safe-regex2, RE2, or indexOf.

  • Prefer setImmediate() over recursive process.nextTick(). nextTick starves I/O if called recursively. Use

nextTick only when you must run before any I/O in the current tick (e.g., emitting events after construction before listeners attach).

  • Prefer queueMicrotask() over process.nextTick() for new code — it's cross-platform and web-standard.
  • Inside I/O callbacks, setImmediate always fires before setTimeout(fn, 0). Outside I/O, the order is

non-deterministic — do not depend on it.

  • Use AbortController for cancellable timers and operations.

Phase order, execution priority, blocking operations table, and worker pool details: see ${CLAUDE_SKILL_DIR}/references/event-loop.md.

Streams

Streams process data incrementally — use them for large files, HTTP bodies, data transformation pipelines, and proxying. Do not use streams when data is already fully in memory.

Core Rules

  • Use pipeline() from node:stream/promises for stream composition. Never manual .pipe() chains — they don't

propagate errors or handle cleanup.

  • Respect backpressure. Check .write() return value; wait for 'drain' event before continuing. pipeline()

handles this automatically.

  • Prefer Readable.from() for converting iterables/async iterables to streams.
  • Use async iteration (for await (const chunk of stream)) as the simplest way to consume readable streams.

Backpressure is handled automatically.

  • Use readline with createInterface for line-by-line file processing.
  • highWaterMark defaults to 16 KiB for byte streams, 16 objects for object mode. It's a hint, not a hard limit.
  • Object mode streams count objects (not bytes) against highWaterMark. Enable with { objectMode: true }.
  • Destroy streams explicitly when you need to abort: stream.destroy(new Error('msg')).
  • Custom Readable: prefer async generators with Readable.from() over class-based _read() implementation unless

you need fine-grained control.

  • Custom Transform: implement _transform(chunk, encoding, callback) and optionally _flush(callback) for

end-of-stream processing.

  • Custom Writable: implement _write(chunk, encoding, callback) and optionally _final(callback) for cleanup

before 'finish' event.

Stream types table and .pipe() pitfalls: see ${CLAUDE_SKILL_DIR}/references/streams.md.

Error Handling

Core Rules

  • Use async/await with try/catch. No callbacks for new code.
  • Always return await when returning promises from try blocks — preserves full stack traces and ensures catch

fires for rejections.

  • Extend Error. Custom errors must extend Error, set a code property for programmatic matching (not message

strings, which change), and set name.

  • Use error.cause for chaining: new Error("context", { cause: originalErr }). The full chain is visible via

util.inspect() and structured loggers.

  • Match errors by error.code or instanceof, never by message string.
  • Register global handlers. Always handle process.on('unhandledRejection') and process.on('uncaughtException').

Log, clean up, exit. Since Node.js 15+, unhandled rejections crash the process by default.

  • Never resume after uncaughtException. The process state is unknown — log, cleanup, exit.
  • Subscribe to 'error' events on all EventEmitters and streams. An unhandled 'error' event crashes the process.

pipeline() handles stream errors automatically.

  • Handle process.on('warning') for non-fatal process warnings (deprecations, memory leaks, experimental features).
  • Use centralized error handlers. Don't scatter error handling across every middleware. Use a single error handler

that maps error types to HTTP responses without leaking internals.

  • Handle once: log OR throw, not both. catch (e) { log(e); throw e } causes duplicate logging.
  • Never swallow errors in event handlers — always re-emit or log.

Error categories table and operational vs programmer error strategies: see ${CLAUDE_SKILL_DIR}/references/errors.md.

Process Lifecycle

  • Graceful shutdown. Handle SIGTERM/SIGINT: stop accepting connections, wait for in-flight requests (with

timeout), close DB pools, flush logs, then process.exit(0). Force-exit on timeout.

  • Log to stdout/stderr. Let infrastructure (Docker, systemd) handle log routing. Use structured JSON logging (pino,

winston) in production.

  • Set NODE_ENV=production in production. It enables framework optimizations and disables debug output.
  • Use npm ci in CI/production. Never npm install — it ignores lockfile mismatches.

Security

Input Validation

  • Validate everything from outside — request bodies, query params, headers, file uploads, environment variables from

untrusted sources. Use schema validation (zod, ajv, typebox).

  • Limit request body size at the HTTP layer before parsing. Set per-content-type limits. Unbounded payloads exhaust

memory.

  • Validate Content-Length header before reading the body.
  • Use streaming JSON parsers (stream-json, @streamparser/json) for very large JSON payloads.

HTTP Security

  • Configure server timeouts. Defaults are too permissive. Set headersTimeout, requestTimeout, timeout,

keepAliveTimeout, maxRequestsPerSocket.

  • Use security headers (via helmet or equivalent): Strict-Transport-Security, X-Content-Type-Options: nosniff,

X-Frame-Options: DENY, Content-Security-Policy.

  • Delegate TLS/gzip to reverse proxy. Node.js should not terminate TLS or compress responses in production — let

nginx/HAProxy/cloud LB handle TLS termination, compression, rate limiting, and WAF rules.

Secrets & Process Hardening

  • Never hardcode secrets in source code. Use environment variables from secure vaults.
  • Never commit .env files — add to .gitignore.
  • Use crypto.timingSafeEqual() for secret comparison (prevents timing attacks).
  • Use crypto.scrypt() or crypto.pbkdf2() (async versions) for password hashing.
  • Avoid shell injection. Never use exec() with user-controlled strings. Use execFile() or spawn() with

argument arrays.

  • Never use eval(), new Function(), or dynamic require() with user input.
  • Run as non-root in Docker — use a dedicated user.
  • Limit V8 heap with --max-old-space-size to prevent memory exhaustion.

Supply chain threats table, dependency auditing, and security checklist: see ${CLAUDE_SKILL_DIR}/references/security.md.

Application

When writing Node.js code:

  • Apply all conventions silently — don't narrate each rule being followed.
  • If an existing codebase contradicts a convention, follow the codebase and flag the divergence once.
  • Prefer node:fs/promises over callback-based node:fs.
  • Prefer node:stream/promises for pipeline operations.

When reviewing Node.js code:

  • Cite the specific violation and show the fix inline.
  • Don't lecture or quote the rule — state what's wrong and how to fix it.

Integration

The javascript skill governs language choices; this skill governs Node.js runtime decisions. Activate typescript alongside both when working with TypeScript.

Respect the event loop. When in doubt, make it async.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.