Web Browsers

Work in progress. This note is still being written and incomplete.

Browsers are a large, complex, network-facing codebase written in memory-unsafe languages, with features added constantly. Architecture is what keeps that from being a disaster.

Memory Unsafety

A Microsoft study found roughly 70% of vulnerabilities fixed by security updates each year are memory safety issues. As of March 2019, all but about 5 of 130 public Critical Chrome bugs were memory corruption.

One example Chrome RCE overrides byteLength on an ArrayBuffer getter to 0xFFFFFFFC. The resulting Uint32Array reads and writes arbitrary memory.

The Rule of 2: for a given task, pick at most 2 of untrusted input, unsafe language, no sandbox. If you need all 3, split the work.

Chrome Multi-Process Architecture

Renderer processes have no direct disk, network, or device access. They run in a restricted sandbox, which limits damage from a renderer exploit. The split also gives parallelism across tabs and survives a single renderer crash.

It has limitations. Same-origin iframes with document.domain can force cross-origin pages into one process. Memory pressure exhausts process budgets. Every renderer can request cross-origin images and scripts, so it effectively sees many cookies.

Auto-update shipped from the start. It is now the delivery mechanism for the whole platform.

Site Isolation

Put content from one site in its own renderer process. The unit is a site, not a tab, and a site, not an origin. The browser process can then restrict each renderer to its own site’s data.

It defends against Spectre-style speculative side channels from JavaScript, universal XSS (UXSS), and fully compromised renderers.

The goals are to stop a renderer receiving cross-site cookies, stored data, saved passwords, or another site’s granted permissions, to block cross-site pages in iframes per X-Frame-Options, and to keep cross-site DOM out of reach of UXSS bugs.

Cross-Origin Read Blocking (CORB) blocks cross-site delivery of HTML, XML, and JSON responses. It works reliably when the response has a correct Content-Type and X-Content-Type-Options: nosniff. Without nosniff, Chrome sniffs the start of the file and protects it only if it can confirm the type. This avoids breaking mislabeled JavaScript files.

Secure Coding in JavaScript

JavaScript has sharp edges. Use strict mode and a linter such as ESLint or StandardJS.

== uses abstract equality, so 0, '0', and false are all mutually equal. Always use ===. Duplicate function parameters and duplicate object keys are allowed by default. Strict mode or a linter catches them. Accessing Object.prototype builtins directly breaks when an object has its own hasOwnProperty, so use Object.hasOwn.

Automatic semicolon insertion changes meaning across line breaks. Write boring code instead of relying on it. A leading ; before ( or [ disambiguates.

A leading zero makes a number octal, so 010 is 8. Strict mode rejects it. Assignment without var, let, or const creates a global. Strict mode makes it a ReferenceError. Assigning to non-writable globals or setting properties on primitives fails silently without strict mode.

Style and Testing Principles

Source code is for humans. Prefer readability over brevity. Avoid clever one-liners that lean on obscure language features. Dangerous code should look dangerous so it stands out in review. Untested code is broken code. Automate tests in CI.

Open Source Supply Chain Risk

Risk comes from accidents, undermaintained packages, and outright malice. Critical infrastructure like OpenSSL and curl is maintained by a handful of people on tiny budgets.

The problem worsened because adding dependencies got easy, packages got smaller, and far more individual maintainers are trusted.

Vulnerabilities are accidental and sometimes acceptable to ship. Malware is intentional and never acceptable. A malicious package is public for about 209 days on average before being reported. 56% run their payload on install through preinstall scripts, exfiltrating process.env, mining cryptocurrency, or stealing credentials. Real cases are ua-parser-js, coa, and rc.

SCA tools like Socket analyze dependency behavior.

Course Takeaways

  • Think like an attacker.
  • Never trust user input. Sanitize at time of use.
  • Use defense in depth.
  • Salt and hash passwords. Just use bcrypt.
  • Beware ambient authority. Use SameSite cookies.
  • Explicit code is safer than magical code.
  • You can never be too paranoid.
Written by September 3, 2026 4 min read
Was this helpful?