Skip to content

fix(api): stop echoing the api_key value in the external knowledge 403 error - #39897

Closed
pacocartones wants to merge 1 commit into
langgenius:mainfrom
pacocartones:fix/external-knowledge-error-leaks-api-key
Closed

fix(api): stop echoing the api_key value in the external knowledge 403 error#39897
pacocartones wants to merge 1 commit into
langgenius:mainfrom
pacocartones:fix/external-knowledge-error-leaks-api-key

Conversation

@pacocartones

Copy link
Copy Markdown

Important

  1. Make sure you have read our contribution guidelines
  2. Ensure there is an associated issue and you have been assigned to it
  3. Use the correct syntax to link this PR: Fixes #<issue number>.

Summary

The external knowledge API validation probe at check_endpoint_and_api_key interpolates the raw api_key value into the ValueError message on a 403 response (api/services/external_knowledge_service.py:117). Because the exception is not wrapped by the caller, it reaches the console API's handle_value_error (api/libs/external_api.py:92-97), which (a) logs the full message via current_app.logger.exception, and (b) returns it verbatim to the caller in a 400 body ({"code": "invalid_param", "message": str(e), "status": 400}). The credential therefore lands in application logs and in the API response itself. (Sentry is unaffected: this project explicitly ignores ValueError in extensions/ext_sentry.py.)

Stop interpolating the key, keeping the auth-failure signal intact. This matches the other validations in the same file (api_key is required at lines 57, 85, and 270), which never echo the value.

Fixes #39888

Screenshots

Backend error-message change with no UI surface; the behaviour change is covered by the regression test.

Before After
400 {"code": "invalid_param", "message": "Forbidden: Authorization failed with api_key: sk-live-key-value"} — key returned to the caller and written to application logs 400 {"code": "invalid_param", "message": "Forbidden: Authorization failed with the provided api_key"} — key is never echoed

Checklist

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.
  • I ran make lint && make type-check (backend) and cd web && pnpm exec vp staged (frontend) to appease the lint gods

On the absence of a private advisory: I did not use the private advisory channel on purpose: there is nothing to disclose beyond log/observability hygiene. The tenant who submits the key already knows its value; the issue is limited to the credential being written to application logs and echoed in the 400 response to that same tenant. Sentry explicitly ignores ValueError in this project, so it never reaches the error-tracking pipeline. I have classified it accordingly — happy to move this to a private advisory if you read it differently.

Test evidence

New regression test test_check_endpoint_403_forbidden_does_not_leak_api_key in api/tests/unit_tests/services/test_external_dataset_service.py (same class and mocking pattern as the existing test_check_endpoint_403_forbidden).

Without the fix (current main):

>       assert "sk-sensitive-key-12345" not in str(exc_info.value)
E       AssertionError: assert 'sk-sensitive-key-12345' not in 'Forbidden: ...ve-key-12345'
E         'sk-sensitive-key-12345' is contained here:
E           Forbidden: Authorization failed with api_key: sk-sensitive-key-12345
FAILED test_external_dataset_service.py::TestExternalDatasetServiceCheckEndpoint::test_check_endpoint_403_forbidden_does_not_leak_api_key

With the fix applied:

test_external_dataset_service.py::TestExternalDatasetServiceCheckEndpoint::test_check_endpoint_403_forbidden PASSED
test_external_dataset_service.py::TestExternalDatasetServiceCheckEndpoint::test_check_endpoint_403_forbidden_does_not_leak_api_key PASSED
======================= 110 passed, 5 warnings in 9.49s =======================

(The full test file passes, 110/110, including the pre-existing test_check_endpoint_403_forbidden, whose Forbidden.*Authorization failed match still holds.)

Assisted-by: AI tooling (implementation and verification reviewed line by line; I understand and stand by the change).

…3 error

The validation probe in check_endpoint_and_api_key interpolated the raw
api_key into the ValueError message on a 403 response. The console API's
handle_value_error then logs the full message and returns it verbatim in
the 400 response body, writing the credential to application logs and
echoing it back to the caller.

Keep the auth-failure signal without echoing the value, consistent with
the other api_key validations in the same file. Adds a regression test
asserting the key never appears in the raised message.

Fixes langgenius#39888
@dosubot dosubot Bot added the size:XS This PR changes 0-9 lines, ignoring generated files. label Aug 2, 2026
@pacocartones

Copy link
Copy Markdown
Author

Closing as superseded by #39888, now on main via #39902. It includes the same functional fix plus a stronger regression test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XS This PR changes 0-9 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

External knowledge 403 validation error echoes the raw api_key value into logs and the response body

1 participant