aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar ionite34 <[email protected]>2022-11-28 11:12:56 +0800
committerGravatar ionite34 <[email protected]>2022-11-28 11:12:56 +0800
commit0442a7cec24bff9985fb8cf59b0fb2604544eaa8 (patch)
treef077979c356dafb8278325525109a962bd94c4b3
parentAdd invalid, absolute, null byte paths to schema (diff)
Add ParsingError handling for invalid base64
-rw-r--r--snekbox/api/resources/eval.py10
-rw-r--r--snekbox/snekio.py22
-rw-r--r--tests/api/test_eval.py2
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)