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

Preserve exception messages for wrapped Django exceptions #8051

Merged
merged 4 commits into from
Oct 11, 2022

Conversation

vanschelven
Copy link
Contributor

I did not review your contributing guidelines, nor did I test anything using the automated tests. I also did only the most minimal of non-automated testing. Still, I thought I'd leave this here, as it may be useful to others. See it as an "issue description with PoC of a solution" if you will.

The problem: when raising standard Django exceptions Http404 or PermissionDenied, the error messages of these exceptions do not show up in the DRF's response. This is because these exceptions are recreated in the piece of code that this PR adapts.

In this PR this is solved by making sure the recreated exceptions are recreated with the same arguments as the original versions. Whether the signatures actually match up, I did not check properly.

@tomchristie
Copy link
Member

It looks like there's a test case that'd need updating...

_ TestFilterBackendAppliedToViews.test_get_instance_view_filters_out_name_with_filter_backend _
tests/test_generics.py:522: in test_get_instance_view_filters_out_name_with_filter_backend
    assert response.data == {'detail': 'Not found.'}
E   AssertionError: assert {'detail': Er...='not_found')} == {'detail': 'Not found.'}
E     Differing items:
E     {'detail': ErrorDetail(string='No BasicModel matches the given query.', code='not_found')} != {'detail': 'Not found.'}
E     Use -v to get the full diff

@vanschelven
Copy link
Contributor Author

It looks like there's a test case that'd need updating...

Indeed, but what would the desired behavior be? If I understand it correctly that test shows that the response data of a request contains some Python objects (as opposed to pure json)... perhaps because of mocking at some level?

Copy link

@jeking3 jeking3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just ran into this issue as well and had to add similar code to my own exception handler that runs and then calls the drf_exception_handler. However it is missing a unit test.

Without this code the resulting detail is "Not Found." but with this code it is whatever got put into the Http404 (usually from get_object_or_404, such as "No matches the given query." - therefore testing to make sure the resulting message for the exception is not "Not Found." would be an acceptable unit test.

@stale
Copy link

stale bot commented Apr 18, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Apr 18, 2022
@vanschelven
Copy link
Contributor Author

Reading the discussion above it appears to me that the staleness is caused by a lack of response from @tomchristie on my question on how to proceed.

@stale stale bot removed the stale label Apr 29, 2022
@stale
Copy link

stale bot commented Jul 12, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jul 12, 2022
@vanschelven
Copy link
Contributor Author

I've updated the failing test to be succeeding; this at least amounts to having an implicit test on the newly introduced behavior as more or less suggested by @jeking3

@stale stale bot removed the stale label Jul 27, 2022
@vanschelven
Copy link
Contributor Author

If I understand it correctly that test shows that the response data of a request contains some Python objects (as opposed to pure json)... perhaps because of mocking at some level?

As I understand now: no. ErrorDetail are picked up by another part of the DRF machinery before an actual HTTP response is sent over the wire. So having a test match on ErrorDetail is fine.

@vanschelven
Copy link
Contributor Author

@tomchristie anything I could do to move this forward?

@vanschelven
Copy link
Contributor Author

vanschelven commented Oct 11, 2022 via email

@tomchristie
Copy link
Member

Okay, yup this seems reasonable. 👍

@tomchristie tomchristie merged commit 56946fa into encode:master Oct 11, 2022
kernicPanel added a commit to openfun/joanie that referenced this pull request Mar 18, 2024
DRF verson 3.15 adds more descriptive not found messages.
encode/django-rest-framework#8051
kernicPanel added a commit to openfun/joanie that referenced this pull request Mar 18, 2024
DRF verson 3.15 adds more descriptive not found messages.
encode/django-rest-framework#8051
mjeammet added a commit to suitenumerique/people that referenced this pull request Mar 21, 2024
djangorestframework released version 3.15.0, which includes modifications of details
upon returning 404 errors (encode/django-rest-framework#8051).

This commit changes the expected details of 404 responses in our tests, to match 3.15.0.
mjeammet added a commit to suitenumerique/people that referenced this pull request Mar 21, 2024
djangorestframework released version 3.15.0, which includes modifications of
details upon returning 404 errors (see related issue
encode/django-rest-framework#8051).

This commit changes the expected details of 404 responses in our tests,
to match DRF 3.15.0.
mjeammet added a commit to suitenumerique/people that referenced this pull request Mar 21, 2024
djangorestframework released version 3.15.0, which includes modifications of
details upon returning 404 errors (see related issue
encode/django-rest-framework#8051).

This commit changes the expected details of 404 responses in our tests,
to match DRF 3.15.0.
jstvz added a commit to SFDO-Tooling/MetaDeploy that referenced this pull request Apr 4, 2024
DRF now passes through Django exception details. Doubtful whether we
should be testing this.

See: encode/django-rest-framework#8051
@ferndot
Copy link
Contributor

ferndot commented Oct 4, 2024

I am very concerned about the security implications of this change. It publicly exposes information, such as internal model names, which could potentially assist a malicious user. I see that it was intended to be helpful, but the Http404 and PermissionDenied exceptions both seem like places where a more generic error message is appropriate.

@liammonahan
Copy link

I have to agree with @ferndot about this change. I think it should be reverted since it makes it more difficult to obscure the underlying models involved in an endpoint.

The fact that the original author of this proposed change started off their PR with "I did not review your contributing guidelines" should have been a tip-off that they weren't going to be thinking very hard about the broader effects of this change on other users of DRF.

@ulgens
Copy link

ulgens commented Feb 4, 2025

+1 for @ferndot and @liammonahan

I can't think of a valid use case that I need error details from model layer, in a 404 response coming from an API handler.

@vanschelven vanschelven deleted the preserve-error-messages branch February 4, 2025 08:25
@auvipy
Copy link
Member

auvipy commented Feb 4, 2025

can any of you send a PR with improvement suggested here? specially the security concerns raised here

@vanschelven
Copy link
Contributor Author

I can't think of a valid use case that I need error details [..]

(Ellipsis to make my point in an evil way). The fact that this information is originally put on the later-wrapped exceptions in the first place is strong evidence that there are some contexts in which this information is useful.

To give an actual example: In my original use-case, the API was internal, so exposure to the API endpoint was perfectly fine and helped in debugging.

I haven't the time to look into this right now (I'm not using the DRF on any of my projects currently)... but wouldn't it be possible to come up with a solution that meets both the original concern and the later-raised concerns about information exposure? E.g. by keeping the solution from the present PR, while later hiding this information (before it's exposed over the wire) by default (with options for customization).

IIRC this is what Django does too: exceptions with rich information (as evidenced by the fact that this information is present in the wrapped exceptions) and a good set of customizable handlers with no-exposure by default. I also recall DRF has something along these lines...

@ulgens
Copy link

ulgens commented Feb 4, 2025

(I destroyed my previous comment, no need to start any pointless discussion, please ignore it if you managed to catch it.)

@auvipy I can try to handle this tomorrow.

@auvipy
Copy link
Member

auvipy commented Feb 5, 2025

(I destroyed my previous comment, no need to start any pointless discussion, please ignore it if you managed to catch it.)

@auvipy I can try to handle this tomorrow.

ping me when you have something to review

@llybin
Copy link

llybin commented Mar 13, 2025

REST_FRAMEWORK = {
    "EXCEPTION_HANDLER": "drf.exceptions.custom_exception_handler",
}

if someone needs to keep the previous behavior, just create custom_exception_handler

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants