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

92 lines
3.1 KiB
Markdown

---
title: Default to Locked Rules, Open Explicitly
impact: CRITICAL
impactDescription: Defense in depth, prevents accidental data exposure
tags: 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):**
```javascript
// 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):**
```javascript
// 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](https://pocketbase.io/docs/api-rules-and-filters/)