Skip to content

Commit

Permalink
api: encode x-error-msg as JSON - so it does not contain <CR> or <LF>
Browse files Browse the repository at this point in the history
When the server raises an exception in a HTTP request handler context,
more often than not, the exception is sent back to the client in the
body.

Additionally, the message of the exception (if any), is also copied as
is in a x-error-msg HTTP header.

That said, HTTP headers must obey strict rules. "\r" and "\n" characters
indicate the end of the current HTTP header. When using aiohttp, the
library rejects any header that has a "\r" or "\n" in its value:

  ValueError: Newline or carriage return character detected in HTTP status message or header. This is a potential security issue.

As an example, any curtin.util.ProcessExecutionError exception will
contain "\n" characters when converted into a string.

We now encode the error message as JSON before copying it in the HTTP
header.

Signed-off-by: Olivier Gayot <[email protected]>
  • Loading branch information
ogayot committed Sep 1, 2023
1 parent b4f9029 commit 181cef0
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 2 deletions.
3 changes: 2 additions & 1 deletion subiquity/common/api/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import inspect
import json
import logging
import os
import traceback
Expand Down Expand Up @@ -173,7 +174,7 @@ async def handler(request):
headers={
"x-status": "error",
"x-error-type": type(exc).__name__,
"x-error-msg": str(exc),
"x-error-msg": json.dumps(str(exc)),
},
)
resp["exception"] = exc
Expand Down
2 changes: 1 addition & 1 deletion subiquity/common/api/tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ async def GET(self, arg: str):
self.assertEqual(resp.headers["x-status"], "error")
self.assertEqual(resp.headers["x-error-type"], "TypeError")
self.assertEqual(
resp.headers["x-error-msg"], 'missing required argument "arg"'
resp.headers["x-error-msg"], '"missing required argument \\"arg\\""'
)

async def test_error(self):
Expand Down

0 comments on commit 181cef0

Please sign in to comment.