ActivityPub/Primer/Uploaded JSON objects
Many ActivityPub implementations allow uploading binary or text data to the server, such as images, video, audio, etc. They can use the ActivityPub upload API or a proprietary API.
One problem with this feature is that there is not a simple mechanism in ActivityPub for determining if an object was really created by the actor identified in the attributedTo
or actor
property.
For example, an attacker could publish an activity like so:
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Create",
"id": "https://social.example/upload/mallory/file1.json",
"actor": "https://social.example/person/bob",
"object": {
"id": "https://social.example/upload/mallory/file2.json",
"type": "Note",
"attributedTo": "https://social.example/person/bob",
"content": "<p>This is a misattributed note.</p>"
}
}
Here, the misattributed note has been attributed to https://social.example/person/bob
. The only reliable way to verify that Bob actually wrote this note is to search through his outbox
to find a Create
activity that matches this id
. With tens or even hundreds of thousands of activities being typical for an ActivityPub actor, this is a difficult process for a remote server.
The heuristic most often used is the same origin check, which checks that the origin of the URL that is Bob's ID matches the origin of the URL of the activity's ID. The premise is that the server that manages these two objects would not publish false information about one of its actors. (This may not be justified even in the best of times!)
This assumption breaks down when the server at social.example
allows uploading JSON-LD files to the same domain as its other ActivityPub objects. An attacker can craft an activity that is misattributed, and remote servers that use the same-origin heuristic will not be able to tell that it is misattributed.
To mitigate this problem, there are a few steps that can be taken by both servers:
- The publishing server can use a different domain for uploaded files, such as uploads.social.example. This will prevent naive implementations that use the same-origin heuristic from trusting JSON-LD files uploaded there.
- The publishing server can disallow uploading JSON or JSON-LD files.
- When publishing servers allow plain text uploads, they should set the content type to
text/plain
. The consuming server can check that the Activity is served asapplication/ld+json
orapplication/activity+json
orapplication/json
, to make sure that files uploaded as plain text (text/plain
) are not treated as Activity Streams 2.0 JSON-LD.
Future versions of ActivityPub may include mechanisms to verify attribution of activities more robustly with an attribution endpoint, delegation of attribution domains, or an author-controlled digital signature.