DEV Community

Ofri Peretz
Ofri Peretz

Posted on

Getting Started with eslint-plugin-pg

13 PostgreSQL-specific rules. SQL injection, connection pools, transactions.

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-n-plus-one-query 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


Follow me for more posts and updates,

GitHub | LinkedIn | dev.to

Top comments (0)