| CVE |
Vendors |
Products |
Updated |
CVSS v3.1 |
| ChirpStack's SQLite-backend device tag filtering (chirpstack/src/storage/device.rs, in both get_count() and list()) interpolates the user-supplied tag KEY directly into a raw SQL fragment via Rust's format!() macro (`dsl::sql::<Bool>(&format!("device.tags->>'{}' =", k)).bind::<Text, _>(v)`), while only the tag VALUE is safely parameter-bound via Diesel's .bind(). An authenticated user with device-list access can inject SQL via a crafted tag key when the SQLite backend (chirpstack-sqlite package) is in use; the PostgreSQL backend is unaffected as it uses Diesel's native JSONB containment operator instead of raw SQL string formatting. |
| Hugging Face peft's LoRA-GA and CorDA initialization modules (src/peft/tuners/lora/corda.py lines ~102 and ~163, and src/peft/tuners/lora/loraga.py line ~101) call torch.load() on config-specified cache/covariance files without weights_only=True, bypassing peft's own safe-loading wrapper used elsewhere in the codebase. Because torch.load() without weights_only=True performs full pickle deserialization, loading a malicious cache or covariance file (e.g. a shared/downloaded LoRA-GA or CorDA cache) results in arbitrary code execution. |
| go-shiori's DownloadBookmark() (internal/core/download.go) fetches a caller-supplied bookmark URL using a plain http.Client with no custom DialContext or destination-IP validation (no IsLoopback(), IsPrivate(), IsUnspecified(), or IsLinkLocalUnicast() checks). An authenticated user creating or updating a bookmark via POST /api/bookmark, PUT /api/v1/bookmarks/cache, or POST /api/bookmarks/ext can supply a loopback (127.0.0.1) or 0.0.0.0 (which Linux redirects to loopback) URL, causing the server to make outbound requests to internal-only services, cloud metadata endpoints, or other network-restricted resources. |
| OpenBK7231T's CHANNEL_SetLabel() (src/cmnds/cmd_channels.c) stores channel labels received via the MQTT SetChannelLabel command using strdup() with no HTML sanitization. CHANNEL_GetLabel() returns these labels unsanitized, and they are rendered via hprintf255() at 15+ locations in src/httpserver/http_fns.c with no HTML encoding. An attacker with MQTT broker access (commonly unauthenticated in real deployments) can set a channel label containing a <script> payload that executes when any user views the device's web panel. |
| OpenBK7231T's /cfg_wifi_set endpoint (src/httpserver/http_fns.c) accepts configuration changes via a plain GET request with no CSRF token. If the `web_admin_password_enabled` parameter is absent from the request, an else-branch silently clears the device's web admin password to an empty string. A one-click CSRF payload (e.g. an <img> tag pointing at /cfg_wifi_set with new SSID/password parameters and web_admin_password_enabled omitted) visited by an authenticated admin's browser both hijacks the device's WiFi configuration and disables its web password protection. |
| Memos' webhook dispatch function safeDialContext() (internal/webhook/webhook.go) resolves the target hostname via net.DefaultResolver.LookupHost() and validates the resulting IPs against reserved ranges, but then dials net.JoinHostPort(host, port) using the original hostname rather than the already-validated IP address. Because net.Dialer.DialContext() performs its own independent DNS resolution, an attacker controlling DNS for the webhook's hostname (e.g. via a short TTL) can return a public, allowed IP during validation and a different, internal IP at dial time — a classic time-of-check/time-of-use DNS-rebinding bypass of the SSRF protection. |
| OpenPLC Runtime v3's compile_program() function (webserver/openplc.py) parses `(*FILE:path content*)` directives from uploaded Structured Text (.st) program files and writes the referenced content to `os.path.join('./core', file_path)` with no validation that file_path stays within the ./core directory. A crafted .st file containing a directive such as `(*FILE:../../../etc/cron.d/x * * * * root <command>*)` writes attacker-controlled content to an arbitrary filesystem path, enabling remote code execution (e.g. via cron or SSH authorized_keys). A path-validation function, validate_file_path(), exists elsewhere in the codebase (webserver/credentials.py) but is never invoked from compile_program(), leaving the sink unprotected. OpenPLC additionally ships with hardcoded default credentials (openplc:openplc), lowering the practical bar for exploitation. |
| WLED's GET /json/cfg endpoint (registered in wled00/wled_server.cpp) calls serveJson() with no settings-PIN check, unlike the /edit endpoint which explicitly checks correctPIN, disclosing the device's general configuration (network, hardware, LED setup) to any unauthenticated client on the network. Separately, the settings-PIN unlock state is tracked via a single global boolean `correctPIN` (wled00/wled.h), not per-session state: once any single client submits the correct 4-digit PIN via POST /json, correctPIN becomes true for every client, granting all subsequent unauthenticated clients full configuration-write access (OTA firmware updates, WiFi reconfiguration, factory reset) until the device reboots. |
| The LINUXTCP port of FreeModbus contains an off-by-one bounds check in xMBPortTCPPool() (demo/LINUXTCP/port/porttcp.c). The check `if (usTCPFrameBytesLeft > MB_TCP_BUF_SIZE)` uses a strict greater-than comparison instead of greater-than-or-equal against the 263-byte MB_TCP_BUF_SIZE limit. An MBAP frame with a Length field of 264 makes usTCPFrameBytesLeft equal to 263, which passes the flawed check, and the subsequent recv() call writes up to 263 bytes starting at buffer offset 7 into the 263-byte static buffer aucTCPBuf, overflowing it by 7 bytes into the adjacent static variable usTCPBufPos. A single crafted, unauthenticated Modbus TCP packet triggers the overflow, since Modbus has no built-in authentication. |
| dr_libs dr_wav.h (all versions through current master) contains an integer overflow in W64 CUE chunk metadata parsing. In drwav__metadata_process_chunk(), a stage-1 capacity estimate truncates the 64-bit W64 chunk sizeInBytes to size_t before dividing by DRWAV_CUE_POINT_BYTES; on 32-bit builds this truncation causes the pre-allocated extra metadata capacity to be computed incorrectly. The subsequent read in drwav__read_cue_to_metadata_obj() computes the actual cue point count and allocation size using the full-precision, attacker-controlled cuePointCount field without cross-checking it against the stage-1 capacity estimate, and the only bounds enforcement on the resulting memory region (drwav__metadata_get_memory()) is a DRWAV_ASSERT, which compiles to a no-op under -DNDEBUG (the default for release builds). A crafted W64 WAV file can therefore cause a heap buffer overflow in any 32-bit application parsing untrusted WAV metadata. |
| ESPHome through 2026.7.0-dev contains an operator-precedence bug in the cv.url() validator in esphome/config_validation.py: `if parsed.scheme and parsed.netloc or parsed.scheme == "file": return parsed.geturl()`. Because `and` binds tighter than `or`, any file: URI passes validation regardless of netloc. This validator gates the `url:` field of the external_components YAML directive's git source schema, which is passed to `git clone` (git supports file:// natively). A crafted `external_components` block with `url: "file:///attacker/repo"` clones an attacker-controlled local path, which is then added to Python's import machinery via ESPHome's component loader, executing arbitrary Python code when the YAML configuration is processed (e.g. via `esphome config`/`esphome run`). |
| Paperless-ngx's MailAccountViewSet.test() action, when called with an existing account's ID and a masked password field, reuses the stored password, account_type, refresh_token, and expiration from that existing account while allowing the caller to supply a different imap_server, imap_port, and imap_security in the same request. The test connection then authenticates to the caller-specified server using the real stored credentials. A user holding only object-level change_mailaccount permission on the target account (not full admin) can redirect the test connection to an attacker-controlled IMAP host, causing the real stored IMAP password or OAuth token to be sent to that host. |
| Grocy's API request-body parser (controllers/Api/BaseApiController.php, GetParsedAndFilteredRequestBody) purifies incoming field values with HTMLPurifier, then manually reverses HTML-entity encoding of the resulting output by replacing &lt;, &gt;, and &amp; back to <, >, and & immediately after purification. This double-decode reconstructs live HTML/script tags from the entity-encoded form that HTMLPurifier produced to neutralize them, re-introducing stored XSS across API-writable fields (products, recipes, stock, users, chores, and others) that are rendered elsewhere without re-sanitization. |
| Miantang/IoT-PHP's index.php implements a POST /userlogin route that reads the password directly from $_POST['pwd'] with no sanitization and concatenates it into a raw SQL string: mysql_query("select * from userlists where username='$username' and password='$password' limit 1"). The username value is passed through htmlspecialchars(), which does not encode single quotes by default and therefore does not prevent SQL injection through the password field. An unauthenticated attacker can submit a payload such as pwd=' OR '1'='1 to bypass authentication and, via UNION-based injection, extract arbitrary data from the database. |
| DjangoCRM ships with its Django SECRET_KEY hardcoded directly in the committed webcrm/settings.py rather than read from an environment variable. Since this key is used for session signing, CSRF token generation, and password reset tokens, anyone who reads the public repository can forge valid session cookies (including for the superadmin account), forge CSRF tokens, and forge password reset tokens, achieving full account takeover. The repository also ships with DEBUG=True as the default, causing error pages to leak database credentials, email credentials, OAuth data, and internal file paths. |
| Firefly III's webhook URL validator (IsValidWebhookUrl.php) filters most private/reserved IPv4 ranges but contains an explicit early-return that allows any resolved address in 127.0.0.0/8, permitting an authenticated user (with webhooks enabled, which is off by default) to configure a webhook targeting loopback services on the server. Additionally, the validator resolves the target hostname once via gethostbyname() at validation time, but the actual outbound request (StandardWebhookSender.php, via Guzzle) re-resolves the hostname independently at send time, allowing a DNS-rebinding attacker to pass validation against a public IP and have the real request delivered to a private or internal address. The webhook response body is only written to a server-side debug log, not returned to the triggering user, so this is a blind SSRF primitive rather than one with direct response read-back. |
| toner-management's admin state-changing handlers (add.php, edit.php, delete.php under admin/toners, admin/toner-brands, admin/printers, and related admin subdirectories) executed INSERT/UPDATE/DELETE database operations with no authentication or authorization check, while access control was enforced only in listing views. An unauthenticated remote attacker could invoke these handlers directly to create, modify, or destroy application data. The vendor has since merged a fix requiring an authenticated admin session before any such handler proceeds. |
| Cotonti CMS's Comments plugin deserializes user-supplied data without restricting the classes that may be instantiated. In plugins/comments/controllers/actions/CreateAction.php, a `ci` POST parameter obtained via `cot_import('ci', 'P', 'TXT')` (trim-only sanitization) is passed to `unserialize(base64_decode($ci))` with no `allowed_classes` restriction, reachable by any member with write access to comments (the default `Auth_members => 'RW'` setting in plugins/comments/comments.setup.php). In plugins/comments/controllers/actions/EditAction.php, a `cb` parameter is similarly deserialized via `unserialize(base64_decode($this->comeback))` in prepareComeBack(), reachable by any member editing their own comment. Because unserialize() is called without allowed_classes, an attacker can construct a serialized PHP object of any class loaded by Cotonti (a PHP Object Injection primitive). This was demonstrated in practice using Cotonti's own MySQL_cache class: a crafted serialized MySQL_cache object, once deserialized and later garbage-collected, triggers its __destruct()->flush() chain, causing an attacker-controlled INSERT INTO cot_cache with attacker-chosen row values — confirming genuine POP-chain exploitation, with further impact (including potential RCE) contingent on other gadget chains available in a given Cotonti installation's loaded classes. A third sink in DeleteAction.php contains the identical unserialize() pattern but is gated behind an admin-only authorization check and is not reachable by ordinary members. |
| Subrion CMS's admin grid sorting helper, _gridGetSorting() in includes/classes/ia.base.controller.admin.php, whitelists the `dir` (ASC/DESC) request parameter via in_array(), but falls back to the raw, attacker-supplied `sort` GET parameter whenever the requested key is not present in the per-controller $_gridSorting whitelist array: `$column = isset($this->_gridSorting[$params['sort']]) ? ... : $params['sort'];`, which is then placed into `sprintf(' ORDER BY %s`%s` %s', $tableAlias, $column, $direction)` with only backtick-quoting and no escaping. Because a backtick in the payload breaks out of the identifier context, an authenticated admin session can inject arbitrary SQL (error-based via EXTRACTVALUE, or time-based via SLEEP()) to extract database contents including administrator password hashes. Most of Subrion's ~29 admin grid controllers either define no $_gridSorting whitelist at all (e.g. pages.php, transactions.php, languages.php) or an incomplete one covering only some of their sortable columns (e.g. members.php whitelists only 1 of 7 sortable fields), making the vast majority of admin grid endpoints exploitable. |
| Bolt CMS renders content field values through Twig's full application-level Environment with no SandboxExtension registered anywhere in the codebase. In src/Entity/Field.php, getTwigValue() calls shouldBeRenderedAsTwig(), which gates rendering only on the field definition's allow_twig flag and a regex checking for `{{`, `{%`, or `{#`; when true, the raw field value is compiled and rendered via `self::getTwig()->createTemplate($value)->render(['record' => $this->getContent()])` with no sandboxing. Bolt's own bundled config/bolt/contenttypes.yaml sets `allow_twig: true` on the default "pages" contenttype's content field out of the box. Any user with edit access to that content type (a standard editor role, not just an administrator) can inject a Twig payload such as `{{ ['id']|map('passthru')|join }}` that executes arbitrary OS commands when the content is saved and rendered, achieving remote code execution as the web server user. |