Jul 28, 2026·6 min read·3 visits
Unauthenticated remote attackers can bypass webhook authorization and spoof transaction events by exploiting a fail-open design when custom registration paths are configured in the pytonapi dispatcher.
An authentication bypass vulnerability exists in the pytonapi library when custom paths are registered in the TonapiWebhookDispatcher. The application fails to retrieve or store secure tokens for custom paths, leading to a fail-open authorization check that allows unauthenticated remote attackers to send spoofed webhook events directly to internal handlers.
The pytonapi library provides a Python Software Development Kit (SDK) for TONAPI, enabling developer integration with The Open Network (TON) blockchain. The SDK includes a webhook dispatcher class, TonapiWebhookDispatcher, designed to receive and verify asynchronous event notifications such as ledger transactions and smart contract deployments. To ensure request integrity, the dispatcher relies on authentication tokens supplied via the HTTP Authorization header of incoming POST requests.
When developers implement the default webhook routing configuration, the library registers and verifies paths correctly. However, the dispatcher allows developers to register custom endpoint paths using the path keyword parameter on handlers. If a custom path is specified, the internal initialization routine neglects to populate the corresponding verification tokens for that specific route.
This omission results in a logical disconnect within the routing and verification pipeline. Incoming requests directed to custom paths bypass the authentication guard entirely because of a fail-open execution design. An unauthenticated remote attacker can exploit this condition to inject forged transaction payloads directly into user-defined event handlers.
The flaw resides in the initialization sequence within pytonapi/webhook/dispatcher.py. During the invocation of the setup() method, the dispatcher iterates over registered event types to register hook endpoints with the upstream TONAPI client. In versions prior to 2.2.1, the method retrieves tokens solely for the hardcoded suffixes defined in self.DEFAULT_SUFFIXES.
These default suffixes correspond to standard endpoints like /hook/account-tx. If a handler is registered with a custom path (such as /hook/custom), the dispatcher records the custom path for routing but fails to request or associate a secure authorization token with this path inside the self._tokens dictionary. As a consequence, the token lookup table lacks keys representing custom-registered paths.
When the dispatcher receives an HTTP POST request, the process() method retrieves the target route and performs a lookup: expected_token = self._tokens.get(path). For custom paths, this lookup returns None. The validation logic is structured as a conditional check: if expected_token is not None and authorization != f"Bearer {expected_token}": raise TONAPIError(...). Because the expected token is None, the entire conditional block is evaluated as False, bypassing the validation check and executing the handler.
The vulnerable implementation of the dispatcher setup sequence relies on default suffixes to create webhook tokens:
# Vulnerable initialization block in pytonapi <= 2.2.0
suffix = self.DEFAULT_SUFFIXES[event_type]
local_path = self._path + suffix
webhook = await self._client.ensure(f"{self._url}{suffix}")
self._tokens[local_path] = webhook.token # Token populated only for default suffixThe matching authentication logic inside process() relies on a fail-open validation approach:
# Fail-open checking logic in process()
expected_token = self._tokens.get(path) # Resolves to None for custom paths
if expected_token is not None and authorization != f"Bearer {expected_token}":
raise TONAPIError("Invalid webhook token") # Skipped entirelyThe remediation applied in version 2.2.1 modifies the setup loop to iterate over all distinct paths defined across all handlers:
# Remedied initialization loop in pytonapi 2.2.1
for local_path in sorted({path for _, _, path in handlers}):
webhook = await self._client.ensure(self._endpoint_for_path(local_path))
self._tokens[local_path] = webhook.token # Token is correctly generated and mappedThis structural shift ensures that every custom route receives a dedicated token. The reverse path mapper was also refactored to handle multiple paths reliably.
To exploit this vulnerability, an attacker must first locate an application running a vulnerable version of pytonapi that registers custom paths for incoming webhook payloads. Because the custom endpoint must be publicly accessible to receive updates from the TONAPI services, the endpoint is exposed directly to the internet.
No specialized exploitation tools are required to trigger the vulnerability. The attacker can structure an HTTP POST request targeting the custom URL path. The request body must contain a structured JSON payload mimicking a legitimate blockchain event, such as a transaction receipt.
Because of the lack of token validation, the attacker does not need to supply a valid Authorization header. Sending the request with no authorization header, or with a randomized dummy string, succeeds. The server processes the fake transaction payload as legitimate, triggering the application's processing routines which can lead to spoofed ledger deposits.
Below is a schematic mapping of the vulnerability logical flow:
The vulnerability allows complete bypass of authentication controls, leading to a High integrity impact. An attacker cannot read sensitive configuration values directly through this endpoint, keeping confidentiality impact low or none. However, the integrity of application-level transactions is completely compromised.
In applications handling financial actions or cryptocurrency exchanges, webhook dispatchers are utilized to verify user deposits and payments. Spoofing these webhooks allows attackers to claim credit for arbitrary transactions without actually depositing funds onto the blockchain. This can lead to severe financial discrepancies.
This logical flaw is classified under CWE-287 (Improper Authentication) and maps to MITRE ATT&CK technique T1190 (Exploit Public-Facing Application). Because it requires zero interaction from users and can be performed with low complexity over standard HTTP, the CVSS v3.1 score is calculated as 7.5 (High).
The definitive resolution for this issue is to upgrade the pytonapi installation to version 2.2.1 or later. This version ensures proper token generation and enforcement for all custom paths. The package can be upgraded from PyPI using standard package management utilities.
If updating the dependency is not immediately possible, developers must mitigate the risk by eliminating the use of custom paths. Removing the path argument from webhook decorator registrations forces the library to fall back onto its default suffixes, which are correctly authenticated even in vulnerable library versions.
Additionally, network-level ingress filtering can be implemented to restrict incoming requests to the webhook endpoints. Standard TONAPI webhook requests originate from known, documented server IP ranges, allowing developers to construct firewall or reverse proxy rules to drop requests originating from unauthorized addresses.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
pytonapi nessshon | >= 2.0.0, < 2.2.1 | 2.2.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-287 (Improper Authentication) |
| Attack Vector | Network |
| CVSS v3.1 Score | 7.5 (High) |
| Impact | High Integrity Compromise |
| Exploit Status | PoC Available |
| KEV Status | Not Listed |
The software does not prove, or insufficiently proves, the identity of an actor before granting access to resources.
An issue in the ruby-oauth2 gem allows unauthenticated attackers to steal OAuth access tokens or perform Server-Side Request Forgery (SSRF) via a protocol-relative URI in HTTP Location redirect headers.
Quiet-Terminal-Interactive's QTINeon version 1.0.0 is vulnerable to uncontrolled resource consumption and relay-to-host network amplification. The reconnect request handler lacks table size constraints, rate limiting, and request deduplication, allowing unauthenticated attackers to crash the relay server and overwhelm target hosts.
Poweradmin is affected by a critical Host Header Injection vulnerability within its Single Sign-On (SSO) and logout authentication mechanisms. The application dynamically constructs external redirection and callback URLs using the client-controlled HTTP Host header. An unauthenticated attacker can exploit this behavior to poison OAuth and SAML callback parameters, redirecting authentication credentials directly to a malicious external server. This allows full administrative account takeover without credentials when a victim accesses a manipulated authentication link.
The nono-cli package verification mechanism fails open when both the lockfile entry and local trust bundle are absent. This allows local attackers to execute unverified package profiles and native host session hooks by removing metadata configurations, bypassing cryptographic integrity controls.
An Insecure Direct Object Reference (IDOR) vulnerability exists in SourceCodester Leave Application System 1.0 within the User Information Handler component. The application processes client-supplied database identifiers via URL parameters without executing proper authorization checks or session validation. This allows remote, unauthenticated attackers to view sensitive administrative and employee records by altering the 'id' parameter.
An uncontrolled resource consumption vulnerability exists in the Scala-based http4s-blaze-server package of the http4s/blaze library. The vulnerability allows remote, unauthenticated attackers to cause an Out of Memory Error (OOM) and JVM crash by streaming a continuous sequence of small or empty WebSocket continuation frames with the FIN bit set to 0. This bypasses typical payload size checks because of the JVM's per-object allocation overhead, leading to rapid heap exhaustion with minimal network bandwidth.