andrewmusselman opened a new issue, #712:
URL: https://github.com/apache/tooling-trusted-releases/issues/712

   **ASVS Requirement:** 4.1.1 — Verify that every HTTP response with a message 
body contains a Content-Type header field that matches the actual content, 
including the charset parameter
   **Severity:** Low
   **CWE:** CWE-436 (Interpretation Conflict)
   
   ### Description
   
   Several endpoints and response helper classes set `mimetype` without an 
explicit `charset` parameter. While werkzeug may implicitly append 
`charset=utf-8` for `text/*` types, it does not do so for `application/json`. 
ASVS 4.1.1 requires charset to be explicitly specified.
   
   ### Affected Locations
   
   **1. `atr/get/root.py` (lines 118–122)** — `/miscellaneous/resolved.json` 
endpoint:
   ```python
   return quart_response.Response(content, mimetype="application/json")  # No 
charset
   ```
   
   **2. `atr/post/upload.py` (lines 168–173)** — `_json_error` and 
`_json_success` helpers:
   ```python
   def _json_error(message: str, status: int) -> web.WerkzeugResponse:
       return response.Response(json.dumps({"error": message}), status=status, 
mimetype="application/json")
   
   def _json_success(data: dict[str, str], status: int = 200) -> 
web.WerkzeugResponse:
       return response.Response(json.dumps(data), status=status, 
mimetype="application/json")
   ```
   
   **3. `atr/web.py` (lines 211–259)** — Custom response classes 
(`ElementResponse`, `ShellResponse`, `TextResponse`) use `mimetype` without 
explicit charset:
   ```python
   class TextResponse(quart.Response):
       def __init__(self, text: str, status: int = 200) -> None:
           super().__init__(text, status=status, mimetype="text/plain")
   ```
   
   **4. `atr/post/tokens.py` (lines 53–56)** — JWT endpoint returns a token as 
`TextResponse`; the more specific `application/jwt` media type would be 
appropriate.
   
   ### Recommended Fix
   
   Use `content_type` instead of `mimetype` to include charset in all cases:
   
   ```python
   # JSON helpers
   return response.Response(
       json.dumps({"error": message}),
       status=status,
       content_type="application/json; charset=utf-8"
   )
   
   # Custom response classes
   class TextResponse(quart.Response):
       def __init__(self, text: str, status: int = 200) -> None:
           super().__init__(text, status=status, content_type="text/plain; 
charset=utf-8")
   
   # JWT endpoint (optional improvement)
   return quart.Response(jwt_token, content_type="application/jwt; 
charset=utf-8")
   ```
   
   Consider also adding an `after_request` handler as defense-in-depth to catch 
any future omissions:
   
   ```python
   @app.after_request
   async def ensure_charset(response):
       if response.content_type and "charset" not in response.content_type:
           if response.content_type.startswith("text/"):
               response.content_type = f"{response.content_type}; charset=utf-8"
       return response
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to