≡ Menu

JavaScript is the backbone of the modern web, but its flexibility is a double-edged sword.

Because it runs both in the browser and on the server (Node.js), it presents a massive attack surface.

Writing “code that works” isn’t enough anymore; you have to write code that survives.

Here is a deep dive into the essential pillars of secure JavaScript development.


1. Defending Against Cross-Site Scripting (XSS)

XSS remains the most common JavaScript vulnerability. It occurs when an attacker injects malicious scripts into content that other users see.

  • Sanitize and Encode: Never trust user input. Use libraries like DOMPurify to sanitize HTML before rendering it.

  • Use textContent over innerHTML: When displaying plain text, use .textContent. It treats the input as literal text rather than parsing it as HTML, effectively neutralizing script tags.

  • Content Security Policy (CSP): Implement a CSP header to tell the browser which scripts are authorized to run. A strong CSP can block inline scripts and unauthorized external domains.


2. Secure Data Handling & Storage

How you store sensitive information in the browser dictates how easily it can be stolen.

  • Avoid LocalStorage for Secrets: Data in localStorage is accessible to any JavaScript running on your domain. If an attacker finds even a small XSS vulnerability, they can steal session tokens stored there.

  • Use HttpOnly Cookies: For session management, use cookies with the HttpOnly and Secure flags. This prevents JavaScript from accessing the cookie, making it immune to XSS-based theft.

  • Validate on the Server: Client-side validation is for user experience; server-side validation is for security. An attacker can easily bypass your frontend checks using tools like Postman or Burp Suite.


3. Preventing Injection Attacks (NoSQL & SQL)

If you are using Node.js, your database queries are high-value targets.

  • Template Literals are not Safety Nets: Simply using backticks doesn’t prevent injection.

  • Use Parameterized Queries: Whether using PostgreSQL or MongoDB, always use parameterized inputs or Object-Document Mappers (ODMs) like Mongoose that handle sanitization for you.

Vulnerable Example:

// Never do this!
const query = `SELECT * FROM users WHERE id = ${userInput}`;

Secure Example:

// Use placeholders
db.query('SELECT * FROM users WHERE id = $1', [userInput]);

4. Dependency Management: The “Hidden” Risk

Modern JavaScript apps rely on hundreds of npm packages. Each one is a potential backdoor.

  • Audit Regularly: Run npm audit frequently to find known vulnerabilities in your dependency tree.

  • Lock Down Versions: Use package-lock.json to ensure that your production environment uses the exact same code you tested in development.

  • Beware of “Typosquatting”: Double-check package names before installing (e.g., lodash vs lo-dash).


5. Secure Use of eval() and setTimeout()

The eval() function executes a string as code. It is one of the most dangerous functions in JavaScript.

  • The Rule: Just don’t use eval(). There is almost always a safer way to achieve your goal using JSON parsing or bracket notation.

  • Dynamic Function Execution: Similarly, avoid passing strings to setTimeout() or setInterval(), as this invokes the same internal mechanism as eval(). Always pass a function reference instead.


6. Protections Against Prototype Pollution

JavaScript’s prototype-based inheritance can be exploited if an attacker can inject properties into Object.prototype. This can lead to logic bypasses or even Remote Code Execution (RCE).

  • Freeze the Prototype: In sensitive environments, use Object.freeze(Object.prototype).

  • Use Map for Key-Value Pairs: Instead of using plain objects for user-controlled data, use Map, which does not inherit from the standard Object prototype in the same way.

  • Validation: Use JSON schema validators to ensure incoming JSON objects only contain the expected keys.


Summary Checklist

Risk Mitigation
XSS Use textContent, DOMPurify, and CSP.
Token Theft Store session IDs in HttpOnly cookies.
Injection Use parameterized queries/ORMs.
Supply Chain Run npm audit and use lockfiles.
Prototype Pollution Use Object.create(null) or Map.

Useful links below:

Let me & my team build you a money making website/blog for your business https://bit.ly/tnrwebsite_service

Get Bluehost hosting for as little as $1.99/month (save 75%)…https://bit.ly/3C1fZd2

Best email marketing automation solution on the market! http://www.aweber.com/?373860

Build high converting sales funnels with a few simple clicks of your mouse! https://bit.ly/484YV29

Join my Patreon for one-on-one coaching and help with your coding…https://www.patreon.com/c/TyronneRatcliff

Buy me a coffee ☕️https://buymeacoffee.com/tyronneratcliff

{ 0 comments }

You’ve built a sleek, modern web application. It’s fast, the UI is responsive, and your Lighthouse scores are green.

But after a user leaves the tab open for twenty minutes, everything starts to crawl.

The animations stutter, clicks feel laggy, and eventually, the browser tab crashes entirely.

Welcome to the world of memory leaks.

In JavaScript, we often take for granted that the Garbage Collector (GC) is tidying up after us.

But even the smartest GC can’t reclaim memory if you’re still holding onto it—often without even realizing it.

Whether it’s a forgotten event listener or an accidental global variable, these “silent killers” gradually consume a user’s RAM, turning a premium experience into a frustrating one.

In this guide, we’ll dive into the five most frequent memory leaks in modern JavaScript development and provide clear, actionable strategies to plug the holes and keep your apps running lean.

The Concept: What is a Memory Leak?

In JavaScript, memory is managed automatically via Garbage Collection (GC).

The GC’s job is to find objects that are no longer “reachable” and reclaim their space.

A memory leak occurs when you unintentionally keep a reference to an object alive, preventing the GC from doing its job.


1. Accidental Global Variables

The Problem: When you assign a value to a variable that hasn’t been declared with const, let, or var, JavaScript attaches it to the window object (in browsers). Global variables are never garbage collected as long as the window is open.

function leak() {
  // 'message' is now a global variable
  message = "This will stay in memory forever"; 
}

The Fix: Always use Strict Mode ('use strict';) or modern ES6 declarations.

  • Solution: Use const or let.


2. Forgotten Event Listeners

The Problem: This is the most common leak in Single Page Applications (SPAs). If you add an event listener to the window or a parent element within a component, but don’t remove it when the component “dies,” the listener (and any variables it captures) stays in memory.

// Adding it...
window.addEventListener('resize', () => {
  console.log("Resizing...");
});

// If the component is destroyed, the listener is still active!

The Fix: Explicitly remove the listener during the cleanup phase.

  • Solution: Use removeEventListener. In React, do this inside the useEffect return function.


3. Uncleared Timers (setInterval)

The Problem: If a setInterval is running and references data in its scope, that data cannot be collected until the interval is stopped—even if the UI that needed that data is gone.

const heavyData = new Array(1000).fill("💾");

setInterval(() => {
  // As long as this runs, heavyData stays in memory
  console.log(heavyData.length);
}, 1000);

The Fix: Store the timer ID and clear it when it’s no longer needed.

  • Solution: const timerId = setInterval(...); followed by clearInterval(timerId);.


4. Closures Holding Large Scopes

The Problem: Closures are a core feature of JS, but they can be dangerous. A nested function that stays alive (e.g., as a callback) keeps a reference to its entire parent scope. If the parent scope contains large objects, they are leaked.

function outer() {
  const hugeData = new Array(1000000).fill("❌");
  
  return function inner() {
    // Even if hugeData isn't used here, some engines might struggle 
    // to collect it if 'inner' is exported globally.
    console.log("Inner function alive");
  };
}

The Fix: Nullify large variables at the end of the function if they are no longer needed, or keep the closure scope as small as possible.


5. Detached DOM Nodes

The Problem: You save a reference to a DOM element in a JavaScript variable. Later, you remove that element from the page using removeChild() or .remove(). However, because your JS variable still points to it, the browser cannot delete the element from memory.

const elements = {
  button: document.getElementById('myButton')
};

function removeBtn() {
  document.body.removeChild(document.getElementById('myButton'));
  // The button is gone from the UI, but still in the 'elements' object!
}

The Fix: Set the reference to null after removing the element from the DOM.

  • Solution: elements.button = null;


🛠️ How to Debug Leaks

  1. Open DevTools > Memory.

  2. Select Heap Snapshot.

  3. Perform an action in your app, then trigger another snapshot.

  4. Use the “Comparison” view to see which objects were created but not deleted.

🛡️ The JavaScript Memory Health Checklist

Before you ship your next feature, run through these five quick checks to ensure your app stays fast:

  1. Strict Mode: Is 'use strict'; enabled (or are you using ES Modules)? This prevents Accidental Globals.

  2. The Cleanup Rule: For every addEventListener, is there a corresponding removeEventListener in the teardown logic?

  3. Interval Audit: Are all setInterval and setTimeout calls cleared when the component or page changes?

  4. Nullify References: Are you setting large objects or detached DOM nodes to null once they are no longer needed?

  5. Profile Regularly: Have you taken a Heap Snapshot in Chrome DevTools to see if memory usage returns to baseline after a user action?

Useful links below:

Let me & my team build you a money making website/blog for your business https://bit.ly/tnrwebsite_service

Get Bluehost hosting for as little as $1.99/month (save 75%)…https://bit.ly/3C1fZd2

Best email marketing automation solution on the market! http://www.aweber.com/?373860

Build high converting sales funnels with a few simple clicks of your mouse! https://bit.ly/484YV29

Join my Patreon for one-on-one coaching and help with your coding…https://www.patreon.com/c/TyronneRatcliff

Buy me a coffee ☕️https://buymeacoffee.com/tyronneratcliff

 

{ 0 comments }