Categories
JavaScript Nodejs

Using the Node.js OS Module — Part 3

The Node.js OS module has many useful utility functions for getting information about the computer system that the OS module’s program is running on. It can get us information about hardware like CPUs, endianness, the home directory, IP address, hostname, the platform the program is running on, system uptime, information about the currently logged in user and more.

We can use the OS module by writing const os = require('os'); at the top of a JS file. There are many useful properties in the OS module. Below are more useful properties in the OS module:

os.release

The os.release function returns a string that identifies the operating system release. On Unix and Linux systems, the function identifies the operating system with the uname command. On Windows, the GetVersionExW() function from the Win32 API is used. For example, if we run:

console.log(os.release());

Then we may get something like:

'4.15.0-1036-gcp'

os.setPriority

The os.setPriority function lets us set the scheduling priority of a process specified by the process ID. It takes 2 arguments. The first is the process ID, which is a whole number that identifies the running process to set the priority to. The default value to 0.

The second argument is the priority, which is a whole number which indicates the scheduling of the process priority we want to set. It ranges from -20 for the highest priority to the lowest which is 19.

Because of the differences between priority levels between Windows and POSIX systems, Node.js provides us with constants that have the levels of priorities for processes.

They’re in the os.constants.priority constant. On Windows, setting the process priority to the PRIORITY_HIGHEST setting requires elevated privileges. If the user that’s running the program doesn’t have elevated privileges, then it will be silently reduced to PRIORITY_HIGH.

The following priority constants are provided by Node.js:

  • PRIORITY_LOW — The lowest process scheduling priority. This corresponds to IDLE_PRIORITY_CLASS on Windows and a nice value of 19 on all other platforms.
  • PRIORITY_BELOW_NORMAL — This corresponds to BELOW_NORMAL_PRIORITY_CLASS on Windows and a nice value of 10 on all other platforms.
  • PRIORITY_NORMAL — The default process scheduling priority. This corresponds to NORMAL_PRIORITY_CLASS on Windows and a nice value of 0 on all other platforms.
  • PRIORITY_ABOVE_NORMAL — This corresponds to ABOVE_NORMAL_PRIORITY_CLASS on Windows and a nice value of -7 on all other platforms.
  • PRIORITY_HIGH — This corresponds to HIGH_PRIORITY_CLASS on Windows and a nice value of -14 on all other platforms.
  • PRIORITY_HIGHEST — The highest process scheduling priority. This corresponds to REALTIME_PRIORITY_CLASS on Windows and a nice value of -20 on all other platforms.

For example, we can use it as in the following code:

os.setPriority(0, os.constants.priority.PRIORITY_LOW)

os.tmpdir

The os.tmpdir function returns a string that specifies the operating system’s default directory for storing temporary files. For example, if we write:

console.log(os.tmpdir());

Then we may get:

'/tmp'

on Linux systems.

os.totalmem

The os.totalmem function returns the total amount of system memory as a number of bytes in integer form. For example, if we run:

console.log(os.totalmem());

Then we may get something like:

27389460480

os.type

The os.type function returns a string that identifies the operating system as returned by the uname command. For example, it may be 'Linux' on Linux, 'Darwin' on macOS, and 'Windows_NT' on Windows. For example, if we run the following:

console.log(os.type());

on a Linux system, then we get ‘Linux’ .

os.uptime

The os.uptime function returns an integer that has the system uptime in number of seconds. For example, if we run:

console.log(os.uptime());

Then we may get something like:

4928

os.userInfo

The os.userInfo function returns an object with information about the currently effective user, which is the user identity that the user is assumed.

This may be different from the currently logged in user since a user can run programs as a different user in multiuser operating systems. On POSIX systems, this is typically a subset of the password file.

The returned object includes the username , uid , gid , shell , and homedir properties. On Windows, the uid and gid are -1, and shell is null .

A SystemError will be thrown if a user has no username or homedir . The value of homedir returned by the os.userInfo function is provided by the operating system.

This is different from the os.homedir function which returns a string of the path o the home directory of the user from various environment variables. On Unix and Linux systems, it will use the $HOME variable if it’s defined.

Otherwise, it will look up the home directory path by the effective UID, which is the user ID of the user identity that you’re currently assuming. For example, if you used sudo to use the computer as a root user then the effective user ID would be the user ID of the root user.

On Windows, the value of the USERPROFILE will be used if it’s defined. Otherwise, it will be the path of the profile directory of the current user.

It takes one argument, which is an object that lets us set the options for calling the function. It can have one property, which is the encoding property, which is a string that indicates the character encoding used to interpret the resulting strings.

The default value is 'utf8' , but it can also be 'buffer' , which will set the change the values of the properties of the returned object to Buffer objects. The argument is optional.

For example, if we run the following code:

console.log(os.userInfo({ option: 'utf8' }));

We may get something like the following:

{ uid: 1000,  
  gid: 1000,  
  username: 'runner',  
  homedir: '/home/runner',  
  shell: '/bin/bash' }

In the output above, the uid is the user identifier, which identifies the user identity that the currently logged in user has assumed, which may be the currently logged in user if it’s running programs as itself, or it can be a different user like the root user if the Node.js program is currently run as root. This is also called the currently effective user.

The gid is the group ID. It’s the identifier that associates a user with other users that share something in common. A user can be a member of one or more groups and may have more than one GID.

The username is the username of the currently effective user. The homedir is the home directory of the currently effective user. The shell is the command-line interpreter that’s currently being used by the currently effective user.

The Node.js OS module has many useful utility functions for getting information about the computer system that the OS module’s program is running on.

The modules have many more properties containing useful information like CPUs, endianness, home directory, IP address, hostname, the platform the program is running on, system uptime, information about the currently logged in user and more. It also lets us set the priority of running processes.

Categories
Express JavaScript Nodejs

Security Best Practices for Using Express Apps in Production

When we use an Express app for production, i.e. it’s used by external users, we have to be careful about security since it’s available to the outside world.

In this article, we’ll look at some security best practices when running Express apps in a production environment.

Don’t Use Outdated Versions of Express

Outdated versions of Express are no longer maintained and may have unpatched security vulnerabilities, leaving our apps at risk for all sorts of attacks.

Use TLS

If we’re transporting data that needs to be secured, we should use TLS so that users’ data is protected. This means that we avoid man-in-the-middle attacks and packet sniffing.

Even our apps don’t transport secure data, it still gives users more confidence that our website is secure.

We can get free TLS certificates with Let’s Encrypt. It’s an automated service that generates new certificates that are trusted by browsers,

Use Helmet

Helmet is a series of Express middlewares to protect our apps with some well-known security vulnerabilities on the web by setting HTTP headers.

The middlewares included with Helment includes:

  • csp — sets the Content-Security-Policy header to help prevent cross-site scripting attacks and other cross-site injections.
  • hidePoweredBy — removes the X-Powered-By header
  • hpkp — adds public key pinning header to prevent man-in-the-middle attacks with forged certificates
  • hsts — sets Strict-Transport-Security header that enforces HTTPS connects to the server.
  • ieNoOpen 0 sets X-Download-Options for IE 8 or later
  • noCache — sets Cache-Control and Pragma header to disable client-side caching
  • noSniff — sets X-Content-Type-Options header to prevent browsers from MIME-sniffing a response away from the declared content type
  • frameguard — sets the X-Frame-Options header to provide clickjacking protection
  • xssFilter — sets X-XSS-Protection to enable cross-site scripting filter in most recent web browsers

It’s a good idea to at least disable the x-powered-by response header so that attackers won’t know that our app is an Express app and launch specific attacks for it.

Use Cookies Securely

We can use the express-session or cookie-session middleware to use cookies securely.

express-session stores session data on the server. It only saves the session ID on the cookie itself.

We can set up a session store for production use since it uses an in-memory store by default.

cookie-session stores the whole cookie on the client-side. We shouldn’t exceed 4093 bytes when we set our cookies.

The cookie data will be visible to the client, so secret data shouldn’t be sent to the client with cookie-session .

Don’t Use Default Session Cookie Name

The default session cookie name set by Express shouldn’t be used since it can identify that an app is running on Express.

We can do this by passing in an object to session as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const session = require('express-session');  
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.set('trust proxy', 1);  
app.use(session({  
  secret: 'secret',  
  name: 'sessionId'  
}))
app.listen(3000);

Set Cookie Security Options

To enhance security, we can set various cookie options. The following options are available:

  • secure — ensures browsers only send cookie over HTTPS
  • httpOnly — ensures cookie is sent only over HTTP(S) and not client-side JavaScript. This helps us prevent XSS attacks
  • domain — indicates the domain of the cookie, which can be used to compare against the domain of the server in the URL that’s requesting the cookie.
  • path — indicates the path to compare against the requested path, then send the cookie in the request
  • expires — set the expiration date for persistent cookies.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');  
const session = require('express-session');  
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));  
const expiryDate = new Date(Date.now() + 60 * 60 * 1000)  
app.use(session({  
  name: 'session',  
  secret: 'secret',  
  keys: ['foo', 'bar'],  
  cookie: {  
    secure: true,  
    httpOnly: true,  
    domain: 'EnormousBeneficialScript--five-nine.repl.co',  
    path: '/',  
    expires: expiryDate,  
  }  
}));
app.get('/', (req, res) => {  
  req.session.foo = 'foo';  
  res.send(req.session.foo);  
})
app.listen(3000);

Prevent Brute-Force Attacks

We can rate limit our authorization routes so that attackers can’t use brute-force attacks to guess the credentials stored in our app’s database.

For example, we can limit by IP address by limiting the number of failed attempts that people can make if they have the same user name and IP address.

Then we lock out the user for some time if the number of failed attempts what we can tolerate.

If more than 100 failed attempts in a day are made then we block the IP address.

We can use the rate-limiter-flexible package to do rate-limiting of our routes.

Conclusion

To keep our Express app secure in a production environment, we should take a few precautions.

First, we should use TLS for transporting data to keep them from being sniffed and prevent man-in-the-middle attacks.

Next, we should set headers in ways that prevent users from finding information about our app and to enforce secure communication.

Also, we should use cookies securely by signing it with a secret and set the security options for them.

Finally, to prevent brute-force attacks, we should set a rate limit for our API calls so that attackers can’t guess our users’ credentials by repeated login attempts.

Categories
JavaScript Nodejs

Using the Node.js OS Module — Part 2

The Node.js OS module has many useful utility functions for getting information about the computer system that the OS module’s program it is running on. It can provide information about hardware like CPUs, endianness, the home directory, IP address, hostname, the platform the program is running on, system uptime, information about the currently logged in user and more.

We can use the OS module by writing const os = require('os'); at the top of our code. There are many useful properties in the OS module. Below are more useful properties in the OS module:

os.cpus

The os.cpus() function returns an array of objects that has various information about each logical core of the host computer’s CPU. Each entry has a few properties. There’s the model property, which is a string that indicates the model of the computer’s CPU. The speed property is a numeric property that is measured in megahertz. The times property is an object with the following properties:

  • user — a numeric property that indicates the number of milliseconds the CPU has spent in user mode.
  • nice — a numeric property that indicates the number of milliseconds the CPU has spent in nice mode. Nice mode is where the CPU is running processes that have a positive nice value, which means a process that’s a lower priority.
  • sys — a numeric property that indicates the number of milliseconds the CPU has spent in sys mode.
  • idle — a numeric property that indicates the number of milliseconds the CPU has spent in idle mode. A CPU is idle when it’s not used by any program.
  • irq— a number property the number of milliseconds the CPU has spent in IRQ mode. IRQ is a hardware signal that makes the CPU temporarily stop a running program and allow an interrupt handler program to run instead.

For example, we can use the function like the following:

console.log(os.cpus());

We can get the output that resembles the following:

[ { model: 'Intel(R) Xeon(R) CPU @ 2.30GHz',  
    speed: 2300,  
    times:  
     { user: 3367100, nice: 0, sys: 757800, idle: 9833900, irq: 0 } },  
  { model: 'Intel(R) Xeon(R) CPU @ 2.30GHz',  
    speed: 2300,  
    times:  
     { user: 3387000, nice: 0, sys: 730100, idle: 10054300, irq: 0 } },  
  { model: 'Intel(R) Xeon(R) CPU @ 2.30GHz',  
    speed: 2300,  
    times:  
     { user: 3259600, nice: 0, sys: 748300, idle: 10168800, irq: 0 } },  
  { model: 'Intel(R) Xeon(R) CPU @ 2.30GHz',  
    speed: 2300,  
    times:  
     { user: 3229700, nice: 0, sys: 755800, idle: 10195600, irq: 0 } } ]

os.endianness

The os.endianness() function returns a string identifying the endianness of the CPU for which the Node.js run-time binary is compiled from. The 2 possible values are:

  • 'BE' — big-endian. A big-endian CPU order places with the most significant byte first and the least significant byte last.
  • 'LE' — little-endian, the opposite of big-endian.

If we run console.log on the return value of os.endianness() we may get something like the following:

'LE'

os.freemem

The os.freemem() function returns an integer that indicates the amount of free memory in the number of bytes. If we run console.log of the output of os.freemem() , we get something like:

15338930176

os.getPriority

The os.getPriority function returns an integer indicating the scheduling priority of the process which is specified by the PID. It takes one argument, which is the process ID passed in as an integer. If the PID isn’t provided or it’s 0, then the priority of the current process is returned. For example, if we write:

os.getPriority()

Then we get a number. 19 indicates the lowest CPU priority and -20 indicates the highest. Processor priority levels in Node.js are defined by the following constants:

  • PRIORITY_LOW — The lowest process scheduling priority. This corresponds to IDLE_PRIORITY_CLASS on Windows and a nice value of 19 on all other platforms.
  • PRIORITY_BELOW_NORMAL — This corresponds to BELOW_NORMAL_PRIORITY_CLASS on Windows and a nice value of 10 on all other platforms.
  • PRIORITY_NORMAL — The default process scheduling priority. This corresponds to NORMAL_PRIORITY_CLASS on Windows and a nice value of 0 on all other platforms.
  • PRIORITY_ABOVE_NORMAL — This corresponds to ABOVE_NORMAL_PRIORITY_CLASS on Windows and a nice value of -7 on all other platforms.
  • PRIORITY_HIGH — . This corresponds to HIGH_PRIORITY_CLASS on Windows and a nice value of -14 on all other platforms.
  • PRIORITY_HIGHEST — The highest process scheduling priority. This corresponds to REALTIME_PRIORITY_CLASS on Windows and a nice value of -20 on all other platforms.

os.homedir

The os.homedir function returns a string of the path o the home directory of the user. On Unix and Linux systems, it will use the $HOME variable if it’s defined. Otherwise, it will look up the home directory path by the effective UID, which is the user ID of the user identity that you’re currently assuming. For example, if you used sudo to use the computer as a root user then the effective user ID would be the user ID of the root user. On Windows, the value of the USERPROFILE will be used if it’s defined. Otherwise, it will be the path of the profile directory of the current user. For example, if we run console.log on the output of os.homedir() , then we may get something like:

'/home/runner'

if you’re on a Linux system.

os.hostname

The os.hostname function returns the hostname of the operating system as a string. For example, if we call console.log on the return value of os.hostname() , then we may get something like ‘5b84600c80eb’ .

os.loadavg

The os.loadavg function returns a number array containing 1, 5, and 15-minute load averages. The load average measures system activity, which is calculated by the operating system and expressed as a decimal number. The ideal load average should be less than the number of logical CPUs in the system. This function only works on Unix and Linux system. On Windows, it always returns [0,0,0] . For example, if we run this function on the Linux system, like in the following code:

console.log(os.loadavg())

We may get something like:

[ 12.60791015625, 13.3916015625, 9.8798828125 ]

os.networkInterfaces

The os.networkInterfaces function returns an object that has the network interfaces that have been assigned a network address. The keys on the returned object identify a network interface. The corresponding value of the keys is an array of objects that describe an assigned network address. Properties of an assigned network address object include:

  • address — a string that has the assigned IPv4 or IPv6 address
  • netmask — a string that has the IPv4 or IPv6 network mask
  • family — a string that has 2 possible values: IPv4 or IPv6
  • mac — a string that has the MAC address of the network interface
  • internal — a boolean value that is true if the network interface is a loopback or similar interface that is not remotely accessible. Otherwise, it’s false
  • scopeid — a number that has the IPv6 scope ID, applicable only when family is IPv6
  • cidr — a string that has the assigned IPv4 or IPv6 address with the routing prefix in CIDR notation. CIDR notation has 2 groups of numbers. The first is the group of bits, which is the network address. The first group is followed by a slash. The second group is the number of bits that are considered significant for network routing. For example, if we have an IP address 192.168.0.15/24, then 192.168.0.15 is the network address and 24 is the number of significant bits for network routing purposes. If the netmask is invalid, this property is set to null.

For example, if we run:

console.log(os.networkInterfaces());

Then we may get something like:

{ lo:  
   [ { address: '127.0.0.1',  
       netmask: '255.0.0.0',  
       family: 'IPv4',  
       mac: '00:00:00:00:00:00',  
       internal: true,  
       cidr: '127.0.0.1/8' } ],  
  eth0:  
   [ { address: '172.18.0.103',  
       netmask: '255.255.0.0',  
       family: 'IPv4',  
       mac: '02:42:ac:12:00:67',  
       internal: false,  
       cidr: '172.18.0.103/16' } ] }

We have lo for the loopback address and eth0 for the Ethernet interface.

os.platform

The os.platform function returns a string that identifies that operating system platform of the computer that compiled the Node.js binary. The current possible values are 'aix', 'darwin', 'freebsd', 'linux', 'openbsd', 'sunos', or 'win32' . It’s the same as the process.platform property. The value 'android' maybe returned if the Node.js binary is built on an Android device. However, Android support in Node.js is in the experimental phase. For example, if we run:

console.log(os.platform());

Then we may get something like:

'linux'

The Node.js OS module has many useful utility functions for getting information about the computer system that the OS module’s program is running on. The modules have many more properties containing useful information like CPUs, endianness, home directory, IP address, hostname, the platform the program is running on, system uptime, information about the currently logged in user and more.

Categories
JavaScript JavaScript Basics

Using the Javascript Conditional Operator

The JavaScript conditional operator is a basic building block of JavaScript programs.

The conditional operator is also called the ternary operator.

It lets us write expression that returns one thing if a given condition it truthy and return something else otherwise.

The conditional operator is denoted by the ? operator.

We can use it as follows:

const foo = condition ? 'foo' : 'bar';

In the code above, if condition is truthy, then 'foo' is returned. Otherwise, 'bar' is returned.

Then the returned value is assigned to the foo variable.

The code is above is short for:

if (condition) {
  return 'foo';
}
else {
  return 'bar';
}

As we can see, the code above is much longer than using the conditional operator.

Since it’s save so much typing and space on the page, we should use the conditional operator instead of using if statements if we want to write code that returns one thing if a given condition is truthy and something else otherwise.

Categories
JavaScript JavaScript Basics

Introduction to JavaScript Strict Mode

JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.

In this article, we’ll look at the benefits of using the strict mode directive.

Add Use Strict Mode Directive in Our Scripts

If we’re using old-school JavaScript script files, then we should add the 'use strict' directive into the top of our script.

Strict mode eliminates lots of silent errors by changing them to throw errors.

It also fixes mistakes that make optimizing our JavaScript code hard to increase their performance.

Also, it bans syntax that may be used in future JavaScript versions. Keywords like class can’t be used to declare variables, for example.

Strict mode can be applied to the whole script by putting the directive at the top or just in the function level by putting it in functions.

However, we should just apply it everywhere since it brings lots of benefits.

For instance, we can’t declare variables accidentally with 'use strict':

'use strict';
x = 1;

Since we have the 'use strict' directive on top of our script, we’ll get an error with the x = 1 expression since we haven’t declared x yet.

Without strict mode, this would create a global variable called x and assign 1 to it and pollute the global scope.

That isn’t good because it may overwrite another global variable with the same name.

Also, we can assign values to another global value like undefined or Infinity:

With strict mode on, code like the following will throw a TypeError:

var undefined = 1;
var Infinity = 1;

Assigning values to a non-writable property will also fail with a TypeError thrown:

var obj = {};
Object.defineProperty(obj, 'foo', { value: 42, writable: false });
obj.foo = 9;

We also wouldn’t be able to add properties that has preventExtensions called on it to prevent that:

var obj = {};
Object.preventExtensions(obj);
obj.foo = 'a';

The code above would throw a TypeError.

Attempting to delete undeletable properties will also throw an error. If we write something like:

'use strict';
delete Object.prototype;

Then we’ll get a TypeError.

Strict mode also requires function parameters to be unique. For instance, if we write:

'use strict';
function add(a, a, c) {  
  return a + a + c; 
}

Then we’ll get an ‘Uncaught SyntaxError: Duplicate parameter name not allowed in this context’ error since we have JavaScript strict mode on.

Also, it prevents numbers with a leading 0 from being used. The leading zero for octal numbers is rarely used and developers often assume that it’s still a decimal number.

Therefore if we have the following the strict mode throws an error:

'use strict';
var sum = 015 + 222;

If we run that, we get ‘Uncaught SyntaxError: Octal literals are not allowed in strict mode.’

The with statement is prohibited in strict mode. With strict mode, confusing code like this is prohibited:

'use strict';
var x = 17;
with(obj) {
  console.log(x);
}

The code above is confusing because x can either be obj.x or just x. It’s hard to tell what it’s referring to.

With strict mode on as we have above, we get ‘Uncaught SyntaxError: Strict mode code may not include a with statement’.

Doing anything to arguments or eval will also return syntax errors, so code like the following:

'use strict';
eval = 'foo';
arguments++;

Then we get ‘Uncaught SyntaxError: Unexpected eval or arguments in strict mode’ when we run the code above since we have JavaScript strict mode on.

We shouldn’t use these entities regardless of whether JavaScript strict mode is on, so it’s good that strict mode prevents expressions like these from running at least.

With strict mode on, the this value passed into call, apply, or bind aren’t boxed into an object.

Therefore, the original value is preserved if we pass in a primitive value. For instance, if we have:

'use strict';
function fn() {  
  return this;
}
console.log(fn.call(1) === 1);

Then we get 1 returned from fn instead of new Number(1), so we get that the console log output returns true.

Strict mode is enabled automatically for modules so we don’t need the directive on top of our code.

Conclusion

With so many benefits to strict mode, we should always enable it in old-school scripts.

If we use JavaScript modules, then it’s enabled by default, so we don’t have to worry about it.

We just have to put 'use strict' on top of all our scripts.