diff options
-rw-r--r-- | snekbox/api/resources/eval.py | 10 | ||||
-rw-r--r-- | snekbox/snekio.py | 22 | ||||
-rw-r--r-- | tests/api/test_eval.py | 2 |
3 files changed, 18 insertions, 16 deletions
diff --git a/snekbox/api/resources/eval.py b/snekbox/api/resources/eval.py index 764cc0b..de54564 100644 --- a/snekbox/api/resources/eval.py +++ b/snekbox/api/resources/eval.py @@ -9,7 +9,7 @@ from snekbox.nsjail import NsJail __all__ = ("EvalResource",) -from snekbox.snekio import FileAttachment, IllegalPathError +from snekbox.snekio import FileAttachment, ParsingError log = logging.getLogger(__name__) @@ -35,7 +35,7 @@ class EvalResource: "properties": { "path": { "type": "string", - # Disallow single forward slashes, absolute paths, and null bytes + # Disallow single absolute paths, and null bytes "pattern": r"^[^/\\0].*", }, "content": {"type": "string"}, @@ -110,10 +110,8 @@ class EvalResource: py_args=req.media["args"], files=[FileAttachment.from_dict(file) for file in req.media.get("files", [])], ) - except IllegalPathError as e: - raise falcon.HTTPBadRequest( - title="Request file path failed validation", description=str(e) - ) + except ParsingError as e: + raise falcon.HTTPBadRequest(title="Request file is invalid", description=str(e)) except Exception: log.exception("An exception occurred while trying to process the request") raise falcon.HTTPInternalServerError diff --git a/snekbox/snekio.py b/snekbox/snekio.py index 2d2de6e..f57d3b0 100644 --- a/snekbox/snekio.py +++ b/snekbox/snekio.py @@ -28,16 +28,12 @@ def safe_path(path: str) -> str: return path -class AttachmentError(ValueError): - """Raised when an attachment is invalid.""" - - -class ParsingError(AttachmentError): - """Raised when an incoming file cannot be parsed.""" +class ParsingError(ValueError): + """Raised when an incoming content cannot be parsed.""" class IllegalPathError(ParsingError): - """Raised when an attachment has an illegal path.""" + """Raised when a request file has an illegal path.""" @dataclass(frozen=True) @@ -49,9 +45,17 @@ class FileAttachment: @classmethod def from_dict(cls, data: dict[str, str]) -> FileAttachment: - """Convert a dict to an attachment.""" + """ + Convert a dict to an attachment. + + Raises: + ParsingError: Raised when the dict has invalid base64 `content`. + """ path = safe_path(data["path"]) - content = b64decode(data.get("content", "")) + try: + content = b64decode(data.get("content", "")) + except (TypeError, ValueError) as e: + raise ParsingError(f"Invalid base64 encoding for file '{path}'") from e return cls(path, content) @classmethod diff --git a/tests/api/test_eval.py b/tests/api/test_eval.py index 41bdd35..64d7ba6 100644 --- a/tests/api/test_eval.py +++ b/tests/api/test_eval.py @@ -72,7 +72,7 @@ class TestEvalResource(SnekAPITestCase): result = self.simulate_post(self.PATH, json=body) self.assertEqual(result.status_code, 400) expected = { - "title": "Request file path failed validation", + "title": "Request file is invalid", "description": f"File path '{path}' may not traverse beyond root", } self.assertEqual(expected, result.json) |