DEV Community

Cover image for Hardening the Data Layer: The node-postgres Static Analysis Standard
Ofri Peretz
Ofri Peretz

Posted on • Edited on • Originally published at ofriperetz.dev

Hardening the Data Layer: The node-postgres Static Analysis Standard

Postgres is the backbone of your production infrastructure. For engineering leaders, database security isn't a training problemβ€”it's a governance problem. Here is the automated static analysis standard for node-postgres.

Quick Install

npm install --save-dev eslint-plugin-pg
Enter fullscreen mode Exit fullscreen mode

Flat Config

// eslint.config.js
import pg from "eslint-plugin-pg";

export default [pg.configs.recommended];
Enter fullscreen mode Exit fullscreen mode

Run ESLint

npx eslint .
Enter fullscreen mode Exit fullscreen mode

You'll see output like:

src/users.ts
  15:3  error  πŸ”’ CWE-89 OWASP:A03 CVSS:9.8 | Unsafe SQL query detected
               Fix: Use parameterized query: client.query('SELECT * FROM users WHERE id = $1', [id])

src/orders.ts
  28:5  error  πŸ”’ CWE-772 | pool.connect() without client.release()
               Fix: Add client.release() in finally block
Enter fullscreen mode Exit fullscreen mode

Rule Overview

Rule CWE What it catches
no-unsafe-query CWE-89 SQL injection via string concatenation
no-missing-client-release CWE-772 Connection pool leaks
prevent-double-release CWE-415 Double release crashes
no-transaction-on-pool CWE-362 Transaction race conditions
prefer-pool-query CWE-400 Unnecessary connect/release
no-unsafe-copy-from CWE-22 Path traversal in COPY FROM
no-unsafe-search-path CWE-426 search_path hijacking
no-batch-insert-loop Perf N+1 query patterns
Plus 5 more...

Quick Wins

Before

// ❌ SQL Injection
const query = `SELECT * FROM users WHERE id = '${userId}'`;
await pool.query(query);
Enter fullscreen mode Exit fullscreen mode

After

// βœ… Parameterized Query
const query = "SELECT * FROM users WHERE id = $1";
await pool.query(query, [userId]);
Enter fullscreen mode Exit fullscreen mode

Before

// ❌ Connection Leak
const client = await pool.connect();
const result = await client.query("SELECT * FROM users");
return result.rows;
// Missing client.release()!
Enter fullscreen mode Exit fullscreen mode

After

// βœ… Guaranteed Release
const client = await pool.connect();
try {
  const result = await client.query("SELECT * FROM users");
  return result.rows;
} finally {
  client.release();
}
Enter fullscreen mode Exit fullscreen mode

Available Presets

// Security + best practices
pg.configs.recommended;

// All rules enabled
pg.configs.all;
Enter fullscreen mode Exit fullscreen mode

Customizing Rules

// eslint.config.js
import pg from "eslint-plugin-pg";

export default [
  pg.configs.recommended,
  {
    rules: {
      // Downgrade to warning
      "pg/prefer-pool-query": "warn",

      // Increase strictness
      "pg/no-unsafe-query": [
        "error",
        {
          allowLiteral: false,
        },
      ],
    },
  },
];
Enter fullscreen mode Exit fullscreen mode

Performance

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Benchmark: 1000 files                               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ eslint-plugin-pg:          785ms                    β”‚
β”‚ 100% precision (0 false positives in tests)         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
Enter fullscreen mode Exit fullscreen mode

Combine with Other Plugins

import pg from "eslint-plugin-pg";
import secureCoding from "eslint-plugin-secure-coding";

export default [pg.configs.recommended, secureCoding.configs.recommended];
Enter fullscreen mode Exit fullscreen mode

Quick Reference

# Install
npm install --save-dev eslint-plugin-pg

# Config (eslint.config.js)
import pg from 'eslint-plugin-pg';
export default [pg.configs.recommended];

# Run
npx eslint .
Enter fullscreen mode Exit fullscreen mode

πŸ“¦ npm: eslint-plugin-pg
πŸ“– Full Rule List

πŸš€ Using node-postgres? Drop a star on GitHub!

⭐ Star on GitHub


The Interlace ESLint Ecosystem
Interlace is a high-fidelity suite of static code analyzers designed to automate security, performance, and reliability for the modern Node.js stack. With over 330 rules across 18 specialized plugins, it provides 100% coverage for OWASP Top 10, LLM Security, and Database Hardening.

Explore the full Documentation

Β© 2026 Ofri Peretz. All rights reserved.


Build Securely.
I'm Ofri Peretz, a Security Engineering Leader and the architect of the Interlace Ecosystem. I build static analysis standards that automate security and performance for Node.js fleets at scale.

ofriperetz.dev | LinkedIn | GitHub

Top comments (0)