Skip to content

Core 03 os

Core 03 - OS Module

Basic Idea

You need to know what machine your code is running on CPU cores for worker pool sizing , memory for cache limits , network interfaces for binding os module gives you all the system-level intel without writing platform-specific shell commands

System Information

const os = require('os')

// CPU - for sizing thread pools
const cpus = os.cpus()
console.log('CPU count:', cpus.length)
console.log('Model:', cpus[0].model) // e.g., AMD Ryzen 9 7950X
console.log('Speed:', cpus[0].speed, 'MHz')

// Memory
console.log('Total RAM:', os.totalmem() / 1024 / 1024 / 1024, 'GB')
console.log('Free RAM:', os.freemem() / 1024 / 1024 / 1024, 'GB')
console.log('Used:', (os.totalmem() - os.freemem()) / 1024 / 1024 / 1024, 'GB')

cpus() returns an array with info for each logical core - including hyperthreads Don't confuse logical cores with physical cores If you're spawning workers , os.cpus().length is your upper bound

User and System Directories

// home directory - usually /home/user on Linux
console.log('Home:', os.homedir())
// /home/mahmoud

// temp directory - for ephemeral files
console.log('Temp:', os.tmpdir())
// /tmp

// hostname - useful for logging and distributed tracing
console.log('Hostname:', os.hostname())
// kali-2025

homedir() reads the HOME environment variable On Windows it reads USERPROFILE - which might not exist in all contexts like Windows services tmpdir() follows the OS convention - /tmp on Linux , %TEMP% on Windows

Platform Identification

console.log('Platform:', os.platform()) // linux, darwin, win32
console.log('Arch:', os.arch())         // x64, arm64, ia32
console.log('Release:', os.release())   // 6.8.0-45-generic

// practical - conditional logic per platform
switch (os.platform()) {
  case 'linux':
    // use /dev/null or /proc
    break
  case 'win32':
    // use NUL or %SystemRoot%
    break
  case 'darwin':
    // macOS stuff
    break
}

os.platform() returns one of: 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos', 'win32' Don't confuse with process.arch which returns 'x64' , 'arm64' , etc

User Info and Network Interfaces

// user info - username , uid , gid , shell , homedir
const user = os.userInfo()
console.log('Username:', user.username)
console.log('UID:', user.uid)
console.log('Shell:', user.shell) // /bin/bash

// network interfaces
const nets = os.networkInterfaces()
for (const [name, addrs] of Object.entries(nets)) {
  console.log(`Interface ${name}:`)
  for (const addr of addrs) {
    if (addr.family === 'IPv4') {
      console.log(`  ${addr.address}/${addr.netmask}`)
    }
  }
}

networkInterfaces() returns internal network topology - every adapter and every address Good for finding which IP your service should bind to Careful with userInfo() - it leaks system usernames which are often reused across services

Uptime and Load

// system uptime in seconds
console.log('Uptime:', os.uptime(), 'seconds')
console.log('Uptime:', Math.floor(os.uptime() / 3600), 'hours')

// load averages - 1, 5, 15 minutes
const [one, five, fifteen] = os.loadavg()
console.log(`Load: ${one.toFixed(2)} / ${five.toFixed(2)} / ${fifteen.toFixed(2)}`)

loadavg() returns the traditional Unix load averages On Linux these include all processes - not just CPU bound ones A load of 16 on a 8-core machine means the system is slammed On Windows this returns [0, 0, 0] because Windows doesn't have load averages - good luck

Endianness and Priority

// byte order - BE or LE
console.log('Endianness:', os.endianness())
// LE on virtually everything you'll touch

// process priority - only on POSIX systems
os.setPriority(0, -10) // lower nice value = higher priority
console.log('Current priority:', os.getPriority(0))

Most developers will never touch endianness until they interface with binary protocols or hardware setPriority(0, ...) modifies the current process Negative values require root or appropriate capabilities

Security Sensitive APIs

// os.userInfo() exposes system usernames
const { username } = os.userInfo()
// If your app crashes and dumps this into logs + error messages
// that's a username leak - combine with path traversal for exploitation

// os.networkInterfaces() shows internal IP topology
const ifaces = JSON.stringify(os.networkInterfaces(), null, 2)
// Don't expose this in API responses unless you want to help attackers map your internal network

userInfo() and networkInterfaces() are common information disclosure vectors Never expose raw OS module output in error messages , debug endpoints , or logs A /debug route that returns os.networkInterfaces() is basically a free recon pass for attackers

Summary

  • cpus().length for worker pool sizing
  • platform() and arch() for conditional code paths
  • freemem() and loadavg() for health checks
  • Never expose userInfo() or networkInterfaces() in API responses

Prerequisites

next -> core_04_events.md