Skip to content

Security Model

Harish Dhanraj Sugandhi edited this page Mar 4, 2026 · 1 revision

Security Model

OpenWP implements defense-in-depth security with multiple layers of protection.

Security Architecture

Request
  │
  ├── 1. WordPress Nonce / Bearer Token (authentication)
  ├── 2. Capability Check (authorization)
  ├── 3. Policy Engine (action-level permissions)
  ├── 4. Schema Validation (input sanitization)
  ├── 5. SQL Guard (query safety for db_query action)
  ├── 6. Rate Limiter (abuse prevention)
  ├── 7. Approval Queue (human-in-the-loop for risky actions)
  └── 8. Pre-Action Backup (rollback capability)

Policy Engine (inc/Security/PolicyEngine.php)

The PolicyEngine evaluates every action execution:

  1. Capability check - Verifies current_user_can($capability) for the action
  2. Action enabled - Checks per-action policy overrides (can disable individual actions)
  3. Approval routing - Determines if the action needs human approval based on:
    • Risk level settings (medium_requires_approval, high_requires_approval, critical_requires_approval)
    • Per-action policy override (require_approval)
  4. Backup requirement - Auto-requires backup for mutating high/critical actions
  5. Typed confirmation - Critical actions require the user to type "APPROVE"

Policy Override Structure

{
    "wp_create_post": {
        "enabled": true,
        "require_approval": false
    },
    "wp_delete_plugin": {
        "enabled": true,
        "require_approval": true
    }
}

SQL Guard (inc/Security/Sql_Guard.php)

Validates raw SQL queries before execution via the db_query action:

Allowed Statements

  • Read-only: SELECT, SHOW, DESCRIBE, EXPLAIN
  • Mutating: INSERT, UPDATE, DELETE, REPLACE, ALTER, DROP, TRUNCATE, CREATE, RENAME, OPTIMIZE, REPAIR, ANALYZE

Blocked Patterns

The following SQL primitives are always blocked:

  • INTO OUTFILE - File write exploitation
  • LOAD_FILE - File read exploitation
  • INTO DUMPFILE - Binary file write
  • BENCHMARK( - Timing attacks
  • SLEEP( - Time-based injection
  • INFORMATION_SCHEMA.FILES - File system enumeration

Additional Safety

  • Multi-statement queries (containing ; mid-query) are rejected
  • LIMIT extraction for read safety monitoring
  • Unsupported statement types are rejected

Rate Limiter (inc/Security/Rate_Limiter.php)

Prevents abuse through configurable daily limits:

Limit Default Scope
max_actions_user_day 50 Per user per day
max_actions_site_day 500 Site-wide per day
max_tokens_user_day 120,000 Per user per day
max_tokens_site_day 1,200,000 Site-wide per day
min_seconds_between_runs 5 Per user cooldown

Rate limit data is stored in the openwp_usage_daily table.

Encryption Service (inc/Security/Encryption_Service.php)

Encrypts sensitive data (API keys) for storage in the WordPress options table.

Encryption Methods (in preference order)

  1. Sodium (sodium_crypto_secretbox) - Preferred, available in PHP 7.2+
  2. OpenSSL (AES-256-CBC) - Fallback

Key Derivation

The encryption key is derived from site-specific material:

SHA-256(wp_salt('auth') | DB_NAME | site_url())

Storage Format

sodium:base64(nonce + ciphertext)
openssl:base64(iv + ciphertext)

Provider Key Manager (inc/Security/Provider_Key_Manager.php)

Manages encrypted storage and retrieval of LLM provider API keys:

  • Keys are encrypted via Encryption_Service before storage
  • Masked keys are returned to the UI (showing only last 4 characters)
  • Stored in OPENWP_OPTION_PROVIDER_KEYS option

Capability System (inc/Permissions/Capability_Manager.php)

Two custom capabilities granted to administrators on activation:

Capability Purpose
openwp_run_agent Execute agent commands, access console
openwp_manage_settings Manage plugin settings, memory

No Dynamic Execution

Critical safety design: OpenWP never executes arbitrary PHP code. All actions must be pre-registered in the Action_Registry at boot time. The LLM can only select from the catalog of registered actions - it cannot invent new ones.

Input Validation

The Schema_Validator (inc/Utils/Schema_Validator.php) validates all action parameters against their registered JSON schema before execution. This prevents:

  • Type mismatches
  • Missing required fields
  • Unexpected additional properties (when additionalProperties: false)

Clone this wiki locally