Skip to content

Conversation

@obenland
Copy link
Member

@obenland obenland commented Dec 5, 2025

Fixes #2593

Proposed changes:

  • Updates Webfinger::get_data() to use Http::get() for signed HTTP requests.
  • Uses http_request_args filter to override the Accept header to application/jrd+json.

Some ActivityPub implementations like GoToSocial require HTTP signatures for all requests, including WebFinger lookups. Previously, WebFinger requests were made without signatures, causing 401 Unauthorized errors when trying to resolve mentions for users on these platforms.

Other information:

  • Have you written new tests for your changes, if applicable?

Testing instructions:

  • Verify WebFinger lookups work against standard Mastodon instances.
  • Verify WebFinger lookups work against GoToSocial instances (requires a GoToSocial account to test mentions).
  • Run existing WebFinger unit tests with npm run env-test -- --filter=Webfinger.

Changelog entry

  • Automatically create a changelog entry from the details below.
Changelog Entry Details

Significance

  • Patch
  • Minor
  • Major

Type

  • Added - for new features
  • Changed - for changes in existing functionality
  • Deprecated - for soon-to-be removed features
  • Removed - for now removed features
  • Fixed - for any bug fixes
  • Security - in case of vulnerabilities

Message

Mentions now work with GoToSocial and other platforms that require signed requests.

Some ActivityPub implementations like GoToSocial require HTTP signatures
for all requests, including WebFinger lookups. Previously, WebFinger
requests were made without signatures, causing 401 Unauthorized errors
when trying to resolve mentions for users on these platforms.

This updates Webfinger::get_data() to use Http::get() which includes
HTTP signature authentication, while using a filter to override the
Accept header to the WebFinger-appropriate application/jrd+json.

Fixes #2593.
Copilot AI review requested due to automatic review settings December 5, 2025 16:06
@obenland obenland self-assigned this Dec 5, 2025
@obenland obenland requested a review from a team December 5, 2025 16:06
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds HTTP signature support to WebFinger requests to ensure compatibility with ActivityPub implementations like GoToSocial that require signed HTTP requests for all endpoints. Previously, unsigned WebFinger requests resulted in 401 Unauthorized errors when resolving mentions on these platforms.

Key Changes:

  • Replaced wp_safe_remote_get() with Http::get() to enable HTTP signatures on WebFinger requests
  • Implemented http_request_args filter to set the Accept header to application/jrd+json
  • Simplified error handling by removing the HTTP status code check

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
includes/class-webfinger.php Updates WebFinger request mechanism to use signed HTTP requests via Http::get() and adds Accept header through filter
.github/changelog/2594-from-description Adds changelog entry documenting the bug fix for mention compatibility

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

\remove_filter( 'http_request_args', $set_accept_header );

if ( \is_wp_error( $response ) || \wp_remote_retrieve_response_code( $response ) >= 400 ) {
if ( \is_wp_error( $response ) ) {
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

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

The removal of the HTTP status code check || \wp_remote_retrieve_response_code( $response ) >= 400 means that 4xx and 5xx HTTP errors will no longer be caught and converted to WP_Error. This could allow invalid responses (like 404 or 500) to proceed to parsing, potentially causing downstream errors. The status code validation should be retained alongside the WP_Error check.

Suggested change
if ( \is_wp_error( $response ) ) {
if ( \is_wp_error( $response ) || \wp_remote_retrieve_response_code( $response ) >= 400 ) {

Copilot uses AI. Check for mistakes.
)
);
$set_accept_header = function ( $args ) {
$args['headers']['Accept'] = 'application/jrd+json';
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

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

The filter function directly assigns to $args['headers']['Accept'] without checking if the 'headers' key exists. If $args['headers'] is not set, this will create it, but it's safer to check or use array merging to avoid potential issues with existing header configurations.

Suggested change
$args['headers']['Accept'] = 'application/jrd+json';
if ( ! isset( $args['headers'] ) || ! is_array( $args['headers'] ) ) {
$args['headers'] = array();
}
$args['headers'] = array_merge( $args['headers'], array( 'Accept' => 'application/jrd+json' ) );

Copilot uses AI. Check for mistakes.
Comment on lines +218 to 226
$set_accept_header = function ( $args ) {
$args['headers']['Accept'] = 'application/jrd+json';
return $args;
};

\add_filter( 'http_request_args', $set_accept_header );
$response = Http::get( $webfinger_url );
\remove_filter( 'http_request_args', $set_accept_header );

Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

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

Using a global filter for a single HTTP request creates a potential race condition in concurrent scenarios and affects all HTTP requests during execution. Consider passing headers directly to Http::get() if the method supports it, or use a more specific filter with priority to minimize side effects.

Suggested change
$set_accept_header = function ( $args ) {
$args['headers']['Accept'] = 'application/jrd+json';
return $args;
};
\add_filter( 'http_request_args', $set_accept_header );
$response = Http::get( $webfinger_url );
\remove_filter( 'http_request_args', $set_accept_header );
// Set Accept header directly in the request arguments to avoid global filter side effects.
$response = Http::get( $webfinger_url, array(
'headers' => array(
'Accept' => 'application/jrd+json',
),
) );

Copilot uses AI. Check for mistakes.
@obenland
Copy link
Member Author

obenland commented Dec 5, 2025

I don't think this is needed after all.

@obenland obenland closed this Dec 5, 2025
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.

Unable to tag gotosocial accounts?

3 participants