GHSA-F4F9-627C-JH33

Vulnerability from github – Published: 2026-04-08 00:08 – Updated: 2026-04-08 00:08
VLAI?
Summary
WWBN AVideo's GIF poster fetch bypasses traversal scrubbing and exposes local files through public media URLs
Details

Summary

objects/aVideoEncoderReceiveImage.json.php allowed an authenticated uploader to fetch attacker-controlled same-origin /videos/... URLs, bypass traversal scrubbing, and expose server-local files through the GIF poster storage path.

The vulnerable GIF branch could be abused to read local files such as /etc/passwd or application source files and republish those bytes through a normal public GIF media URL.

Details

The vulnerable chain was:

  1. objects/aVideoEncoderReceiveImage.json.php accepted attacker-controlled downloadURL_gifimage
  2. traversal scrubbing used str_replace('../', '', ...), which was bypassable with overlapping input such as ....//
  3. same-origin /videos/... URLs were accepted
  4. url_get_contents() and try_get_contents_from_local() resolved the request into a local filesystem read
  5. the fetched bytes were written into the GIF destination
  6. invalid GIF cleanup used the wrong variable, so the non-image payload remained on disk

This made the GIF poster path a local file disclosure primitive with public retrieval.

Proof of concept

  1. Log in as an uploader and create an owned video row through the normal encoder flow.
  2. Send:
POST /objects/aVideoEncoderReceiveImage.json.php
downloadURL_gifimage=https://localhost/videos/....//....//....//....//....//....//etc/passwd
  1. Query:
GET /objects/videos.json.php?showAll=1
  1. Recover the generated GIF URL from videosURL.gif.url.
  2. Download that GIF URL.
  3. Observe that the body matches the target local file, such as /etc/passwd, byte-for-byte.

Impact

An authenticated uploader can read server-local files and republish them through a public GIF media URL by supplying a crafted same-origin /videos/... path to downloadURL_gifimage. Because traversal scrubbing was bypassable and the fetched bytes were written to the GIF destination without effective invalid-image cleanup, successful exploitation allows disclosure of files such as /etc/passwd, readable application source code, or deployment-specific configuration accessible to the application.

Recommended fix

  • Reject any remote image URL whose decoded path contains traversal markers
  • Do not allow attacker-controlled same-origin /videos/... fetches to resolve into local file reads
  • Constrain any local shortcut path handling with realpath() and strict base-directory allowlists
  • Validate GIF content before saving it into public media storage
  • Ensure invalid-image cleanup checks the correct destination path
Show details on source website

{
  "affected": [
    {
      "package": {
        "ecosystem": "Packagist",
        "name": "WWBN/AVideo"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "last_affected": "26.0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [
    "CVE-2026-39369"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-22"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-08T00:08:44Z",
    "nvd_published_at": "2026-04-07T20:16:31Z",
    "severity": "HIGH"
  },
  "details": "## Summary\n\n`objects/aVideoEncoderReceiveImage.json.php` allowed an authenticated uploader to fetch attacker-controlled same-origin `/videos/...` URLs, bypass traversal scrubbing, and expose server-local files through the GIF poster storage path.\n\nThe vulnerable GIF branch could be abused to read local files such as `/etc/passwd` or application source files and republish those bytes through a normal public GIF media URL.\n\n## Details\n\nThe vulnerable chain was:\n\n1. `objects/aVideoEncoderReceiveImage.json.php` accepted attacker-controlled `downloadURL_gifimage`\n2. traversal scrubbing used `str_replace(\u0027../\u0027, \u0027\u0027, ...)`, which was bypassable with overlapping input such as `....//`\n3. same-origin `/videos/...` URLs were accepted\n4. `url_get_contents()` and `try_get_contents_from_local()` resolved the request into a local filesystem read\n5. the fetched bytes were written into the GIF destination\n6. invalid GIF cleanup used the wrong variable, so the non-image payload remained on disk\n\nThis made the GIF poster path a local file disclosure primitive with public retrieval.\n\n## Proof of concept\n\n1. Log in as an uploader and create an owned video row through the normal encoder flow.\n2. Send:\n\n```text\nPOST /objects/aVideoEncoderReceiveImage.json.php\ndownloadURL_gifimage=https://localhost/videos/....//....//....//....//....//....//etc/passwd\n```\n\n3. Query:\n\n```text\nGET /objects/videos.json.php?showAll=1\n```\n\n4. Recover the generated GIF URL from `videosURL.gif.url`.\n5. Download that GIF URL.\n6. Observe that the body matches the target local file, such as `/etc/passwd`, byte-for-byte.\n\n## Impact\n\nAn authenticated uploader can read server-local files and republish them through a public GIF media URL by supplying a crafted same-origin `/videos/...` path to `downloadURL_gifimage`. Because traversal scrubbing was bypassable and the fetched bytes were written to the GIF destination without effective invalid-image cleanup, successful exploitation allows disclosure of files such as `/etc/passwd`, readable application source code, or deployment-specific configuration accessible to the application.\n\n\n## Recommended fix\n\n- Reject any remote image URL whose decoded path contains traversal markers\n- Do not allow attacker-controlled same-origin `/videos/...` fetches to resolve into local file reads\n- Constrain any local shortcut path handling with `realpath()` and strict base-directory allowlists\n- Validate GIF content before saving it into public media storage\n- Ensure invalid-image cleanup checks the correct destination path",
  "id": "GHSA-f4f9-627c-jh33",
  "modified": "2026-04-08T00:08:44Z",
  "published": "2026-04-08T00:08:44Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/WWBN/AVideo/security/advisories/GHSA-f4f9-627c-jh33"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-39369"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/WWBN/AVideo"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L",
      "type": "CVSS_V3"
    }
  ],
  "summary": "WWBN AVideo\u0027s GIF poster fetch bypasses traversal scrubbing and exposes local files through public media URLs"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or observed by the user.
  • Confirmed: The vulnerability has been validated from an analyst's perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
  • Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
  • Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
  • Not confirmed: The user expressed doubt about the validity of the vulnerability.
  • Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…