More in Backend Dev — page 37

Content Security Policy (CSP): An Allowlist for Browser Resources
Content Security Policy is an allowlist you send to the browser, dictating which scripts, styles, and images are safe to load. It's a primary defense against XSS attacks by blocking unauthorized resources.

Dependency Scanning with npm audit
Think of dependency scanning as a background check for your code. `npm audit` compares your project's packages against a database of known security flaws, telling you if you're using vulnerable code. The biggest footgun is blindly running `npm audit fix`.
Preventing SQL Injection: Never Trust User Input
To prevent SQL injection, treat SQL as a template and user input as data that can only fill placeholders, never changing the query's structure. Use this for any database query in your Node.js app that uses external data.
XSS Prevention: Context-Aware Output Encoding
Prevent XSS by encoding all untrusted data just before it's rendered. The key is context: escaping for an HTML body is different from an attribute or script tag. This is critical for displaying user content.
Nock: Intercept and Mock Node.js HTTP Requests
Nock acts like a fake switchboard for your Node.js app's outgoing HTTP calls, redirecting them to pre-defined responses. This lets you unit test code that relies on external services, making tests fast, deterministic, and offline-capable.
E2E Testing: The Final Check, Not The Whole Strategy
E2E testing is a dress rehearsal for your app, simulating a full user journey. Use it sparingly for critical flows like checkout, as it tests all services together. The footgun is over-reliance: they are slow, brittle, and hard to debug.
Code Coverage Reporting with nyc/Istanbul
Code coverage reporting asks, "Which lines of my code did my tests actually run?" Use a tool like `nyc` to wrap your test runner (e.g., Mocha) and generate a report. The footgun is chasing 100% coverage, which doesn't guarantee quality.
Test Doubles: Mocks, Stubs, and Spies
A test double is a stand-in for a real component, letting you test code in isolation. Use them to fake slow dependencies like database calls or external APIs, making tests fast and predictable.
Supertest: Test Node.js APIs Without the Boilerplate
Supertest lets you test your Node.js API without running a separate server. Use it in Jest or Mocha to make requests to your routes and assert on responses. The footgun: since it's in-process, state can leak between tests if not reset properly.
Chai: Assertions for Readable JavaScript Tests
Chai makes your JavaScript tests read like sentences. It provides assertion styles like `expect(value).to.equal(5)` to verify code behavior in test frameworks like Mocha. The main footgun: the `should` style fails silently on null or undefined values.
Mocha: A Flexible JavaScript Test Runner
Mocha is a flexible JavaScript test runner, providing structure but not assertions. It organizes and executes tests in Node.js and browsers, excelling with asynchronous code. The main footgun is forgetting you must pair it with an assertion library like Chai.

Jest: A Batteries-Included JavaScript Test Framework
Jest is a 'batteries-included' JavaScript test framework, bundling a runner, assertions, and mocks for a zero-config experience. It's a go-to for testing Node, React, and TypeScript apps. Footgun: Snapshot tests only catch unexpected changes, not flawed logic.
Node.js Uncaught Exceptions: Clean Up, Don't Continue
An uncaught exception is a fire alarm for your Node.js app, signaling an unknown state. Use the `process.on('uncaughtException')` hook for last-resort synchronous cleanup before exiting, not to resume normal operation.
Never Trust User Input: The Validation Mindset
Treat all incoming data as hostile until proven otherwise. Input validation ensures only properly formed data enters your system, protecting against errors and attacks. It applies to user forms, APIs, and partner feeds.
Joi: Declarative Schemas for Data Validation
Joi lets you describe your data's shape with a readable schema instead of writing manual validation logic. It's used to validate API request bodies or config files.

Custom Error Classes: Beyond Generic Errors
Create specific error types, like `NotFoundError`, instead of generic ones. This lets your code react differently to different failures, like sending a 404 for a missing user vs. a 500 for a database outage.
Error-First Callbacks: Node.js's Original Async Handler
The error-first callback is a Node.js convention: check for rain before unpacking the picnic. The first argument to any async callback is for an error. It's the standard for older core modules like `fs`.
JWT Storage: Cookies (CSRF Risk) vs. Local Storage (XSS Risk)
Storing JWTs means choosing your risk: Cross-Site Request Forgery (CSRF) with cookies, or Cross-Site Scripting (XSS) with local storage. While local storage is simpler, HttpOnly cookies are generally safer as they can't be read by client-side scripts.
CSRF Tokens: Preventing Unwanted State Changes on Your Behalf
CSRF protection prevents a malicious site from forcing a user's browser to submit unwanted requests to your app. It adds a unique token to forms that the server validates. The footgun is failing to protect all state-changing endpoints, not just POST forms.
Passport.js: The Generic OAuth2 Strategy
Passport's generic OAuth2 strategy is a template for social logins, not a plug-and-play solution. Use it to integrate a custom OAuth2 provider. The footgun is using it when a provider-specific strategy (like passport-github2) exists, which handles quirks for…