Skip to content



This hook enumerates special or external permissions, making them available for use in CiviCRM configuration.


Available starting in CiviCRM 5.34.

These two hooks appear similar, but they serve different purposes:

  • hook_civicrm_permission: Defines new permissions. The permission will be fully available in configuration screens for CiviCRM/Drupal/WordPress/etc.
  • hook_civicrm_permissionList: Modifies the list of permissions presented in CiviCRM configuration. For example, this is used to import Drupal/WordPress permissions into CiviCRM configuration screens (without creating a funny loop).




  • $permissions: reference to an associative array of imported permissions. Each permission is keyed by its symbolic name, and it has properties:

    • group (string): Logical grouping for related permissions. For example, in the default arrangement, permissions for CiviCRM resources have group civicrm. and permissions for CMS resources have group cms.
    • title (string): Brief, descriptive title. (Ex: "CiviEvent: Register for events")
    • description (string): Longer, explanatory description (Ex: "Use public facing forms to register for events online")
    • is_active (bool): Whether the permission is currently available for use in configuration screens. Default is TRUE.
    • is_synthetic (bool): Normal permissions are checked through the CMS/UF layer. Synthetic permissions have their own custom checkers. If the permission name begins with @, then the default will be is_synthetic=TRUE. Otherwise, the default is is_synthetic=FALSE.


  • null


In this example, we define a synthetic permission @always which always allows access.

use CRM_Mymodule_ExtensionUtil as E;

// Add '@always' to the list of known permissions
function mymodule_civicrm_permissionList(&$permissions) {
  $permissions['@always'] = [
    'title' => E::ts('Always allow access'),
    'description' => E::ts('Always grants access'),

// Interpret '@always' as always true.
function mymodule_civicrm_permission_check($permission, &$granted, $contactId) {
  if ($permission === '@always') $granted = TRUE;