Files
2026-04-17 23:26:01 +00:00

3.1 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Default to Locked Rules, Open Explicitly CRITICAL Defense in depth, prevents accidental data exposure api-rules, security, defaults, best-practices

Default to Locked Rules, Open Explicitly

New collections should start with locked (null) rules and explicitly open only what's needed. This prevents accidental data exposure and follows the principle of least privilege.

Incorrect (starting with open rules):

// Dangerous: copying rules from examples without thinking
const collection = {
  name: 'user_settings',
  listRule: '',      // Open - leaks all user settings!
  viewRule: '',      // Open - anyone can view any setting
  createRule: '',    // Open - no auth required
  updateRule: '',    // Open - anyone can modify!
  deleteRule: ''     // Open - anyone can delete!
};

// Also dangerous: using auth check when ownership needed
const collection = {
  name: 'private_notes',
  listRule: '@request.auth.id != ""',  // Any logged-in user sees ALL notes
  viewRule: '@request.auth.id != ""',
  updateRule: '@request.auth.id != ""',  // Any user can edit ANY note!
};

Correct (locked by default, explicitly opened):

// Step 1: Start locked
const collection = {
  name: 'user_settings',
  listRule: null,    // Locked - superusers only
  viewRule: null,
  createRule: null,
  updateRule: null,
  deleteRule: null
};

// Step 2: Open only what's needed with proper checks
const collection = {
  name: 'user_settings',
  // Users can only see their own settings
  listRule: 'user = @request.auth.id',
  viewRule: 'user = @request.auth.id',
  // Users can only create settings for themselves
  createRule: '@request.auth.id != "" && @request.body.user = @request.auth.id',
  // Users can only update their own settings
  updateRule: 'user = @request.auth.id',
  // Prevent deletion or restrict to owner
  deleteRule: 'user = @request.auth.id'
};

// For truly public data, document why it's open
const collection = {
  name: 'public_announcements',
  // Intentionally public - these are site-wide announcements
  listRule: '',
  viewRule: '',
  // Only admins can manage (using custom "role" field on auth collection)
  // IMPORTANT: Prevent role self-assignment in the users collection updateRule:
  //   updateRule: 'id = @request.auth.id && @request.body.role:isset = false'
  createRule: '@request.auth.role = "admin"',
  updateRule: '@request.auth.role = "admin"',
  deleteRule: '@request.auth.role = "admin"'
};

Rule development workflow:

  1. Start locked - All rules null
  2. Identify access needs - Who needs what access?
  3. Write minimal rules - Open only required operations
  4. Test thoroughly - Verify both allowed and denied cases
  5. Document decisions - Comment why rules are set as they are

Security checklist:

  • No empty string rules without justification
  • Ownership checks on personal data
  • Auth checks on write operations
  • Admin-only rules for sensitive operations
  • Tested with different user contexts

Reference: PocketBase API Rules