# @strapi/permissions

> Strapi's permission layer.

Latest version **5.55.0** (published 2026-09-23) · SEE LICENSE IN LICENSE license · 0 weekly downloads

## Install

```sh
npm install @strapi/permissions
pnpm add @strapi/permissions
yarn add @strapi/permissions
bun add @strapi/permissions
```

## Health

**Score 75/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score; popular repo; extremely popular.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 5.55.0 |
| Published | 2026-09-23 |
| First published | 2022-09-09 |
| Weekly downloads | 0 |
| License | SEE LICENSE IN LICENSE |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=20.0.0 <=26.x.x |
| Dependencies | 5 |
| Unpacked size | 95.9 KB |
| Known vulnerabilities | 0 (+2 in 1 direct dependencies) |
| Install scripts | no |
| GitHub stars | 73203 |
| Author | Strapi Solutions SAS |
| Maintainers | pierreburgy, aurelsicoko, alexandrebodin, convly, nico-strapi, strapi.adzouz, cache-your-dreams, baronvoninternet, marc-roig-strapi, jhoward1994, bassel17 |

## Links

- npm: https://www.npmjs.com/package/@strapi/permissions
- Repository: https://github.com/strapi/strapi
- Homepage: https://strapi.io
- Issues: https://github.com/strapi/strapi/issues
- npm.io page: https://npm.io/package/@strapi/permissions

## Dependencies (5)

- [qs](https://npm.io/package/qs.md) 6.15.3
- [sift](https://npm.io/package/sift.md) 16.0.1
- [lodash](https://npm.io/package/lodash.md) 4.18.1
- [@casl/ability](https://npm.io/package/@casl/ability.md) 6.7.5
- [@strapi/utils](https://npm.io/package/@strapi/utils.md) 5.55.0

## Recent versions

- 5.55.0 (latest) — 2026-09-23
- 0.0.0-experimental.bc2fdf229afcf1dc7c28753b3ce6befedf9d8da5 (experimental) — 2026-09-23
- 0.0.0-next.38ed6a5e2b7972b41472ceffafcdc0ab57426964 (next) — 2026-09-23
- 4.26.2 (legacy) — 2026-06-09
- 0.0.0-experimental.646a3d905bdd8978683813330ee46984938eed0a (beta-ai) — 2025-07-16
- 5.17.0-beta.0 (beta) — 2025-06-18
- 0.0.0-experimental.4e03c41e8e44fa7b77c41c3e0edd86c7f1fc9c52 (alpha) — 2025-05-15
- 5.0.0-rc.30 (rc) — 2024-09-18
- 0.0.0-experimental.13b53246eca3c6fba6e1b81bc287f7275a0ae516 — 2026-09-23
- 0.0.0-experimental.7b8d648ba906e3b288dcf19d36a8e18185653eb6 — 2026-09-23
- 0.0.0-experimental.82061dc62dde507a59e3b90c275bff5b7445da2a — 2026-09-23
- 0.0.0-experimental.18cedb506b918a866cc2c139cd97e67ff559c3e0 — 2026-09-23
- 0.0.0-experimental.e721769332be9c554bb73e0341d73857f83d48b5 — 2026-09-23
- 0.0.0-experimental.2986acf70cb905fe82293eb90138cfac715b8cde — 2026-09-23
- 0.0.0-experimental.f3f1c6ec2a8396ddc1d603cbdd143e0a70fd7006 — 2026-09-23
- … 2476 more at https://npm.io/package/@strapi/permissions/versions

## README

# Strapi Permissions

Highly customizable permission engine made for Strapi

## Get Started

```sh
yarn add @strapi/permissions
```

```javascript
const permissions = require('@strapi/permissions');

const engine = permissions.engine.new({ providers });

const ability = await engine.generateAbility([
  { action: 'read' },
  { action: 'delete', subject: 'foo' },
  { action: 'update', subject: 'bar', properties: { fields: ['foobar'] } },
  {
    action: 'create',
    subject: 'foo',
    properties: { fields: ['foobar'] },
    conditions: ['isAuthor'],
  },
]);

ability.can('read'); // true
ability.can('publish'); // false
ability.can('update', 'foo'); // false
ability.can('update', 'bar'); // true
```

- You need to give both an action and a condition provider as parameters when instantiating a new permission engine instance. They must be contained in a `providers` object property.
- You can also pass an `abilityBuilderFactory` to customize what kind of ability the `generateAbility` method will return. By default it'll use a `@casl/ability` builder.

You can also register to some hooks for each engine instance.
See `lib/engine/hooks.js` -> `createEngineHooks` for available hooks.

```javascript
const permissions = require('@strapi/permissions');

const engine = permissions.engine
  .new({ providers })
  .on('before-format::validate.permission', ({ permission }) => {
    if (permission.action === 'read') {
      return false;
    }
  });

const ability = await engine.generateAbility([
  { action: 'read' },
  { action: 'delete', subject: 'foo' },
  { action: 'update', subject: 'bar', properties: { fields: ['foobar'] } },
  {
    action: 'create',
    subject: 'foo',
    properties: { fields: ['foobar'] },
    conditions: ['isAuthor'],
  },
]);

ability.can('read'); // false since the validation hook prevents the engine from registering the permission
ability.can('publish'); // false
ability.can('update', 'foo'); // false
ability.can('update', 'bar'); // true
```

The `format.permission` hook can be used to modify the permission.

```javascript
const permissions = require('@strapi/permissions');

const engine = permissions.engine
  .new({ providers })
  .on('before-format::validate.permission', ({ permission }) => {
    if (permission.action === 'modify') {
      return false;
    }
  })
  .on('after-format::validate.permission', ({ permission }) => {
    if (permission.action === 'update') {
      return false;
    }
  })
  .on('format.permission', ({ permission }) => {
    if (permission.action === 'update') {
      return {
        ...permission,
        action: 'modify',
      };
    }
    if (permission.action === 'delete') {
      return {
        ...permission,
        action: 'remove',
      };
    }
    return permission;
  });

const ability = await engine.generateAbility([{ action: 'update' }, { action: 'delete' }]);

ability.can('update'); // false
ability.can('modify'); // true, because create was changed to 'modify'

ability.can('delete'); // false, doesn't exist because it was changed by format.permission
ability.can('remove'); // true, before-format::validate.permission validates before format.permission changed it
```

---
_Source: https://npm.io/package/@strapi/permissions · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
