Common Weakness Enumeration

CWE-613

Allowed-with-Review

Insufficient Session Expiration

Abstraction: Base · Status: Incomplete

According to WASC, "Insufficient Session Expiration is when a web site permits an attacker to reuse old session credentials or session IDs for authorization."

1083 vulnerabilities reference this CWE, most recent first.

GHSA-85R2-J732-H557

Vulnerability from github – Published: 2026-06-30 21:31 – Updated: 2026-06-30 21:31
VLAI
Details

IBM DevOps Automation 1.0.1 and IBM DevOps Loop 1.0.2 does not invalidate session IDs after expiration which could allow an authenticated user to impersonate another user on the system.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2025-36359"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-06-30T21:16:30Z",
    "severity": "HIGH"
  },
  "details": "IBM DevOps Automation 1.0.1 and IBM DevOps Loop 1.0.2 does not invalidate session IDs after expiration which could allow an authenticated user to impersonate another user on the system.",
  "id": "GHSA-85r2-j732-h557",
  "modified": "2026-06-30T21:31:45Z",
  "published": "2026-06-30T21:31:45Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-36359"
    },
    {
      "type": "WEB",
      "url": "https://www.ibm.com/support/pages/node/7277970"
    }
  ],
  "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"
    }
  ]
}

GHSA-8863-4QMG-FR45

Vulnerability from github – Published: 2025-01-08 09:30 – Updated: 2025-01-08 16:14
VLAI
Summary
Apache Airflow Fab Provider Insufficient Session Expiration vulnerability
Details

Insufficient Session Expiration vulnerability in Apache Airflow Fab Provider.

This issue affects Apache Airflow Fab Provider: before 1.5.2.

When user password has been changed with admin CLI, the sessions for that user have not been cleared, leading to insufficient session expiration, thus logged users could continue to be logged in even after the password was changed. This only happened when the password was changed with CLI. The problem does not happen in case change was done with webserver thus this is different from CVE-2023-40273 which was addressed in Apache-Airflow 2.7.0

Users are recommended to upgrade to version 1.5.2, which fixes the issue.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "apache-airflow-providers-fab"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.5.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2024-45033"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-01-08T16:14:43Z",
    "nvd_published_at": "2025-01-08T09:15:07Z",
    "severity": "LOW"
  },
  "details": "Insufficient Session Expiration vulnerability in Apache Airflow Fab Provider.\n\nThis issue affects Apache Airflow Fab Provider: before 1.5.2.\n\nWhen user password has been changed with admin CLI, the sessions for that user have not been cleared, leading to insufficient session expiration, thus logged users could continue to be logged in even after the password was changed. This only happened when the password was changed with CLI. The problem does not happen in case change was done with webserver thus this is different from\u00a0[CVE-2023-40273](https://github.com/advisories/GHSA-pm87-24wq-r8w9)\u00a0which was addressed in Apache-Airflow 2.7.0\n\n\nUsers are recommended to upgrade to version 1.5.2, which fixes the issue.",
  "id": "GHSA-8863-4qmg-fr45",
  "modified": "2025-01-08T16:14:43Z",
  "published": "2025-01-08T09:30:38Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-45033"
    },
    {
      "type": "WEB",
      "url": "https://github.com/apache/airflow/pull/45139"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/apache/airflow"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread/yw535346rk766ybzpqtvrl36sjj789st"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:P/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Apache Airflow Fab Provider Insufficient Session Expiration vulnerability"
}

GHSA-889W-M37P-88M5

Vulnerability from github – Published: 2026-10-09 17:09 – Updated: 2026-10-09 17:09
VLAI
Summary
pyLoad: Api.set_user_permission never invalidates the target's session
Details

Summary

An admin who revokes or downgrades a non-admin user's permissions through pyLoad's own documented /api/<func> RPC surface — e.g. POST /api/set_user_permission (or its legacy alias /api/setUserPermission) — updates the target's database row but never invalidates that user's existing Flask cookie session. The demoted user keeps their pre-revocation role/permission bits on every subsequent WebUI page load and every subsequent /api/<func> call made with that cookie, for up to the default session_lifetime of ~31 days, or until they voluntarily log out. No action by the demoted user is required beyond already being logged in at the time of revocation.

Details

The vulnerable method, verbatim, at src/pyload/core/api/__init__.py:1652-1656:

    @legacy("setUserPermission")
    @post
    def set_user_permission(self, user: str, permission: int, role: int) -> None:
        self.pyload.db.set_permission(user, permission)
        self.pyload.db.set_role(user, role)

It carries no @permission(...) decorator and its body never calls clear_all_user_sessions or any other session-invalidation routine.

The only call site in the entire codebase that pairs a permission/role change with clear_all_user_sessions is the WebUI's update_users() route, src/pyload/webui/app/blueprints/json_blueprint.py:442-444:

        api.set_user_permission(name, data["permission"], data["role"])
        if was_changed:
            clear_all_user_sessions(name)

A repo-wide grep for set_user_permission|setUserPermission returns exactly 3 hits: the @legacy alias registration (core/api/__init__.py:1652), the method definition itself (:1654), and this one call site (json_blueprint.py:442). No other caller exists.

pyLoad's own public RPC dispatcher reaches Api.set_user_permission directly, bypassing json_blueprint.py entirely. src/pyload/webui/app/blueprints/api_blueprint.py:21-26 registers rpc(func, args="") on /api/<func> and /api/<func>/<args> for GET/POST; line 68 dispatches with response = jsonify(getattr(api, func)(**json_request_body)) — i.e. it invokes any method on the Api object by name, including set_user_permission (also reachable via form/multipart bodies at :72/:77). The only authorization gate before that dispatch, at api_blueprint.py:50, is:

if not api.is_authorized(func, {"role": user_info["role"], "permission": user_info["permission"]}):

is_authorized (core/api/__init__.py:1419-1432) returns True outright when the caller's role is Role.ADMIN; otherwise it requires func_name in perm_map. set_user_permission has no @permission decorator, so it is absent from perm_map (the module comment at core/api/__init__.py:37 states "unlisted functions are for admins only"). This gate concerns only the caller's own authorization — it says nothing about, and never touches, the target user's existing session.

The stale session survives

The demoted user's session was populated once, at login, and is never refreshed:

  • helpers.py:170,179,183-185 — parse_permissions(session) derives the caller's effective admin/permission bits from session.get("role") and session.get("perms").
  • These values are written once by set_session() (helpers.py:223-234), called only from app_blueprint.py:88 (login) and :100 (autologin). A repo-wide grep for before_request inside src/pyload/ returns nothing — no hook anywhere refreshes a live session from the database.
  • is_authenticated(session) (helpers.py:261-266) is exactly: user = session.get("name") authenticated = session.get("authenticated", False) return authenticated and api.user_exists(user) It re-validates only that the username still exists — never that the session's cached role/perms still match the current database values.
  • Inside apikey_auth (helpers.py:393-404), when no X-API-Key header is supplied, flask.g.user_info is built as {"id": s["id"], "name": s["name"], "role": s["role"], "permission": s["perms"]} — straight from the same stale, login-time-cached session fields. This is exactly the user_info that api_blueprint.py:50 feeds into is_authorized() for every /api/<func> call made over a cookie session.

The exposure window is bounded, not indefinite: default.cfg:47 sets session_lifetime = 44640 (minutes, ≈31 days), wired into PERMANENT_SESSION_LIFETIME at webui/app/__init__.py:130-131, and SESSION_REFRESH_EACH_REQUEST = False at :128 means the window is a hard ~31 days from login, not extended by continued activity.

Attack Sequence

Starting privilege: an already-authenticated non-admin user, plus an admin who legitimately uses pyLoad's own documented API instead of the WebUI page.

  1. Victim user logs in normally, obtains a Flask session cookie (A) with role/perms reflecting their current (elevated) permissions.
  2. Admin revokes or downgrades the victim's permissions via POST /api/set_user_permission (or legacy POST /api/setUserPermission) with the victim's username and the new, lower permission/role values — using curl, a script, or any RPC client, rather than the WebUI's "Manage Users" HTML page. Api.set_user_permission updates pyload.db.set_permission / pyload.db.set_role and returns; no session anywhere is touched.
  3. Using cookie A (never invalidated), the victim loads any WebUI admin-gated page, or calls any /api/<func> endpoint gated only on role/permission. apikey_auth's cookie branch rebuilds user_info from the stale session fields (role/perms as of step 1), is_authorized() / parse_permissions() evaluate against those stale values, and the call succeeds as if the revocation never happened.
  4. This persists for up to ~31 days (default session_lifetime) or until the victim logs out, whichever comes first.

This sequence was confirmed against a real, locally-run pyLoad instance, not just traced from source. See Section 10 for the exact commands, real HTTP status codes and response bodies, and the precondition that the admin step here used X-API-Key header auth rather than a cookie (explained there).

Suggested Fix

Move the clear_all_user_sessions(name) call into Api.set_user_permission itself (ideally also adopting the apikey-cache purge pattern already used in remove_user, core/api/__init__.py:1626-1636), so that every entry point — WebUI and /api/<func> RPC alike — inherits session invalidation automatically, rather than requiring each caller to remember to invoke it separately.

PoC

This was executed for real against pyLoad's own code, not merely predicted from reading it. The verifier pass that produced Sections 1-9 (ghsa/CLAIMS-pyload.md) source-traced every claim but never ran a PoC; this section closes that gap.

Method and preconditions

  • Target: pyload/pyload at the pinned commit 31e341fd41d2dac9fffa3683a756edc54bcdeb77 (develop branch), installed editable (pip install -e ".[test]") into a fresh Python 3.12.3 virtualenv. No source files were modified.
  • Transport: Flask's in-process test client (app.test_client()) against the real pyload.core.Core / pyload.webui.app Flask app object, not a bound TCP server. This is the same bootstrap the project's own tests/integration/conftest.py fixture uses, and it exercises the identical route/view/decorator code (api_blueprint.rpc(), apikey_auth, is_authorized(), parse_permissions(), Flask-WTF CSRF protection) that a real 127.0.0.1:8000-bound server would run. No real network socket was opened and no third-party or public host was touched, only this locally-run copy of the target's own cloned code.
  • Two users: pyload/pyload (pyLoad's own automatically-created default admin account) and a freshly created non-admin victim user with the Perms.SETTINGS permission bit.
  • Elevated-action probe: GET /api/get_userdir (core/api/__init__.py:1434-1437, decorated @permission(Perms.SETTINGS) @get), chosen because it is gated on an ordinary non-admin permission bit and because it is a GET request, so it needs no CSRF token (Flask-WTF's WTF_CSRF_METHODS default excludes GET), keeping the reproduction focused on session staleness rather than CSRF plumbing.
  • The admin's POST /api/set_user_permission call used X-API-Key header authentication rather than a cookie. This is a precondition, not a simplification of the bug: apikey_auth (helpers.py:335-413) marks the whole /api/<func> route CSRF-exempt at decoration time, then, only in the cookie-session branch (no API key), manually calls csrf.protect() (helpers.py:397) before dispatch -- so a cookie-authenticated admin call needs a valid CSRF token, and an X-API-Key call does not (helpers.py:361-384 returns before that check is reached). This has no bearing on the vulnerability itself: Api.set_user_permission's body (core/api/__init__.py:1652-1656) does not branch on how the caller authenticated, and the is_authorized() gate that runs before it (api_blueprint.py:50) only checks the ADMIN CALLER's own role, never the target user's session. A cookie-authenticated admin request (fetching a CSRF token the same way the victim's login step does) reaches the identical code path and was not separately re-run.
  • Full script, README with exact from-nothing run instructions, and the verbatim captured output are in the evidence bundle: ghsa/poc-bundles/pyload-poc/ (zipped copy: ghsa/poc-bundles/pyload-poc.zip).

Output (ran: 2026-09-10)

STEP 1: victim logs in through the real WebUI /login route, keeping the session cookie
==============================================================================
POST /login -> status 302
Set-Cookie: ['pyload_session_8000=Kgq1peWlETCpxj4MSOSY-yxy-v3EYgIjiLxYT7kLgO0; Expires=Sun, 11 Oct 2026 12:30:51 GMT; HttpOnly; Path=/; SameSite=Lax']
victim's cached session contents right after login: role=1 perms=128 authenticated=True

==============================================================================
STEP 2: BASELINE -- victim, using cookie A, calls a SETTINGS-gated GET endpoint (/api/get_userdir, @permission(Perms.SETTINGS)) and it succeeds
==============================================================================
GET /api/get_userdir (victim cookie) -> status 200
body: "/tmp/pyload_poc_userdir_y9fl5y10"

==============================================================================
STEP 3: admin revokes the victim's permissions via pyLoad's own public /api/<func> RPC dispatcher (X-API-Key header, NOT the WebUI 'Manage Users' page, NOT json_blueprint.py's update_users())
==============================================================================
POST /api/set_user_permission (admin API key) -> status 200
body: null

==============================================================================
STEP 4: confirm via a fresh DB read that the victim's permission really is downgraded in the database
==============================================================================
victim DB row after set_user_permission: {'id': 2, 'name': 'victim', 'permission': 0, 'role': 1, 'template': 'default', 'email': ''}

==============================================================================
STEP 5 (the bug): using the victim's ORIGINAL, UNCHANGED cookie A from step 1, repeat the exact same SETTINGS-gated call
==============================================================================
GET /api/get_userdir (SAME victim cookie, post-demotion) -> status 200
body: "/tmp/pyload_poc_userdir_y9fl5y10"
RESULT: call STILL SUCCEEDS after the permission revocation. The stale cookie session retains the pre-revocation SETTINGS bit.
victim's cached session contents after admin's revocation (unchanged since login): role=1 perms=128

==============================================================================
STEP 6 (control): the SAME demoted victim, authenticating via the X-API-Key header instead of the cookie, correctly gets the NEW, reduced permission immediately
==============================================================================
GET /api/get_userdir (victim X-API-Key, post-demotion) -> status 401
body: {"error": "Access denied"}
RESULT: API-key path correctly reflects the demotion immediately (access denied), confirming the bug is cookie-session-specific.

(Log lines from pyLoad's own logger, interleaved with this output in the raw capture, are omitted here for readability; the full unedited capture, including those log lines, is output.txt in the evidence bundle.)

This matches the predicted behavior in Sections 4 and 6 exactly: the demoted victim's original cookie still returns 200 with the pre-revocation permission's data (step 5), while the same demotion is correctly and immediately visible through X-API-Key auth (step 6, 401). Nothing in the live run contradicted the source-level analysis; no additional gate blocked the bypass, and no easier bypass was found.

The run was repeated from a completely freshly built virtualenv (pip install -e ".[test]" into a new venv, no reuse of any prior install) with identical outcomes -- only the random API key values, the signed session cookie value, and the temp directory path differ between runs, as expected.

Reproduce from nothing

# starting from a pyload/pyload checkout pinned at 31e341fd41d2dac9fffa3683a756edc54bcdeb77
cd /path/to/pyload-clone-at-31e341f

python3 -m venv /tmp/pyload-poc-venv
/tmp/pyload-poc-venv/bin/pip install -U pip
/tmp/pyload-poc-venv/bin/pip install -e ".[test]"

# optional sanity check against the project's own test suite
/tmp/pyload-poc-venv/bin/python -m pytest tests/integration/test_api.py -q   # -> 12 passed

/tmp/pyload-poc-venv/bin/python3 /path/to/ghsa/poc-bundles/pyload-poc/poc_stale_session.py

Impact

The header-present branch of apikey_auth (helpers.py:370) reads role/permission fresh from the database via get_user_by_id on every request. This bug is specific to the cookie/session-based auth path (helpers.py:393-404).

pyload-poc.zip

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "PyPI",
        "name": "pyload-ng"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0.5.0b3.dev98"
            },
            {
              "last_affected": "0.5.0b3.dev101"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-10-09T17:09:07Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "### Summary\nAn admin who revokes or downgrades a non-admin user\u0027s permissions through pyLoad\u0027s own documented\n`/api/\u003cfunc\u003e` RPC surface \u2014 e.g. `POST /api/set_user_permission` (or its legacy alias\n`/api/setUserPermission`) \u2014 updates the target\u0027s database row but never invalidates that user\u0027s\nexisting Flask cookie session. The demoted user keeps their pre-revocation `role`/`permission` bits\non every subsequent WebUI page load and every subsequent `/api/\u003cfunc\u003e` call made with that cookie,\nfor up to the default `session_lifetime` of ~31 days, or until they voluntarily log out. No action\nby the demoted user is required beyond already being logged in at the time of revocation.\n\n### Details\nThe vulnerable method, verbatim, at `src/pyload/core/api/__init__.py:1652-1656`:\n\n```\n    @legacy(\"setUserPermission\")\n    @post\n    def set_user_permission(self, user: str, permission: int, role: int) -\u003e None:\n        self.pyload.db.set_permission(user, permission)\n        self.pyload.db.set_role(user, role)\n```\n\nIt carries no `@permission(...)` decorator and its body never calls `clear_all_user_sessions` or any\nother session-invalidation routine.\n\nThe **only** call site in the entire codebase that pairs a permission/role change with\n`clear_all_user_sessions` is the WebUI\u0027s `update_users()` route,\n`src/pyload/webui/app/blueprints/json_blueprint.py:442-444`:\n\n```\n        api.set_user_permission(name, data[\"permission\"], data[\"role\"])\n        if was_changed:\n            clear_all_user_sessions(name)\n```\n\nA repo-wide grep for `set_user_permission|setUserPermission` returns exactly 3 hits: the `@legacy`\nalias registration (`core/api/__init__.py:1652`), the method definition itself (`:1654`), and this one\ncall site (`json_blueprint.py:442`). No other caller exists.\n\npyLoad\u0027s own public RPC dispatcher reaches `Api.set_user_permission` directly, bypassing\n`json_blueprint.py` entirely. `src/pyload/webui/app/blueprints/api_blueprint.py:21-26` registers\n`rpc(func, args=\"\")` on `/api/\u003cfunc\u003e` and `/api/\u003cfunc\u003e/\u003cargs\u003e` for `GET`/`POST`; line 68 dispatches\nwith `response = jsonify(getattr(api, func)(**json_request_body))` \u2014 i.e. it invokes any method on\nthe `Api` object by name, including `set_user_permission` (also reachable via form/multipart bodies\nat `:72`/`:77`). The only authorization gate before that dispatch, at `api_blueprint.py:50`, is:\n\n```\nif not api.is_authorized(func, {\"role\": user_info[\"role\"], \"permission\": user_info[\"permission\"]}):\n```\n\n`is_authorized` (`core/api/__init__.py:1419-1432`) returns `True` outright when the **caller\u0027s**\nrole is `Role.ADMIN`; otherwise it requires `func_name in perm_map`. `set_user_permission` has no\n`@permission` decorator, so it is absent from `perm_map` (the module comment at `core/api/__init__.py:37`\nstates \"unlisted functions are for admins only\"). This gate concerns only the caller\u0027s own\nauthorization \u2014 it says nothing about, and never touches, the **target** user\u0027s existing session.\n\n### The stale session survives\nThe demoted user\u0027s session was populated once, at login, and is never refreshed:\n\n- `helpers.py:170,179,183-185` \u2014 `parse_permissions(session)` derives the caller\u0027s effective\n  admin/permission bits from `session.get(\"role\")` and `session.get(\"perms\")`.\n- These values are written once by `set_session()` (`helpers.py:223-234`), called only from\n  `app_blueprint.py:88` (login) and `:100` (autologin). A repo-wide grep for `before_request` inside\n  `src/pyload/` returns nothing \u2014 no hook anywhere refreshes a live session from the database.\n- `is_authenticated(session)` (`helpers.py:261-266`) is exactly:\n  ```\n  user = session.get(\"name\")\n  authenticated = session.get(\"authenticated\", False)\n  return authenticated and api.user_exists(user)\n  ```\n  It re-validates only that the username still exists \u2014 never that the session\u0027s cached `role`/`perms`\n  still match the current database values.\n- Inside `apikey_auth` (`helpers.py:393-404`), when no `X-API-Key` header is supplied, `flask.g.user_info`\n  is built as `{\"id\": s[\"id\"], \"name\": s[\"name\"], \"role\": s[\"role\"], \"permission\": s[\"perms\"]}` \u2014\n  straight from the same stale, login-time-cached session fields. This is exactly the `user_info` that\n  `api_blueprint.py:50` feeds into `is_authorized()` for every `/api/\u003cfunc\u003e` call made over a cookie\n  session.\n\nThe exposure window is bounded, not indefinite: `default.cfg:47` sets `session_lifetime = 44640`\n(minutes, \u224831 days), wired into `PERMANENT_SESSION_LIFETIME` at `webui/app/__init__.py:130-131`, and\n`SESSION_REFRESH_EACH_REQUEST = False` at `:128` means the window is a hard ~31 days from login, not\nextended by continued activity.\n\n## Attack Sequence\nStarting privilege: an already-authenticated non-admin user, plus an admin who legitimately uses\npyLoad\u0027s own documented API instead of the WebUI page.\n\n1. Victim user logs in normally, obtains a Flask session cookie (`A`) with `role`/`perms` reflecting\n   their current (elevated) permissions.\n2. Admin revokes or downgrades the victim\u0027s permissions via\n   `POST /api/set_user_permission` (or legacy `POST /api/setUserPermission`) with the victim\u0027s\n   username and the new, lower `permission`/`role` values \u2014 using `curl`, a script, or any RPC client,\n   rather than the WebUI\u0027s \"Manage Users\" HTML page. `Api.set_user_permission` updates\n   `pyload.db.set_permission` / `pyload.db.set_role` and returns; no session anywhere is touched.\n3. Using cookie `A` (never invalidated), the victim loads any WebUI admin-gated page, or calls any\n   `/api/\u003cfunc\u003e` endpoint gated only on role/permission. `apikey_auth`\u0027s cookie branch rebuilds\n   `user_info` from the stale session fields (`role`/`perms` as of step 1), `is_authorized()` /\n   `parse_permissions()` evaluate against those stale values, and the call succeeds as if the\n   revocation never happened.\n4. This persists for up to ~31 days (default `session_lifetime`) or until the victim logs out,\n   whichever comes first.\n\nThis sequence was confirmed against a real, locally-run pyLoad instance, not just traced from source.\nSee Section 10 for the exact commands, real HTTP status codes and response bodies, and the\nprecondition that the admin step here used `X-API-Key` header auth rather than a cookie (explained\nthere).\n\n## Suggested Fix\nMove the `clear_all_user_sessions(name)` call into `Api.set_user_permission` itself (ideally also\nadopting the apikey-cache purge pattern already used in `remove_user`,\n`core/api/__init__.py:1626-1636`), so that every entry point \u2014 WebUI and `/api/\u003cfunc\u003e` RPC alike \u2014\ninherits session invalidation automatically, rather than requiring each caller to remember to invoke\nit separately.\n\n### PoC\nThis was executed for real against pyLoad\u0027s own code, not merely predicted from reading it. The\nverifier pass that produced Sections 1-9 (`ghsa/CLAIMS-pyload.md`) source-traced every claim but never\nran a PoC; this section closes that gap.\n\n### Method and preconditions\n\n- Target: `pyload/pyload` at the pinned commit `31e341fd41d2dac9fffa3683a756edc54bcdeb77`\n  (`develop` branch), installed editable (`pip install -e \".[test]\"`) into a fresh Python 3.12.3\n  virtualenv. No source files were modified.\n- Transport: Flask\u0027s in-process test client (`app.test_client()`) against the real\n  `pyload.core.Core` / `pyload.webui.app` Flask app object, not a bound TCP server. This is the same\n  bootstrap the project\u0027s own `tests/integration/conftest.py` fixture uses, and it exercises the\n  identical route/view/decorator code (`api_blueprint.rpc()`, `apikey_auth`, `is_authorized()`,\n  `parse_permissions()`, Flask-WTF CSRF protection) that a real `127.0.0.1:8000`-bound server would\n  run. No real network socket was opened and no third-party or public host was touched, only this\n  locally-run copy of the target\u0027s own cloned code.\n- Two users: `pyload`/`pyload` (pyLoad\u0027s own automatically-created default admin account) and a\n  freshly created non-admin `victim` user with the `Perms.SETTINGS` permission bit.\n- Elevated-action probe: `GET /api/get_userdir` (`core/api/__init__.py:1434-1437`, decorated\n  `@permission(Perms.SETTINGS)` `@get`), chosen because it is gated on an ordinary non-admin permission bit\n  and because it is a `GET` request, so it needs no CSRF token (Flask-WTF\u0027s `WTF_CSRF_METHODS` default\n  excludes `GET`), keeping the reproduction focused on session staleness rather than CSRF plumbing.\n- The admin\u0027s `POST /api/set_user_permission` call used `X-API-Key` header authentication rather than\n  a cookie. This is a precondition, not a simplification of the bug: `apikey_auth`\n  (`helpers.py:335-413`) marks the whole `/api/\u003cfunc\u003e` route CSRF-exempt at decoration time, then, only\n  in the cookie-session branch (no API key), manually calls `csrf.protect()` (`helpers.py:397`) before\n  dispatch -- so a cookie-authenticated admin call needs a valid CSRF token, and an `X-API-Key` call\n  does not (`helpers.py:361-384` returns before that check is reached). This has no bearing on the\n  vulnerability itself: `Api.set_user_permission`\u0027s body (`core/api/__init__.py:1652-1656`) does not\n  branch on how the caller authenticated, and the `is_authorized()` gate that runs before it\n  (`api_blueprint.py:50`) only checks the ADMIN CALLER\u0027s own role, never the target user\u0027s session. A\n  cookie-authenticated admin request (fetching a CSRF token the same way the victim\u0027s login step does)\n  reaches the identical code path and was not separately re-run.\n- Full script, README with exact from-nothing run instructions, and the verbatim captured output are\n  in the evidence bundle: `ghsa/poc-bundles/pyload-poc/` (zipped copy:\n  `ghsa/poc-bundles/pyload-poc.zip`).\n\n### Output (ran: 2026-09-10)\n\n```\nSTEP 1: victim logs in through the real WebUI /login route, keeping the session cookie\n==============================================================================\nPOST /login -\u003e status 302\nSet-Cookie: [\u0027pyload_session_8000=Kgq1peWlETCpxj4MSOSY-yxy-v3EYgIjiLxYT7kLgO0; Expires=Sun, 11 Oct 2026 12:30:51 GMT; HttpOnly; Path=/; SameSite=Lax\u0027]\nvictim\u0027s cached session contents right after login: role=1 perms=128 authenticated=True\n\n==============================================================================\nSTEP 2: BASELINE -- victim, using cookie A, calls a SETTINGS-gated GET endpoint (/api/get_userdir, @permission(Perms.SETTINGS)) and it succeeds\n==============================================================================\nGET /api/get_userdir (victim cookie) -\u003e status 200\nbody: \"/tmp/pyload_poc_userdir_y9fl5y10\"\n\n==============================================================================\nSTEP 3: admin revokes the victim\u0027s permissions via pyLoad\u0027s own public /api/\u003cfunc\u003e RPC dispatcher (X-API-Key header, NOT the WebUI \u0027Manage Users\u0027 page, NOT json_blueprint.py\u0027s update_users())\n==============================================================================\nPOST /api/set_user_permission (admin API key) -\u003e status 200\nbody: null\n\n==============================================================================\nSTEP 4: confirm via a fresh DB read that the victim\u0027s permission really is downgraded in the database\n==============================================================================\nvictim DB row after set_user_permission: {\u0027id\u0027: 2, \u0027name\u0027: \u0027victim\u0027, \u0027permission\u0027: 0, \u0027role\u0027: 1, \u0027template\u0027: \u0027default\u0027, \u0027email\u0027: \u0027\u0027}\n\n==============================================================================\nSTEP 5 (the bug): using the victim\u0027s ORIGINAL, UNCHANGED cookie A from step 1, repeat the exact same SETTINGS-gated call\n==============================================================================\nGET /api/get_userdir (SAME victim cookie, post-demotion) -\u003e status 200\nbody: \"/tmp/pyload_poc_userdir_y9fl5y10\"\nRESULT: call STILL SUCCEEDS after the permission revocation. The stale cookie session retains the pre-revocation SETTINGS bit.\nvictim\u0027s cached session contents after admin\u0027s revocation (unchanged since login): role=1 perms=128\n\n==============================================================================\nSTEP 6 (control): the SAME demoted victim, authenticating via the X-API-Key header instead of the cookie, correctly gets the NEW, reduced permission immediately\n==============================================================================\nGET /api/get_userdir (victim X-API-Key, post-demotion) -\u003e status 401\nbody: {\"error\": \"Access denied\"}\nRESULT: API-key path correctly reflects the demotion immediately (access denied), confirming the bug is cookie-session-specific.\n```\n\n(Log lines from pyLoad\u0027s own logger, interleaved with this output in the raw capture, are omitted here\nfor readability; the full unedited capture, including those log lines, is `output.txt` in the evidence\nbundle.)\n\nThis matches the predicted behavior in Sections 4 and 6 exactly: the demoted victim\u0027s original cookie\nstill returns `200` with the pre-revocation permission\u0027s data (step 5), while the same demotion is\ncorrectly and immediately visible through `X-API-Key` auth (step 6, `401`). Nothing in the live run\ncontradicted the source-level analysis; no additional gate blocked the bypass, and no easier bypass\nwas found.\n\nThe run was repeated from a completely freshly built virtualenv (`pip install -e \".[test]\"` into a new\nvenv, no reuse of any prior install) with identical outcomes -- only the random API key values, the\nsigned session cookie value, and the temp directory path differ between runs, as expected.\n\n### Reproduce from nothing\n\n```sh\n# starting from a pyload/pyload checkout pinned at 31e341fd41d2dac9fffa3683a756edc54bcdeb77\ncd /path/to/pyload-clone-at-31e341f\n\npython3 -m venv /tmp/pyload-poc-venv\n/tmp/pyload-poc-venv/bin/pip install -U pip\n/tmp/pyload-poc-venv/bin/pip install -e \".[test]\"\n\n# optional sanity check against the project\u0027s own test suite\n/tmp/pyload-poc-venv/bin/python -m pytest tests/integration/test_api.py -q   # -\u003e 12 passed\n\n/tmp/pyload-poc-venv/bin/python3 /path/to/ghsa/poc-bundles/pyload-poc/poc_stale_session.py\n```\n\n### Impact\nThe header-present branch of `apikey_auth` (`helpers.py:370`) reads role/permission fresh from the database via `get_user_by_id`\non every request. This bug is specific to the cookie/session-based auth path (`helpers.py:393-404`).\n\n[pyload-poc.zip](https://github.com/user-attachments/files/32062053/pyload-poc.zip)",
  "id": "GHSA-889w-m37p-88m5",
  "modified": "2026-10-09T17:09:07Z",
  "published": "2026-10-09T17:09:07Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/pyload/pyload/security/advisories/GHSA-889w-m37p-88m5"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pyload/pyload/commit/3e726ba271a6b1015e3a0ea6dc7e46a8f71a62ad"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/pyload/pyload"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "pyLoad: Api.set_user_permission never invalidates the target\u0027s session"
}

GHSA-88RM-6CPC-9J4W

Vulnerability from github – Published: 2026-07-22 21:32 – Updated: 2026-08-07 06:30
VLAI
Details

Question2Answer through 1.8.8 contains a session invalidation vulnerability that allows attackers with a previously obtained remember-me cookie to retain authenticated access by exploiting the forgot-password reset flow's failure to clear the sessioncode field in qa-include/app/users-edit.php. While the normal password-change flow in qa-include/pages/account.php explicitly clears the sessioncode to invalidate persistent qa_session cookies, the forgot-password handler qa_finish_reset_user() omits this step, allowing any valid persistent cookie issued before the reset to continue authenticating the account after the password reset completes.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2026-64829"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2026-07-22T20:17:08Z",
    "severity": "CRITICAL"
  },
  "details": "Question2Answer through 1.8.8 contains a session invalidation vulnerability that allows attackers with a previously obtained remember-me cookie to retain authenticated access by exploiting the forgot-password reset flow\u0027s failure to clear the sessioncode field in qa-include/app/users-edit.php. While the normal password-change flow in qa-include/pages/account.php explicitly clears the sessioncode to invalidate persistent qa_session cookies, the forgot-password handler qa_finish_reset_user() omits this step, allowing any valid persistent cookie issued before the reset to continue authenticating the account after the password reset completes.",
  "id": "GHSA-88rm-6cpc-9j4w",
  "modified": "2026-08-07T06:30:22Z",
  "published": "2026-07-22T21:32:08Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-64829"
    },
    {
      "type": "WEB",
      "url": "https://github.com/q2a/question2answer/pull/1017"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/question2answer-session-fixation-via-forgot-password-flow"
    },
    {
      "type": "WEB",
      "url": "http://seclists.org/fulldisclosure/2026/Aug/32"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:N/PR:N/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-895X-RFQP-JH5C

Vulnerability from github – Published: 2025-10-23 15:30 – Updated: 2026-02-17 17:21
VLAI
Summary
Keycloak does not invalidate offline sessions when the offline_access scope is removed
Details

A flaw was found in Keycloak. An offline session continues to be valid when the offline_access scope is removed from the client. The refresh token is accepted and you can continue to request new tokens for the session. As it can lead to a situation where an administrator removes the scope, and assumes that offline sessions are no longer available, but they are.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.keycloak:keycloak-services"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "26.2.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-12110"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2025-10-23T19:24:54Z",
    "nvd_published_at": "2025-10-23T15:15:32Z",
    "severity": "MODERATE"
  },
  "details": "A flaw was found in Keycloak. An offline session continues to be valid when the offline_access scope is removed from the client. The refresh token is accepted and you can continue to request new tokens for the session. As it can lead to a situation where an administrator removes the scope, and assumes that offline sessions are no longer available, but they are.",
  "id": "GHSA-895x-rfqp-jh5c",
  "modified": "2026-02-17T17:21:35Z",
  "published": "2025-10-23T15:30:34Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-12110"
    },
    {
      "type": "WEB",
      "url": "https://github.com/keycloak/keycloak/pull/43790"
    },
    {
      "type": "WEB",
      "url": "https://github.com/keycloak/keycloak/commit/54e1c8af1e089ad33d32e0f2792610e4b8df421b"
    },
    {
      "type": "WEB",
      "url": "https://github.com/keycloak/keycloak/commit/c830a27928cac4294619af7d147bdff34d4a85e7"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2025:21370"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2025:21371"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2025:22088"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/errata/RHSA-2025:22089"
    },
    {
      "type": "WEB",
      "url": "https://access.redhat.com/security/cve/CVE-2025-12110"
    },
    {
      "type": "WEB",
      "url": "https://bugzilla.redhat.com/show_bug.cgi?id=2406033"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/keycloak/keycloak"
    }
  ],
  "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"
    }
  ],
  "summary": "Keycloak does not invalidate offline sessions when the offline_access scope is removed"
}

GHSA-89HR-6X2P-8XJV

Vulnerability from github – Published: 2026-03-31 15:31 – Updated: 2026-03-31 23:51
Withdrawn 2026-03-31 VLAI
Summary
Duplicate Advisory: OpenClaw's device removal and token revocation do not terminate active WebSocket sessions
Details

Duplicate Advisory

This advisory has been withdrawn because it is a duplicate of GHSA-2pr2-hcv6-7gwv. This link is maintained to preserve external references.

Original Description

OpenClaw before 2026.3.28 fails to disconnect active WebSocket sessions when devices are removed or tokens are revoked. Attackers with revoked credentials can maintain unauthorized access through existing live sessions until forced reconnection.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "npm",
        "name": "openclaw"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "2026.3.28"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-03-31T23:51:46Z",
    "nvd_published_at": "2026-03-31T15:16:19Z",
    "severity": "HIGH"
  },
  "details": "### Duplicate Advisory\nThis advisory has been withdrawn because it is a duplicate of GHSA-2pr2-hcv6-7gwv. This link is maintained to preserve external references.\n\n### Original Description\nOpenClaw before 2026.3.28 fails to disconnect active WebSocket sessions when devices are removed or tokens are revoked. Attackers with revoked credentials can maintain unauthorized access through existing live sessions until forced reconnection.",
  "id": "GHSA-89hr-6x2p-8xjv",
  "modified": "2026-03-31T23:51:46Z",
  "published": "2026-03-31T15:31:56Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/security/advisories/GHSA-2pr2-hcv6-7gwv"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34503"
    },
    {
      "type": "WEB",
      "url": "https://github.com/openclaw/openclaw/commit/7a801cc451e9e667b705eeccff651923a1b8c863"
    },
    {
      "type": "WEB",
      "url": "https://www.vulncheck.com/advisories/openclaw-incomplete-websocket-session-termination-on-device-removal-and-token-revocation"
    }
  ],
  "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: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"
    }
  ],
  "summary": "Duplicate Advisory: OpenClaw\u0027s device removal and token revocation do not terminate active WebSocket sessions",
  "withdrawn": "2026-03-31T23:51:46Z"
}

GHSA-8C39-XPPG-479C

Vulnerability from github – Published: 2026-01-06 17:18 – Updated: 2026-01-06 17:18
VLAI
Summary
Pterodactyl does not revoke SFTP access when server is deleted or permissions reduced
Details

Summary

Pterodactyl does not revoke active SFTP connections when a user is removed from a server instance or has their permissions changes with respect to file access over SFTP. This allows a user that was already connected to SFTP to remain connected and access files even after their permissions are revoked.

Details

When a user opens a connection to a server using the Wings SFTP server instance the permissions are checked and returned from the authentication API call made to the Panel. However, credentials are not checked again after the initial handshake. Thus, if a user is removed from a server in the panel or have their permissions modified, those permissions are not updated in the SFTP connection.

As a result, a user that has already gained access to a server's files via the SFTP subsystem will maintain those permissions until disconnected (via Wings restart, or a manual disconnection on their end).

[!NOTE]

This issue impacts the SFTP subsystem for server files specifically. There is no exposure of Wings private data, or any data outside of a server's local filesystem. Additionally, a user must have been connected to SFTP at the time of their permissions being revoked in order for this issue to be exploited. If a user was not connected, they would not be able to connect once their permissions were reduced.

Fix

Please upgrade to wings@1.12.0 and panel@1.12.0 to resolve this issue. Patches are available via the implementation PRs, but it is recommended to apply by upgrading the entire instance.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "pterodactyl/panel"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.12.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Go",
        "name": "github.com/pterodactyl/wings"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.12.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2025-68954"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-01-06T17:18:56Z",
    "nvd_published_at": "2026-01-06T01:16:01Z",
    "severity": "HIGH"
  },
  "details": "### Summary\nPterodactyl does not revoke _active_ SFTP connections when a user is removed from a server instance or has their permissions changes with respect to file access over SFTP. This allows a user that was already connected to SFTP to remain connected and access files even after their permissions are revoked.\n\n### Details\nWhen a user opens a connection to a server using the Wings SFTP server instance the permissions are checked and returned from the authentication API call made to the Panel. However, credentials are not checked again after the initial handshake. Thus, if a user is removed from a server in the panel or have their permissions modified, those permissions are not updated in the SFTP connection.\n\nAs a result, a user that has already gained access to a server\u0027s files via the SFTP subsystem will maintain those permissions until disconnected (via Wings restart, or a manual disconnection on their end).\n\n\u003e [!NOTE]\n\u003e\n\u003e This issue impacts the SFTP subsystem for server files specifically. There is no exposure of Wings private data, or any data outside of a server\u0027s local filesystem. Additionally, a user must have been _connected to SFTP at the time of their permissions being revoked_ in order for this issue to be exploited. If a user was not connected, they would not be able to connect once their permissions were reduced.\n\n### Fix\nPlease upgrade to `wings@1.12.0` and `panel@1.12.0` to resolve this issue. Patches are available via the implementation PRs, but it is recommended to apply by upgrading the entire instance.",
  "id": "GHSA-8c39-xppg-479c",
  "modified": "2026-01-06T17:18:56Z",
  "published": "2026-01-06T17:18:56Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/pterodactyl/panel/security/advisories/GHSA-8c39-xppg-479c"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-68954"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pterodactyl/panel/commit/2bd9d8baddb0e0606e4a9d5be402f48678ac88d5"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/pterodactyl/panel"
    },
    {
      "type": "WEB",
      "url": "https://github.com/pterodactyl/panel/releases/tag/v1.12.0"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:4.0/AV:N/AC:L/AT:P/PR:H/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Pterodactyl does not revoke SFTP access when server is deleted or permissions reduced"
}

GHSA-8CV6-H2PR-548G

Vulnerability from github – Published: 2024-03-06 18:30 – Updated: 2024-03-06 18:30
VLAI
Details

A vulnerability in Cisco Duo Authentication for Windows Logon and RDP could allow an authenticated, physical attacker to bypass secondary authentication and access an affected Windows device.

This vulnerability is due to a failure to invalidate locally created trusted sessions after a reboot of the affected device. An attacker with primary user credentials could exploit this vulnerability by attempting to authenticate to an affected device. A successful exploit could allow the attacker to access the affected device without valid permissions.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-20301"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287",
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-03-06T17:15:08Z",
    "severity": "MODERATE"
  },
  "details": "A vulnerability in Cisco Duo Authentication for Windows Logon and RDP could allow an authenticated, physical attacker to bypass secondary authentication and access an affected Windows device. \n\n This vulnerability is due to a failure to invalidate locally created trusted sessions after a reboot of the affected device. An attacker with primary user credentials could exploit this vulnerability by attempting to authenticate to an affected device. A successful exploit could allow the attacker to access the affected device without valid permissions.",
  "id": "GHSA-8cv6-h2pr-548g",
  "modified": "2024-03-06T18:30:37Z",
  "published": "2024-03-06T18:30:37Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-20301"
    },
    {
      "type": "WEB",
      "url": "https://sec.cloudapps.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-duo-win-bypass-pn42KKBm"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:P/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-8FF6-GRVW-RMVX

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

DomainMOD domainmod-v4.15.0 is affected by an insufficient session expiration vulnerability. On changing a password, both sessions using the changed password and old sessions in any other browser or device do not expire and remain active. Such flaws frequently give attackers unauthorized access to some system data or functionality.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-35358"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-613"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2021-03-15T12:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "DomainMOD domainmod-v4.15.0 is affected by an insufficient session expiration vulnerability. On changing a password, both sessions using the changed password and old sessions in any other browser or device do not expire and remain active. Such flaws frequently give attackers unauthorized access to some system data or functionality.",
  "id": "GHSA-8ff6-grvw-rmvx",
  "modified": "2022-05-24T17:44:33Z",
  "published": "2022-05-24T17:44:33Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-35358"
    },
    {
      "type": "WEB",
      "url": "https://gist.github.com/anku-agar/0fec2ffd98308e550ce9b5d4b395d0d7"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-8FQ3-C5W3-PJ3Q

Vulnerability from github – Published: 2026-04-01 22:09 – Updated: 2026-04-27 16:27
VLAI
Summary
CI4MS: Account Deactivation Module Grants Full Persistent Unauthorized Access for All‑Roles via Improper Session Invalidation (Logic Flaw)
Details

Summary

Vulnerability: Improper Session Invalidation on Account Deactivation (Broken Access Control / Logic Flaw)

  • This vulnerability is caused by a backend logic flaw that maintains a false trust assumption that already-authenticated users remain trustworthy, even after their accounts are explicitly deactivated. As a result, administrative security actions do not behave as intended, allowing persistent unauthorized access.

Description

The application fails to immediately revoke active user sessions when an account is deactivated. Due to a logic flaw in the backend design, account state changes are enforced only during authentication (login), not for already-established sessions.

The system implicitly assumes that authenticated users remain trusted for the lifetime of their session. There is no session expiration or account expiration mechanism in place, causing deactivated accounts to retain indefinite access until the user manually logs out. This behavior breaks the intended access control policy and results in persistent unauthorized access, representing a critical security flaw.

Affected Functionality

  • User session management and authentication logic
  • Account deactivation mechanism
  • All authenticated endpoints, including administrative and content interfaces

Attack Scenario

  • A user logs into the application.
  • An administrator deactivates the user account.
  • The user remains fully logged in and can continue performing all actions allowed by their role indefinitely, as there is no session expiration.
  • The user can continue invoking backend methods, triggering application actions, accessing sensitive interfaces (including user management if permitted), and interacting with the system as if the account were still active.
  • Access is only lost if the user manually logs out, which may never occur.

Impact

  • Unauthorized Continued Access: Deactivated users retain full access indefinitely, violating intended access control and expected security behavior.
  • Bypass of Administrative Controls: Administrative actions (deactivation) fail to immediately restrict active sessions.
  • Logic Flaw Resulting in Broken Behavior: Backend authorization logic relies on a flawed trust assumption that authenticated users remain valid, enforcing account state only at login.
  • Full Functional Access Retained: Deactivated users can continue invoking application methods, executing actions, interacting with protected endpoints, and using the system exactly as before being deactivated.
  • Privilege Abuse: Users with elevated roles (moderator, editor, administrator) can continue performing privileged actions after account deactivation, including accessing user management interfaces and modifying application state.
  • Service Disruption Potential: Persistent access allows attackers to disrupt services, manipulate content, or interfere with normal application operations.
  • Attack Persistence: Attackers can maintain access indefinitely, increasing the risk of data exfiltration, unauthorized modifications, or further privilege escalation.
  • False Sense of Remediation: Administrators may believe a threat has been mitigated while the deactivated user remains active within the system.

Endpoint Example: Any endpoint accessible to authenticated users, including dashboards, administrative interfaces, user management pages, and API endpoints.

Steps To Reproduce (PoC)

  1. Create or use an existing user account.
  2. Log into the application using this account.
  3. From an administrative account, deactivate the logged-in user account.
  4. Observe that the target user remains authenticated.
  5. Verify that the user can still access protected functionality, invoke actions, and interact with the application as before.
  6. Confirm that the user only loses access after manually logging out (if they choose to do so).

Remediation

  • Immediately invalidate all active sessions when an account is deactivated.
  • Enforce account status checks on every authenticated request, not only during login.
  • Introduce proper session expiration or account expiration mechanisms to prevent indefinite access.
  • Correct the backend logic flaw to ensure access control behavior aligns with intended security design and does not rely on unsafe trust assumptions.

Ready Video POC:

https://mega.nz/file/zJkhwCII#G1-TecKmNBJmEeBS0ExsAY_RXEmAl3QqMqu4t5oy844

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 0.28.6.0"
      },
      "package": {
        "ecosystem": "Packagist",
        "name": "ci4-cms-erp/ci4ms"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "0.31.0.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-34572"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-1254",
      "CWE-284",
      "CWE-613"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-01T22:09:39Z",
    "nvd_published_at": "2026-04-01T22:16:21Z",
    "severity": "HIGH"
  },
  "details": "## Summary\n### Vulnerability: Improper Session Invalidation on Account Deactivation (Broken Access Control / Logic Flaw)\n- This vulnerability is caused by a backend logic flaw that maintains a false trust assumption that already-authenticated users remain trustworthy, even after their accounts are explicitly deactivated. As a result, administrative security actions do not behave as intended, allowing persistent unauthorized access.\n\n### Description\nThe application fails to immediately revoke active user sessions when an account is deactivated. Due to a logic flaw in the backend design, account state changes are enforced only during authentication (login), not for already-established sessions.\n\nThe system implicitly assumes that authenticated users remain trusted for the lifetime of their session. There is no session expiration or account expiration mechanism in place, causing deactivated accounts to retain indefinite access until the user manually logs out. This behavior breaks the intended access control policy and results in persistent unauthorized access, representing a critical security flaw.\n\n### Affected Functionality\n- User session management and authentication logic\n- Account deactivation mechanism\n- All authenticated endpoints, including administrative and content interfaces\n\n### Attack Scenario\n- A user logs into the application.\n- An administrator deactivates the user account.\n- The user remains fully logged in and can continue performing all actions allowed by their role indefinitely, as there is no session expiration.\n- The user can continue invoking backend methods, triggering application actions, accessing sensitive interfaces (including user management if permitted), and interacting with the system as if the account were still active.\n- Access is only lost if the user manually logs out, which may never occur.\n\n### Impact\n- Unauthorized Continued Access: Deactivated users retain full access indefinitely, violating intended access control and expected security behavior.\n- Bypass of Administrative Controls: Administrative actions (deactivation) fail to immediately restrict active sessions.\n- Logic Flaw Resulting in Broken Behavior: Backend authorization logic relies on a flawed trust assumption that authenticated users remain valid, enforcing account state only at login.\n- Full Functional Access Retained: Deactivated users can continue invoking application methods, executing actions, interacting with protected endpoints, and using the system exactly as before being deactivated.\n- Privilege Abuse: Users with elevated roles (moderator, editor, administrator) can continue performing privileged actions after account deactivation, including accessing user management interfaces and modifying application state.\n- Service Disruption Potential: Persistent access allows attackers to disrupt services, manipulate content, or interfere with normal application operations.\n- Attack Persistence: Attackers can maintain access indefinitely, increasing the risk of data exfiltration, unauthorized modifications, or further privilege escalation.\n- False Sense of Remediation: Administrators may believe a threat has been mitigated while the deactivated user remains active within the system.\n\nEndpoint Example: Any endpoint accessible to authenticated users, including dashboards, administrative interfaces, user management pages, and API endpoints.\n\n## Steps To Reproduce (PoC)\n1. Create or use an existing user account.\n2. Log into the application using this account.\n3. From an administrative account, deactivate the logged-in user account.\n4. Observe that the target user remains authenticated.\n5. Verify that the user can still access protected functionality, invoke actions, and interact with the application as before.\n6. Confirm that the user only loses access after manually logging out (if they choose to do so).\n\n## Remediation\n- Immediately invalidate all active sessions when an account is deactivated.\n- Enforce account status checks on every authenticated request, not only during login.\n- Introduce proper session expiration or account expiration mechanisms to prevent indefinite access.\n- Correct the backend logic flaw to ensure access control behavior aligns with intended security design and does not rely on unsafe trust assumptions.\n\n# Ready Video POC:\nhttps://mega.nz/file/zJkhwCII#G1-TecKmNBJmEeBS0ExsAY_RXEmAl3QqMqu4t5oy844",
  "id": "GHSA-8fq3-c5w3-pj3q",
  "modified": "2026-04-27T16:27:49Z",
  "published": "2026-04-01T22:09:39Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/ci4-cms-erp/ci4ms/security/advisories/GHSA-8fq3-c5w3-pj3q"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-34572"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/ci4-cms-erp/ci4ms"
    },
    {
      "type": "WEB",
      "url": "https://github.com/ci4-cms-erp/ci4ms/releases/tag/0.31.0.0"
    }
  ],
  "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": "CI4MS: Account Deactivation Module Grants Full Persistent Unauthorized Access for All\u2011Roles via Improper Session Invalidation (Logic Flaw)"
}

Mitigation
Implementation

Set sessions/credentials expiration date.

No CAPEC attack patterns related to this CWE.