Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] PydanticInvalidForJsonSchema error when requesting /docs or /redoc endpoints #725

Open
1 task done
b1tst0rm opened this issue Apr 5, 2024 · 1 comment
Open
1 task done
Labels
bug Something isn't working

Comments

@b1tst0rm
Copy link

b1tst0rm commented Apr 5, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Empire Version

5.9.5

Python Version

3.11.8

Operating System

Kali Rolling 2023.3

Database

MariaDB

Current Behavior

When requesting /docs (or /redoc), those endpoints 200 however the request for openapi.json is a 500. The following error output is generated by the server:

[INFO]: 10.255.255.253:37778 - "GET /redoc?vscodeBrowserReqId=1712347444857 HTTP/1.1" 200 
[INFO]: 10.255.255.253:37778 - "GET /openapi.json HTTP/1.1" 500 
[ERROR]: Exception in ASGI application
 
Traceback (most recent call last):
...
  File "/home/<redacted>/empire/.venv/lib/python3.11/site-packages/pydantic/json_schema.py", line 2074, in handle_invalid_for_json_schema
    raise PydanticInvalidForJsonSchema(f'Cannot generate a JsonSchema for {error_info}')
pydantic.errors.PydanticInvalidForJsonSchema: Cannot generate a JsonSchema for core_schema.PlainValidatorFunctionSchema ({'type': 'no-info', 'function': <bound method CustomOptionSchema.check_value of <class 'empire.server.api.v2.shared_dto.CustomOptionSchema'>>})

For further information visit https://errors.pydantic.dev/2.5/u/invalid-for-json-schema

Expected Behavior

When requesting /docs, FastAPI Swagger UI loads without error showing API endpoints.

Steps To Reproduce

  1. On Kali 2023.3, run setup/install.sh
  2. Activate the virtualenv and run the server: source .venv/bin/activate && ./ps-empire server
  3. Visit in a browser: http://localhost:1337/docs

Anything else?

It appears the issue lies within the empire.server.api.v2.shared_dto.CustomOptionSchema class, particularly the methods check_value and check_suggested_values trigger the PydanticInvalidForJsonSchema error.

https://github.com/BC-SECURITY/Empire/blob/main/empire/server/api/v2/shared_dto.py#L33

The 500 can be "fixed" by commenting the following lines of empire/server/api/v2/shared_dto.py and then you can access the /docs and /redoc endpoints without issues:

Lines 35-43

class CustomOptionSchema(BaseModel):
    description: str
    required: bool
    value: str
    suggested_values: list[str]
    strict: bool
    value_type: ValueType

    # Ensure the functionality of pydantic v1 coercing values to strings
    # https://github.com/pydantic/pydantic/issues/5606
#    @field_validator("value", mode="plain")
#    @classmethod
#    def check_value(cls, v):
#        return str(v)
#
#    @field_validator("suggested_values", mode="plain")
#    @classmethod
#    def check_suggested_values(cls, v):
#        return [str(value) for value in v]
@b1tst0rm b1tst0rm added the bug Something isn't working label Apr 5, 2024
@vinnybod
Copy link

vinnybod commented Apr 6, 2024

Thanks, I have a fix for this that will be in 5.10 in a couple weeks. until then, this is the patch that can be applied (git apply <patch>)

diff --git a/empire/server/api/v2/shared_dto.py b/empire/server/api/v2/shared_dto.py
index 353ad15f..7664c0f4 100644
--- a/empire/server/api/v2/shared_dto.py
+++ b/empire/server/api/v2/shared_dto.py
@@ -1,7 +1,11 @@
 from enum import Enum
 from typing import Annotated, Any
 
-from pydantic import BaseModel, BeforeValidator, ConfigDict, field_validator
+from pydantic import (
+    BaseModel,
+    BeforeValidator,
+    ConfigDict,
+)
 
 from empire.server.core.db import models
 
@@ -22,26 +26,22 @@ class ValueType(str, Enum):
     file = "FILE"
 
 
+# Ensure the functionality of pydantic v1 coercing values to strings
+# https://github.com/pydantic/pydantic/issues/5606
+def coerce_to_string(v: Any):
+    if isinstance(v, list):
+        return [str(value) for value in v]
+    return str(v)
+
+
 class CustomOptionSchema(BaseModel):
     description: str
     required: bool
-    value: str
-    suggested_values: list[str]
+    value: Annotated[str, BeforeValidator(coerce_to_string)]
+    suggested_values: Annotated[list[str], BeforeValidator(coerce_to_string)]
     strict: bool
     value_type: ValueType
 
-    # Ensure the functionality of pydantic v1 coercing values to strings
-    # https://github.com/pydantic/pydantic/issues/5606
-    @field_validator("value", mode="plain")
-    @classmethod
-    def check_value(cls, v):
-        return str(v)
-
-    @field_validator("suggested_values", mode="plain")
-    @classmethod
-    def check_suggested_values(cls, v):
-        return [str(value) for value in v]
-
 
 class OrderDirection(str, Enum):
     asc = "asc"

cmndcntrlcyber pushed a commit to cmndcntrlcyber/Empire that referenced this issue May 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants