Skip to content

Cadwyn vulnerable to XSS on the docs page

High severity GitHub Reviewed Published Jul 20, 2025 in zmievsa/cadwyn • Updated Jul 23, 2025

Package

pip cadwyn (pip)

Affected versions

< 5.4.3

Patched versions

5.4.3

Description

Summary

The version parameter of the /docs endpoint is vulnerable to a Reflected XSS (Cross-Site Scripting) attack.

PoC

  1. Setup a minimal app following the quickstart guide: https://docs.cadwyn.dev/quickstart/setup/
  2. Click on the following PoC link: http://localhost:8000/docs?version=%27%2balert(document.domain)%2b%27

Impact

Refer to this security advisory for an example of the impact of a similar vulnerability that shares the same root cause.

This XSS would notably allow an attacker to execute JavaScript code on a user's session for any application based on Cadwyn via a one-click attack.

A CVSS for the average case may be: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:L/A:L

Details

The vulnerable code snippet can be found in the 2 functions swagger_dashboard and redoc_dashboard: https://github.com/zmievsa/cadwyn/blob/main/cadwyn/applications.py#L387-L413

The implementation uses the get_swagger_ui_html function from FastAPI. This function does not encode or sanitize its arguments before using them to generate the HTML for the swagger documentation page and is not intended to be used with user-controlled arguments.

    async def swagger_dashboard(self, req: Request) -> Response:
        version = req.query_params.get("version")

        if version:
            root_path = self._extract_root_path(req)
            openapi_url = root_path + f"{self.openapi_url}?version={version}"
            oauth2_redirect_url = self.swagger_ui_oauth2_redirect_url
            if oauth2_redirect_url:
                oauth2_redirect_url = root_path + oauth2_redirect_url
            return get_swagger_ui_html(
                openapi_url=openapi_url,
                title=f"{self.title} - Swagger UI",
                oauth2_redirect_url=oauth2_redirect_url,
                init_oauth=self.swagger_ui_init_oauth,
                swagger_ui_parameters=self.swagger_ui_parameters,
            )
        return self._render_docs_dashboard(req, cast("str", self.docs_url))

In this case, the openapi_url variable contains the version which comes from a user supplied query string without encoding or sanitisation. The user controlled injection ends up inside of a string in a <script> tag context: https://github.com/fastapi/fastapi/blob/master/fastapi/openapi/docs.py#L132

    f"""
    ...
    const ui = SwaggerUIBundle({{
        url: '{openapi_url}',
    """

By simply injecting a single quote we can escape from the string context and execute JavaScript like so '+alert(document.domain)+'

The resulting HTML sent back from the server contains the following injection:

  const ui = SwaggerUIBundle({
        url: '/openapi/flows.json?flows='+alert(document.domain)+'',

References

@zmievsa zmievsa published to zmievsa/cadwyn Jul 20, 2025
Published to the GitHub Advisory Database Jul 21, 2025
Reviewed Jul 21, 2025
Published by the National Vulnerability Database Jul 21, 2025
Last updated Jul 23, 2025

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
Required
Scope
Unchanged
Confidentiality
High
Integrity
Low
Availability
Low

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:L/A:L

EPSS score

Exploit Prediction Scoring System (EPSS)

This score estimates the probability of this vulnerability being exploited within the next 30 days. Data provided by FIRST.
(12th percentile)

Weaknesses

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users. Learn more on MITRE.

CVE ID

CVE-2025-53528

GHSA ID

GHSA-2gxp-6r36-m97r

Source code

Credits

Loading Checking history
See something to contribute? Suggest improvements for this vulnerability.