GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration
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.

4215 vulnerabilities reference this CWE, most recent first.

GHSA-C9HW-VRGH-HH3M

Vulnerability from github – Published: 2026-07-09 06:31 – Updated: 2026-07-09 06:31
VLAI
Details

The Divi Form Builder plugin for WordPress is vulnerable to Missing Authorization in versions up to, and including, 5.1.8. This is due to the update_user() function accepting a user ID parameter from form submissions without verifying that the authenticated user has permission to edit that specific user account, and the handle_register_submission() function only checking if any user is logged in rather than validating permissions for the target user. This makes it possible for authenticated attackers, with subscriber-level access and above, to change the email address and password of any user account, including administrators, resulting in complete account takeover.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-5523"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-09T06:16:21Z",
    "severity": "HIGH"
  },
  "details": "The Divi Form Builder plugin for WordPress is vulnerable to Missing Authorization in versions up to, and including, 5.1.8. This is due to the update_user() function accepting a user ID parameter from form submissions without verifying that the authenticated user has permission to edit that specific user account, and the handle_register_submission() function only checking if any user is logged in rather than validating permissions for the target user. This makes it possible for authenticated attackers, with subscriber-level access and above, to change the email address and password of any user account, including administrators, resulting in complete account takeover.",
  "id": "GHSA-c9hw-vrgh-hh3m",
  "modified": "2026-07-09T06:31:59Z",
  "published": "2026-07-09T06:31:59Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-5523"
    },
    {
      "type": "WEB",
      "url": "https://diviengine.com/divi-form-builder-changelog"
    },
    {
      "type": "WEB",
      "url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/cb158acc-69d7-4a7d-b356-7de1f6b37019?source=cve"
    }
  ],
  "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-C9M9-282W-83CP

Vulnerability from github – Published: 2026-09-15 03:30 – Updated: 2026-09-15 03:30
VLAI
Details

Soft Serve versions 0.7.1 through 0.11.6 fail to scope Git LFS lock queries by repository, allowing authenticated users to read lock metadata from repositories they cannot access. Attackers with write access to any repository can enumerate lock IDs globally to recover locked file paths, usernames, and lock timestamps from private repositories.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-91773"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-09-15T02:16:50Z",
    "severity": "MODERATE"
  },
  "details": "Soft Serve versions 0.7.1 through 0.11.6 fail to scope Git LFS lock queries by repository, allowing authenticated users to read lock metadata from repositories they cannot access. Attackers with write access to any repository can enumerate lock IDs globally to recover locked file paths, usernames, and lock timestamps from private repositories.",
  "id": "GHSA-c9m9-282w-83cp",
  "modified": "2026-09-15T03:30:30Z",
  "published": "2026-09-15T03:30:30Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/charmbracelet/soft-serve/security/advisories/GHSA-xqg9-4q65-m2wf"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-91773"
    },
    {
      "type": "WEB",
      "url": "https://github.com/charmbracelet/soft-serve/commit/e34914699128c937afad167d43ccb5310e48b319"
    },
    {
      "type": "WEB",
      "url": "https://github.com/charmbracelet/soft-serve"
    },
    {
      "type": "WEB",
      "url": "https://github.com/charmbracelet/soft-serve/blob/v0.11.6/pkg/store/database/lfs.go#L115-L124"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/soft-serve-0.7.1-through-0.11.6-information-disclosure-via-lfs-locks"
    }
  ],
  "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:L/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-CC7F-7QRJ-R4V2

Vulnerability from github – Published: 2024-09-06 15:32 – Updated: 2026-06-03 18:33
VLAI
Details

Exposure of Sensitive Information to an Unauthorized Actor vulnerability in Ariva Computer Accord ORS allows Retrieve Embedded Sensitive Data.This issue affects Accord ORS: before 7.3.2.1.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-1744"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-200",
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-09-06T13:15:03Z",
    "severity": "CRITICAL"
  },
  "details": "Exposure of Sensitive Information to an Unauthorized Actor vulnerability in Ariva Computer Accord ORS allows Retrieve Embedded Sensitive Data.This issue affects Accord ORS: before 7.3.2.1.",
  "id": "GHSA-cc7f-7qrj-r4v2",
  "modified": "2026-06-03T18:33:05Z",
  "published": "2024-09-06T15:32:58Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-1744"
    },
    {
      "type": "WEB",
      "url": "https://siberguvenlik.gov.tr/guvenlik-bildirimleri/detay/tr-24-1408"
    },
    {
      "type": "WEB",
      "url": "https://www.usom.gov.tr/bildirim/tr-24-1408"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:H/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-CC7G-VFW3-M4MR

Vulnerability from github – Published: 2026-02-06 03:30 – Updated: 2026-02-06 03:30
VLAI
Details

The Timeline Block – Beautiful Timeline Builder for WordPress (Vertical & Horizontal Timelines) plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 1.3.3 via the tlgb_shortcode() function due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with Author-level access and above, to disclose private timeline content via the id attribute supplied to the 'timeline_block' shortcode.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-1228"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-02-06T03:15:48Z",
    "severity": "MODERATE"
  },
  "details": "The Timeline Block \u2013 Beautiful Timeline Builder for WordPress (Vertical \u0026 Horizontal Timelines) plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 1.3.3 via the tlgb_shortcode() function due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with Author-level access and above, to disclose private timeline content via the id attribute supplied to the \u0027timeline_block\u0027 shortcode.",
  "id": "GHSA-cc7g-vfw3-m4mr",
  "modified": "2026-02-06T03:30:19Z",
  "published": "2026-02-06T03:30:19Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-1228"
    },
    {
      "type": "WEB",
      "url": "https://plugins.trac.wordpress.org/changeset/3446078/timeline-block-block"
    },
    {
      "type": "WEB",
      "url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/cecebfd0-c2af-4150-8793-299cdbeaa7b9?source=cve"
    }
  ],
  "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"
    }
  ]
}

GHSA-CCC2-WRMM-MGWP

Vulnerability from github – Published: 2026-06-11 12:32 – Updated: 2026-06-11 12:32
VLAI
Details

Cerebrate before version 1.37 allowed the id primary key field to be supplied through request input during CRUD edit operations and certain custom entity patching flows. In affected entities that did not explicitly mark id as inaccessible, an authenticated attacker could submit a crafted edit request containing the id of another record, causing the save operation to update that unrelated record instead of the record identified by the route parameter. The issue affected several entity types inheriting permissive mass-assignment defaults, including User, Role, UserSetting, LocalTool, PermissionLimitation, and EnumerationCollection. Since UserSettings edit functionality was reachable by any authenticated user, exploitation could allow unauthorized modification of records within the same entity type, with impact depending on the affected endpoint and writable fields. Cerebrate 1.37 fixes this by stripping id from request input after marshalling callbacks and by globally marking id as inaccessible in the base AppModel entity.

The discovery of those potential vulnerabilities are inherited from initial finding from Jeroen Pinoy additional support from AI-Assisted Optus 4.8 (the commit wrongly assign Claude Fable 5 as the model switched) and coordinated by Andras Iklody.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-53911"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-06-11T10:16:21Z",
    "severity": "MODERATE"
  },
  "details": "Cerebrate before version 1.37 allowed the id primary key field to be supplied through request input during CRUD edit operations and certain custom entity patching flows. In affected entities that did not explicitly mark id as inaccessible, an authenticated attacker could submit a crafted edit request containing the id of another record, causing the save operation to update that unrelated record instead of the record identified by the route parameter. The issue affected several entity types inheriting permissive mass-assignment defaults, including User, Role, UserSetting, LocalTool, PermissionLimitation, and EnumerationCollection. Since UserSettings edit functionality was reachable by any authenticated user, exploitation could allow unauthorized modification of records within the same entity type, with impact depending on the affected endpoint and writable fields. Cerebrate 1.37 fixes this by stripping id from request input after marshalling callbacks and by globally marking id as inaccessible in the base AppModel entity.\n\nThe discovery of those potential vulnerabilities are inherited from initial finding from Jeroen Pinoy additional support from AI-Assisted Optus 4.8 (the commit wrongly assign Claude Fable 5 as the model switched) and coordinated by Andras Iklody.",
  "id": "GHSA-ccc2-wrmm-mgwp",
  "modified": "2026-06-11T12:32:44Z",
  "published": "2026-06-11T12:32:44Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-53911"
    },
    {
      "type": "WEB",
      "url": "https://github.com/cerebrate-project/cerebrate/commit/b3c8f951b0634f05691339512ef06cc261afecaf"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:N/SC:N/SI:H/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-CCG5-9C8W-XH6V

Vulnerability from github – Published: 2026-09-09 18:01 – Updated: 2026-09-09 18:01
VLAI
Summary
SQLAdmin: Unvalidated sortBy parameter in `ModelView` bypasses `column_sortable_list`
Details

Summary

ModelView.sort_query() uses the attacker-controlled sortBy list-view query parameter without checking it against the configured column_sortable_list allow-list. The value is resolved with getattr(model, ...) and fed into relationship joins and order_by(), so a request can sort by any column of the model — including ones hidden from column_list — and, via a dotted path, by columns of related models. Because row order then reflects the value of an unexposed column, this is an information-exposure ordering oracle.

Root cause

column_sortable_list is consulted only in the list template to decide which header links to render; the server never enforces it, so removing a column from the UI does not prevent sorting by it.

Exploitation

A single request leaks the relative ordering of an unexposed column; the ascdesc reversal confirms rows are ordered by the secret's actual value. Pairing sortBy with searchable/filterable columns and pagination can narrow the oracle toward specific values, though value recovery is conditional on having a filterable target column.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "sqladmin"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.27.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-54529"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-20",
      "CWE-200",
      "CWE-248",
      "CWE-639"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-09-09T18:01:56Z",
    "nvd_published_at": null,
    "severity": "MODERATE"
  },
  "details": "## Summary\n\n`ModelView.sort_query()` uses the attacker-controlled `sortBy` list-view query parameter without checking it against the configured `column_sortable_list` allow-list. The value is resolved with `getattr(model, ...)` and fed into relationship joins and `order_by()`, so a request can sort by **any** column of the model \u2014 including ones hidden from `column_list` \u2014 and, via a dotted path, by columns of related models. Because row order then reflects the value of an unexposed column, this is an information-exposure **ordering oracle**.\n\n## Root cause\n\n`column_sortable_list` is consulted only in the list template to decide which header links to render; the server never enforces it, so removing a column from the UI does not prevent sorting by it.\n\n## Exploitation\n\nA single request leaks the relative ordering of an unexposed column; the `asc`\u2194`desc` reversal confirms rows are ordered by the secret\u0027s actual value. Pairing `sortBy` with searchable/filterable columns and pagination can narrow the oracle toward specific values, though value recovery is conditional on having a filterable target column.",
  "id": "GHSA-ccg5-9c8w-xh6v",
  "modified": "2026-09-09T18:01:56Z",
  "published": "2026-09-09T18:01:56Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/smithyhq/sqladmin/security/advisories/GHSA-ccg5-9c8w-xh6v"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/smithyhq/sqladmin"
    },
    {
      "type": "WEB",
      "url": "https://github.com/smithyhq/sqladmin/releases/tag/0.27.1"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "SQLAdmin: Unvalidated sortBy parameter in `ModelView` bypasses `column_sortable_list`"
}

GHSA-CCGQ-FX7H-2V4C

Vulnerability from github – Published: 2026-09-15 18:32 – Updated: 2026-09-15 18:32
VLAI
Details

Vikunja before 2.6.0 fails to validate that user-supplied project_view_id in task-position requests belongs to the task's project. Authenticated attackers can insert task position rows into arbitrary other tenant project views via POST or PUT task-position endpoints.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-91984"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-09-15T16:17:55Z",
    "severity": "MODERATE"
  },
  "details": "Vikunja before 2.6.0 fails to validate that user-supplied project_view_id in task-position requests belongs to the task\u0027s project. Authenticated attackers can insert task position rows into arbitrary other tenant project views via POST or PUT task-position endpoints.",
  "id": "GHSA-ccgq-fx7h-2v4c",
  "modified": "2026-09-15T18:32:30Z",
  "published": "2026-09-15T18:32:30Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/go-vikunja/vikunja/security/advisories/GHSA-w39f-h553-h2mx"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-91984"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/vikunja-before-2.6.0-broken-object-level-authorization-via-task-position"
    }
  ],
  "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"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/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-CCGV-2JPF-98M2

Vulnerability from github – Published: 2026-08-27 18:32 – Updated: 2026-08-27 18:32
VLAI
Details

Affected versions of Flowintel contain an insecure direct object reference / broken object-level authorization issue across numerous task endpoints.

The routes generally received both a case identifier and a task identifier, but previously they did not enforce that the task actually belonged to the supplied case. As a result, an authenticated user with editor-level access to one case could potentially substitute the ID of a task from another case and invoke operations against that foreign task.

The patch introduces task_case_bound_required, which loads both objects and returns 404 unless the task belongs to the requested case. This protection is applied to edit, delete, note, assignment, status, file, export, MISP-linking, subtask, external-reference, and other task-related endpoints.

The fix also adds explicit checks that a requested note_id belongs to the current task before returning or exporting it, closing related cross-object access paths.

Version impacted =>3.3.0

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-81817"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-08-27T17:21:05Z",
    "severity": "HIGH"
  },
  "details": "Affected versions of Flowintel contain an insecure direct object reference / broken object-level authorization issue across numerous task endpoints.\n\n\nThe routes generally received both a case identifier and a task identifier, but previously they did not enforce that the task actually belonged to the supplied case. As a result, an authenticated user with editor-level access to one case could potentially substitute the ID of a task from another case and invoke operations against that foreign task.\n\n\nThe patch introduces task_case_bound_required, which loads both objects and returns 404 unless the task belongs to the requested case. This protection is applied to edit, delete, note, assignment, status, file, export, MISP-linking, subtask, external-reference, and other task-related endpoints.\n\nThe fix also adds explicit checks that a requested note_id belongs to the current task before returning or exporting it, closing related cross-object access paths.\n\nVersion impacted =\u003e3.3.0",
  "id": "GHSA-ccgv-2jpf-98m2",
  "modified": "2026-08-27T18:32:30Z",
  "published": "2026-08-27T18:32:30Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-81817"
    },
    {
      "type": "WEB",
      "url": "https://github.com/flowintel/flowintel/commit/10676eec7f1286d7ee0769546c772c5cb9c1c72b.patch"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:L/VI:H/VA:L/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-CCHP-3RQ6-69WJ

Vulnerability from github – Published: 2024-06-21 09:30 – Updated: 2025-03-24 21:45
VLAI
Summary
events2 TYPO3 extension insecure direct object reference (IDOR) vulnerability
Details

An issue was discovered in the events2 (aka Events 2) extension before 8.3.8 and 9.x before 9.0.6 for TYPO3. Missing access checks in the management plugin lead to an insecure direct object reference (IDOR) vulnerability with the potential to activate or delete various events for unauthenticated users.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "jweiland/events2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "8.3.8"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "jweiland/events2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "9.0.0"
            },
            {
              "fixed": "9.0.6"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2024-38874"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639",
      "CWE-693"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2024-06-21T15:07:37Z",
    "nvd_published_at": "2024-06-21T07:15:10Z",
    "severity": "MODERATE"
  },
  "details": "An issue was discovered in the events2 (aka Events 2) extension before 8.3.8 and 9.x before 9.0.6 for TYPO3. Missing access checks in the management plugin lead to an insecure direct object reference (IDOR) vulnerability with the potential to activate or delete various events for unauthenticated users.",
  "id": "GHSA-cchp-3rq6-69wj",
  "modified": "2025-03-24T21:45:07Z",
  "published": "2024-06-21T09:30:26Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-38874"
    },
    {
      "type": "WEB",
      "url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/jweiland/events2/CVE-2024-38874.yaml"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/jweiland-net/events2"
    },
    {
      "type": "WEB",
      "url": "https://typo3.org/security/advisory/typo3-ext-sa-2024-003"
    }
  ],
  "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:L",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:L/VA:L/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "events2 TYPO3 extension insecure direct object reference (IDOR) vulnerability"
}

GHSA-CFH6-PV5C-38JV

Vulnerability from github – Published: 2026-08-18 20:51 – Updated: 2026-08-18 20:51
VLAI
Summary
Lemur: Unchecked `replaces[]` lets any user silence notifications and hijack auto-rotation for arbitrary certificates
Details

Summary

Repo under test: https://github.com/Netflix/lemur

The certificate create and upload endpoints accept a replaces[] (alias replacements) array that is resolved to live Certificate ORM objects with no ownership or CertificatePermission check on the referenced certificates. The SQLAlchemy Certificate.replaces append listener then immediately sets victim.notify = False and populates victim.replaced. From that point the victim certificate is excluded from auto-reissue, its expiration notifications are silenced, and the periodic certificate_rotate Celery task deploys the attacker's certificate (endpoint.certificate.replaced[0]) onto every endpoint serving the victim certificate.

Any authenticated non-read-only user can therefore silently substitute their own certificate onto production load balancers and Kubernetes secrets they hold no role on, while suppressing the legitimate certificate's lifecycle automation.

Affected route

POST /api/1/certificates POST /api/1/certificates/upload PUT /api/1/certificates/<id>

Affected code

Impact

An authenticated insider or holder of a stolen low-privilege token can, without holding any role on a target certificate:

  1. Upload a self-signed or attacker-minted certificate listing arbitrary high-value production certificate IDs in replaces.
  2. Immediately disable expiration notifications and auto-reissue for those production certificates.
  3. On the next scheduled certificate_rotate Celery run, have the attacker's certificate pushed to every endpoint (AWS ELB/CloudFront/ACM, Kubernetes, SFTP, etc.) currently serving the victim certificate, while the legitimate certificate is detached.

Minimum impact is fleet-wide TLS denial of service equivalent to mass revocation. Where internal clients trust the substituted chain (or combined with the sub-CA finding LEMUR-BUG-07), it escalates to TLS interception. This directly violates the invariant that a user may only modify or revoke a certificate if they are its owner, a member of an owning role, or an administrator.

Root cause

AssociatedCertificateSchema.get_object calls fetch_objects(Certificate, data) and returns the ORM rows verbatim. No caller on the create/upload/edit path iterates the resolved replaces list to enforce CertificatePermission before the model assigns them, and the Certificate.replaces append event listener mutates the victim row (notify = False) as a side effect of ORM collection assignment. The direct revoke endpoint does enforce CertificatePermission, but this replaces path achieves an equivalent or worse outcome while bypassing it entirely.

Validated evidence

Static trace, confirmed by code inspection (validation status: CONFIRMED):

  • replaces is accepted in CertificateInputSchema / CertificateUploadInputSchema and resolved via fetch_objects(Certificate, ...) with no per-object authorization.
  • grep -n CertificatePermission lemur/certificates/views.py shows the check is applied to PUT/DELETE/revoke/export paths but never to the replaces payload of POST /certificates or POST /certificates/upload.
  • The Celery certificate_rotate task and cli.rotate() consume Endpoint.replaced.any() unconditionally and deploy replaced[0] with commit=True.

Proof of concept / reproducer

Status: reconstructed from source report (static control-flow trace; not executed against a live CA).

Preconditions: attacker is an authenticated Lemur user holding any role other than read-only (default StrictRolePermission config). <VICTIM_CERT_ID> is any certificate id readable via GET /api/1/certificates.

# 1. Upload an attacker-controlled cert that "replaces" the victim
curl -sS -X POST "<TARGET_BASE_URL>/api/1/certificates/upload" \
  -H "Authorization: Bearer <AUTH_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
        "name": "attacker-replacement",
        "owner": "attacker@example.com",
        "body": "-----BEGIN CERTIFICATE-----\n<ATTACKER_CERT_PEM>\n-----END CERTIFICATE-----",
        "privateKey": "-----BEGIN PRIVATE KEY-----\n<ATTACKER_KEY_PEM>\n-----END PRIVATE KEY-----",
        "replaces": [{"id": <VICTIM_CERT_ID>}]
      }'

# 2. Observe victim.notify is now false and victim is queued for rotation
curl -sS "<TARGET_BASE_URL>/api/1/certificates/<VICTIM_CERT_ID>" \
  -H "Authorization: Bearer <AUTH_TOKEN>" | jq '.notify, .replaced'

# 3. On the next certificate_rotate Celery beat tick, the attacker cert is
#    deployed to every endpoint that was serving <VICTIM_CERT_ID>.

Static-trace validation command from the source report:

grep -n 'replaces' lemur/certificates/schemas.py lemur/certificates/views.py lemur/schemas.py \
  && grep -n 'CertificatePermission' lemur/certificates/views.py

Source artifact: audit/harnesses/public-repo-threat-model-harness/results/netflix-lemur-100run-mythos-20260627T051129Z/findings.jsonl (run_083, finding cluster lemur-replaces-unauth, 7/100 runs).

Suggested fix

Before persisting replaces/replacements on certificate create, upload, and edit, iterate each referenced certificate and enforce the same CertificatePermission(owner_role, cert.roles) check used by the revoke endpoint (views.py:1677-1685); reject with 403 if the caller is not creator/owner/role-member/admin for any target. Additionally, move the value.notify = False side effect out of the SQLAlchemy append listener so an authorization failure cannot leave a victim certificate partially mutated, and emit an audit_log entry whenever a certificate is marked as replaced.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.9.2"
      },
      "package": {
        "ecosystem": "PyPI",
        "name": "lemur"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.5.0"
            },
            {
              "fixed": "1.9.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-71308"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-639",
      "CWE-862"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-08-18T20:51:33Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "## Summary\n\nRepo under test: https://github.com/Netflix/lemur\n\nThe certificate create and upload endpoints accept a `replaces[]` (alias `replacements`) array that is resolved to live `Certificate` ORM objects with no ownership or `CertificatePermission` check on the referenced certificates. The SQLAlchemy `Certificate.replaces` append listener then immediately sets `victim.notify = False` and populates `victim.replaced`. From that point the victim certificate is excluded from auto-reissue, its expiration notifications are silenced, and the periodic `certificate_rotate` Celery task deploys the attacker\u0027s certificate (`endpoint.certificate.replaced[0]`) onto every endpoint serving the victim certificate.\n\nAny authenticated non-read-only user can therefore silently substitute their own certificate onto production load balancers and Kubernetes secrets they hold no role on, while suppressing the legitimate certificate\u0027s lifecycle automation.\n\n## Affected route\n\n`POST /api/1/certificates`\n`POST /api/1/certificates/upload`\n`PUT /api/1/certificates/\u003cid\u003e`\n\n## Affected code\n\n- [`lemur/certificates/schemas.py:402`](https://github.com/Netflix/lemur/blob/main/lemur/certificates/schemas.py#L402) \u2014 `replaces = fields.Nested(AssociatedCertificateSchema, missing=[], many=True)` accepted on create/upload/edit\n- [`lemur/schemas.py:152`](https://github.com/Netflix/lemur/blob/main/lemur/schemas.py#L152) \u2014 `AssociatedCertificateSchema` resolves any certificate by id/name via `fetch_objects(Certificate, data)` with no permission check\n- [`lemur/certificates/views.py:651`](https://github.com/Netflix/lemur/blob/main/lemur/certificates/views.py#L651) \u2014 only `StrictRolePermission().can()` gates `/certificates/upload`; no check on `data[\u0027replaces\u0027]`\n- [`lemur/certificates/models.py:506`](https://github.com/Netflix/lemur/blob/main/lemur/certificates/models.py#L506) \u2014 `@event.listens_for(Certificate.replaces, \u0027append\u0027)` sets `value.notify = False` on the victim\n- [`lemur/certificates/service.py:277`](https://github.com/Netflix/lemur/blob/main/lemur/certificates/service.py#L277) \u2014 `get_all_pending_reissue()` filters `not_(Certificate.replaced.any())`, excluding the victim\n- [`lemur/certificates/cli.py:347`](https://github.com/Netflix/lemur/blob/main/lemur/certificates/cli.py#L347) \u2014 `request_rotation(endpoint, endpoint.certificate.replaced[0], message, commit)` deploys the attacker cert\n- [`lemur/common/celery.py:638`](https://github.com/Netflix/lemur/blob/main/lemur/common/celery.py#L638) \u2014 periodic `certificate_rotate` task runs `cli_certificate.rotate(..., commit=True)`\n- [`lemur/deployment/service.py:17`](https://github.com/Netflix/lemur/blob/main/lemur/deployment/service.py#L17) \u2014 `endpoint.source.plugin.update_endpoint(endpoint, new_cert)` pushes to ELB/CloudFront/ACM/K8s\n\n## Impact\n\nAn authenticated insider or holder of a stolen low-privilege token can, without holding any role on a target certificate:\n\n1. Upload a self-signed or attacker-minted certificate listing arbitrary high-value production certificate IDs in `replaces`.\n2. Immediately disable expiration notifications and auto-reissue for those production certificates.\n3. On the next scheduled `certificate_rotate` Celery run, have the attacker\u0027s certificate pushed to every endpoint (AWS ELB/CloudFront/ACM, Kubernetes, SFTP, etc.) currently serving the victim certificate, while the legitimate certificate is detached.\n\nMinimum impact is fleet-wide TLS denial of service equivalent to mass revocation. Where internal clients trust the substituted chain (or combined with the sub-CA finding LEMUR-BUG-07), it escalates to TLS interception. This directly violates the invariant that a user may only modify or revoke a certificate if they are its owner, a member of an owning role, or an administrator.\n\n## Root cause\n\n`AssociatedCertificateSchema.get_object` calls `fetch_objects(Certificate, data)` and returns the ORM rows verbatim. No caller on the create/upload/edit path iterates the resolved `replaces` list to enforce `CertificatePermission` before the model assigns them, and the `Certificate.replaces` append event listener mutates the victim row (`notify = False`) as a side effect of ORM collection assignment. The direct revoke endpoint *does* enforce `CertificatePermission`, but this `replaces` path achieves an equivalent or worse outcome while bypassing it entirely.\n\n## Validated evidence\n\nStatic trace, confirmed by code inspection (validation status: `CONFIRMED`):\n\n- `replaces` is accepted in `CertificateInputSchema` / `CertificateUploadInputSchema` and resolved via `fetch_objects(Certificate, ...)` with no per-object authorization.\n- `grep -n CertificatePermission lemur/certificates/views.py` shows the check is applied to `PUT`/`DELETE`/`revoke`/`export` paths but never to the `replaces` payload of `POST /certificates` or `POST /certificates/upload`.\n- The Celery `certificate_rotate` task and `cli.rotate()` consume `Endpoint.replaced.any()` unconditionally and deploy `replaced[0]` with `commit=True`.\n\n## Proof of concept / reproducer\n\nStatus: reconstructed from source report (static control-flow trace; not executed against a live CA).\n\nPreconditions: attacker is an authenticated Lemur user holding any role other than `read-only` (default `StrictRolePermission` config). `\u003cVICTIM_CERT_ID\u003e` is any certificate id readable via `GET /api/1/certificates`.\n\n```bash\n# 1. Upload an attacker-controlled cert that \"replaces\" the victim\ncurl -sS -X POST \"\u003cTARGET_BASE_URL\u003e/api/1/certificates/upload\" \\\n  -H \"Authorization: Bearer \u003cAUTH_TOKEN\u003e\" \\\n  -H \"Content-Type: application/json\" \\\n  -d \u0027{\n        \"name\": \"attacker-replacement\",\n        \"owner\": \"attacker@example.com\",\n        \"body\": \"-----BEGIN CERTIFICATE-----\\n\u003cATTACKER_CERT_PEM\u003e\\n-----END CERTIFICATE-----\",\n        \"privateKey\": \"-----BEGIN PRIVATE KEY-----\\n\u003cATTACKER_KEY_PEM\u003e\\n-----END PRIVATE KEY-----\",\n        \"replaces\": [{\"id\": \u003cVICTIM_CERT_ID\u003e}]\n      }\u0027\n\n# 2. Observe victim.notify is now false and victim is queued for rotation\ncurl -sS \"\u003cTARGET_BASE_URL\u003e/api/1/certificates/\u003cVICTIM_CERT_ID\u003e\" \\\n  -H \"Authorization: Bearer \u003cAUTH_TOKEN\u003e\" | jq \u0027.notify, .replaced\u0027\n\n# 3. On the next certificate_rotate Celery beat tick, the attacker cert is\n#    deployed to every endpoint that was serving \u003cVICTIM_CERT_ID\u003e.\n```\n\nStatic-trace validation command from the source report:\n\n```bash\ngrep -n \u0027replaces\u0027 lemur/certificates/schemas.py lemur/certificates/views.py lemur/schemas.py \\\n  \u0026\u0026 grep -n \u0027CertificatePermission\u0027 lemur/certificates/views.py\n```\n\nSource artifact: `audit/harnesses/public-repo-threat-model-harness/results/netflix-lemur-100run-mythos-20260627T051129Z/findings.jsonl` (run_083, finding cluster `lemur-replaces-unauth`, 7/100 runs).\n\n## Suggested fix\n\nBefore persisting `replaces`/`replacements` on certificate create, upload, and edit, iterate each referenced certificate and enforce the same `CertificatePermission(owner_role, cert.roles)` check used by the revoke endpoint ([`views.py:1677-1685`](https://github.com/Netflix/lemur/blob/main/lemur/certificates/views.py#L1677)); reject with 403 if the caller is not creator/owner/role-member/admin for any target. Additionally, move the `value.notify = False` side effect out of the SQLAlchemy append listener so an authorization failure cannot leave a victim certificate partially mutated, and emit an `audit_log` entry whenever a certificate is marked as replaced.",
  "id": "GHSA-cfh6-pv5c-38jv",
  "modified": "2026-08-18T20:51:33Z",
  "published": "2026-08-18T20:51:33Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/Netflix/lemur/security/advisories/GHSA-cfh6-pv5c-38jv"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Netflix/lemur/commit/286874535160952143b0afe2d356642669f9d4c6"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/Netflix/lemur"
    },
    {
      "type": "WEB",
      "url": "https://github.com/Netflix/lemur/releases/tag/v1.9.3"
    }
  ],
  "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:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Lemur: Unchecked `replaces[]` lets any user silence notifications and hijack auto-rotation for arbitrary certificates"
}

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.