Commit graph

6,058 commits

Author SHA1 Message Date
Oneric
7869030e08 api/statuses/context: fix local-only contexts
All checks were successful
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline was successful
The context query is separate from the main timeline query
but was omitted to be adjusted when local-only posts were introduced.
Thus only local-only posts directly addressing the API user were considered.
2026-04-07 00:00:00 +00:00
Oneric
a088a0136b api/statuses/context: return 404 when not existing
Or is not visible to the current user.
Previously led to 500 Internal Server Error if post didn’t exist
and empty response if post existed but was not accessible.
2026-04-07 00:00:00 +00:00
Oneric
e4066ca98e Remove remnants of list addressing
The feature was removed in 271110c1a5
2026-04-07 00:00:00 +00:00
Oneric
370d422a1d db: drop activity_visibility and related indexes
The last user of this acursed mess was dropped in the preceding commit.
The COALESCE_follower_addres index existed solely for activity_visibility.

Now nothing is blocking parallel restore of db dumps anymore
allowing significantly faste restores and removing the pitfall
of (when not following our old documented flgs) greatly _worsening_
restore times by enabling parallel mode.
2026-04-07 00:00:00 +00:00
Oneric
9e105a64a9 api: drop direct timeline
As announced in the 3.18 (2025.12) release

Closes: #798
2026-04-07 00:00:00 +00:00
Oneric
f81bf5214b api: remove deprecated thread containment feature
While disabled by default since almost immediately after its
introduction and entirely undocument and seemingly unsued anyway,
it was deprecated in 9d19dbab99 with
a loud warning to any potential users (see this commit for motivation).

Nobody contacted us so now it is time to follow up with a proper removal
2026-04-07 00:00:00 +00:00
Oneric
17841dca53 api: finalise removal of exclude_visibilites
It was tenatively removed in 0aeeaeb973
for release 3.18 (2025.12) with the intent to follow up with a proper
clean if no objections were raised.
Nobody complained, so lets now get rid off its vestiges.
2026-04-04 00:00:00 +00:00
Oneric
6ed20f1ca3 fed/out: indicate our own polls are always anonymous
All checks were successful
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline was successful
With regard to regular user and admin interaction via API.
Ofc, the server operator can still extract identites from the database.
2026-04-04 00:00:00 +00:00
Oneric
11982eb249 {api,fed/in}: expose remotes claims wrt poll vote anonymitiy
Most of the major micro-blogging AP implementations do not make
votes or voter identity available to anyone by regular means.
However, this is but an informally adopted common practice.

Smithereen may (depending on the decision of the creating user)
disclose who voted and what everyone voted for. This information
is made publically available to everyone, including via ActivityPub
(eventhough the AP vote collections show some type and data
 inconsistencies between the inline and standalone version at the
 time of writing. It is necessary to fetch the standalone collections
 for the full information.)

Smithereen does indicate whether a poll will disclose votes and voter
identies and when this is kept secret. But of course, for this info
to be visible to our users we will need to first pick up the hint
from Smithereen and forward it in our Masto API responses.

Example: https://friends.grishka.me/posts/1116518
2026-04-04 00:00:00 +00:00
dc3673fffa api/account: add profile media alt text
All checks were successful
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline was successful
Projects like e.g. Iceshrimp.NET and Pleroma already allow
setting and federate alt text for profile media.
Mastodon too recently added support for avatar and header descriptions
in https://github.com/mastodon/mastodon/pull/37634
and https://github.com/mastodon/mastodon/pull/38221.

We use Mastodon-compatible API parameters for avatar and headers and
extend the naming scheme for background images not found in Mastodon.
There’s one difference however: we do not actually store media alt text
when no matching media was yet set at all. Since media is stored as an
inline, AP-like JSON object, it can only exist if there’s an image.

Co-authored-by: Oneric <oneric@oneric.stub>
2026-04-04 00:00:00 +00:00
80fc784432 Merge pull request 'Add sane defaults for database_config_whitelist, add a task to remove non-whitelisted configs' (#1077) from mkljczk/akkoma:akkoma-database-config-whitelist into develop
Some checks failed
ci/woodpecker/push/publish/2 Pipeline is pending
ci/woodpecker/push/docs Pipeline was successful
ci/woodpecker/push/publish/4 Pipeline failed
ci/woodpecker/push/publish/1 Pipeline failed
Reviewed-on: #1077
Reviewed-by: floatingghost <hannah@coffee-and-dreams.uk>
2026-04-01 10:38:29 +00:00
Oneric
0b061090ac ap/transmogrifier: fix attachment MIME extraction
All checks were successful
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline was successful
ci/woodpecker/push/docs Pipeline was successful
ci/woodpecker/push/publish/4 Pipeline was successful
ci/woodpecker/push/publish/1 Pipeline was successful
ci/woodpecker/push/publish/2 Pipeline was successful
If an attachment with a full Link object as an "url" (i.e. a map)
but no "mediaType" attribute in the Link made it to this point
processing crashed since MIME.extensions/1 requires binary input.

Additionally the is_bitstring/1 checks in the other branches were too
lax; bitstrings may contain any number of bits not just full bytes.
2026-03-30 00:00:00 +00:00
48eaf69a06 web: mark local uploader and proxied responses as immutable
All checks were successful
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline was successful
While modern browsers already limit revalidation requests a lot,
marking it as immutable enusres there’ll never be a need for
revalidation until the max-age (currently two weeks) elapses.

Uploaded media is indeed guaranteed to be immutable with
the hash of the file content being part of the path.
Proxied responses are technically not immutable, but we’d
like to not reproxy it if we can avoid doing so. Reverse
proxy (e.g. nginx) side caching already helps here and
may overwrite this flag if desired.
2026-03-28 00:00:00 +00:00
Oneric
570de73062 fed/in: reject inbox POST with 405 if not federating
All checks were successful
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline was successful
ci/woodpecker/push/docs Pipeline was successful
ci/woodpecker/push/publish/4 Pipeline was successful
ci/woodpecker/push/publish/1 Pipeline was successful
ci/woodpecker/push/publish/2 Pipeline was successful
As advised by ActivityPub spec.
2026-03-28 00:00:00 +00:00
Oneric
455ea15817 fed/out: recognise if inbox does not support federation 2026-03-28 00:00:00 +00:00
Oneric
e761960fcc api/masto/list: include reblogs in timelines
All checks were successful
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline was successful
This matches Mastodon’s behaviour.

The test for the absence of reblogs was originally added without
explanation in cfc99fe05c.
2026-03-28 00:00:00 +00:00
f268e63b60 api/masto/list: support exclusive param
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2026-03-28 00:00:00 +00:00
Clara Engler
792b1b8a09 user/fetcher: fix fallback return schema for eval_counter_collection
All checks were successful
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline was successful
Fixes omission in d2fda68afd;
the fallback function clause was not updated to include
whether or not counters are considered private, leading
to match exceptions for users without a follower or following address.

Likely fixes #1080
2026-03-24 00:00:00 +00:00
9ee4283c46 web/embed: fix content-type for /embed
All checks were successful
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline was successful
Currently the response uses a generic application/octet-stream type
causing browsers to just offer a download rather than actually embedding
it. Additionally this no longer usees the embedding template, but the
same app template like static-fe breaking styling.
Presumably the latter broke when the layout assignment got lost in
c63ae73bc0. Thus restore it and since
even then it is not set automatically (anymore?), explicitly set
response contnet-type to HTML.

Add unit test for correct text/html content-type so this won’t repeat.
2026-03-23 00:00:00 +00:00
Oneric
720785b4cc api/masto/marker: fix datetime format for updated_at
Some checks failed
ci/woodpecker/push/docs Pipeline is pending
ci/woodpecker/push/publish/1 Pipeline is pending
ci/woodpecker/push/publish/2 Pipeline is pending
ci/woodpecker/push/publish/4 Pipeline is pending
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline failed
Ref: https://docs.joinmastodon.org/api/datetime-format/

Fixes: #1087
2026-03-23 00:00:00 +00:00
Oneric
a062ac5ceb webfinger/finger: actually limit refetch
Fixes mistake in eb361dd456
2026-03-21 00:00:00 +00:00
Oneric
eb361dd456 webfinger/finger: only accept authority of query domain
And permit refetching once(!) unless initial query
was already designated as the canonical authority.
(Only once to not get stuck in loops)

Fixes an oversight in c80aec05de.
The argument for why subjects from both authorities can be accepted
hinged on the assumption that only paths under direct control of the
domain operator are involved since both webfinger and host-meta
are /.well-known/ paths.
However, HTTP redirects or the LRDD schema inside the initial domains
host-meta may point at _any_ path on another domain, including e.g.
paths containing user uploads, thus enabling third-parties to
illegitimately claim handles from urelated domains, _if_ the victim
domain can be made to serve attacker-prepared JSON (e.g. via user
uploads or (media) proxies).

With trust being limited to initial domain and refetches we do not need
to make guesses about whether and when being redirected to indicates
authorisation of the final domain. It requires more fetch requests in
no-FEP-2c59 setups, but makes it more robust.
As a side effect current FEP-less Mastodon setups should happen to work.
2026-03-21 00:00:00 +00:00
Oneric
9baf4d16e5 test: properly mock url in more Tesla responses 2026-03-21 00:00:00 +00:00
Oneric
9d1e169472 webfinger/finger: allow WebFinger endpoint delegation with FEP-2c59
The ban on redirects was based on a misreading of FEP-2c59’s
requirements. It is only meant to forbid addresses other than
the canonical ActivityPub ID being advertised as such in the
returned WebFinger data.
This does not meaningfully lessen security and verification still
remains stricter than without FEP-2c59.

Notably this allows Mastodon with its backwards WebFinger redirect
(redirecting from the canonical WebFinger domain to the AP domain)
to adopt FEP-2c59 without causing issues or extra effort to existing
deplyoments which already adopted the Mastodon-recommended setup.
2026-03-13 00:00:00 +00:00
Oneric
e8d6d054d0 test/webfinger/finger: fix tests
One asserted the response format of finger_actor on a finger_mention
call as a previous iteration of the implementation mistakenly returned.
The other didn’t actually test anything WebFinger but fundamental id
containment and verification for generic AP fetches. Now it does.
2026-03-12 00:00:00 +00:00
Oneric
ab2210f02d test/webfinger/finger: add more validation tests 2026-03-12 00:00:00 +00:00
Oneric
5256785b9a test/webfinger/finger: mock url in all new tests
It is used in security checks and only due to an abudance of
existing tests lacking it, _only_ the test env is allowed to
fallback to the query URL for theses tests as a temporary
(well, ... it’s been a while now) measure.
We really shouldn’t be adding more deficient tests like that.
2026-03-12 00:00:00 +00:00
Oneric
4460c9c26d test/webfinger/finger: improve new test names and comments 2026-03-12 00:00:00 +00:00
f87a2f52e1 add extra happy and unhappy path tests for webfingers 2026-03-12 00:00:00 +00:00
627ac3645a add some more webfinger tests 2026-03-12 00:00:00 +00:00
2020a2395a add baseline webfinger FEP-2c59 tests 2026-03-12 00:00:00 +00:00
Oneric
fd734c5a7b webfinger/finger: normalise mention resources to more common format 2026-03-12 00:00:00 +00:00
Oneric
838d0b0a74 ap/views: use consistent structure for root collections
Notably user follow* collections faked a zero totalItem count
rather than simply omitting the field and included a link to a first
page even when knowing this page cannot be fetched while most others
omitted it. Omitting it will spare us receiving requests doomed to
failure for this page and matches the format used by GtS and Mastodon.

Such requests occur e.g. when other *oma servers try to determine
whether follow* relationships should be publicly shown. Other
implementations like Mastodon¹ simply treat the presence of a (link to)
a first page aready as an indicator for a public collection. By
omitting the link Mastodon servers will now too honour our users
request to hide follow* details.

The "featured" user collection are typically quite small and thus
the sole occurence of the alternative form where all items are directly
inlined into the root without an intermediate page. Thus it is not
converted but also no helper for this format created.

1: eb848d082a/app/services/activitypub/process_account_service.rb (L303)
2026-03-12 00:00:00 +00:00
Oneric
ddcc1626f8 ap/user_view: optimise total count of follow* collections
The count is precomputed as a user property.
Masto API already relies on this cached value.
This let’s us skip actually querying  follow* details unless
follow(ing/ed) users are publicly exposed and thus will be served.

In fact this could now be optimised further by using keyset pagination
to only fetch what’s actually needed for the current page. This would
also completely obsolete the need for the _offset collection page
helpers. However, for this pagination to be efficient it needs to happen
o the follow relation table, not users. This is left to a future commit.

Due to an ambiguity with PhoenixHtmlHelpers the Ecto.Query
select import was unusable without extra qualification,
therfore it is converted to a require expression.
2026-03-12 00:00:00 +00:00
Oneric
a899663ddc Fix malformed is_active qualifiers in User.Query usages
While "is_active" is a property of users, it is not a recognised keyword
for the User.Query helper; instead "deactivated" with negated value must
be used.
This arose because originally the user property was also called
"deactivated" until it was renamed adn negated five years ago
in 860b5c7804. This included renaiming
the parameter in most but not all User.Query usages.
Notably the parameter in User.get_followers_query was renamed
but not in User.get_friends_query (friends == following).
The accepted query parameter in User.Query however was not changed.
This lead to the former mistakenly including deleted users causing
too large values to be reported in the ActivityPub follower, but not
following collection as reported in #1078.

In Masto API responses filtering by `User.is_visible` weeded out
the extra accounts before they got displayed to API users.

On the surface it might seem logical to align the name of the User.Query
parameter with the actual property name. However, User.Query already
accepts an "active" parameter which is an alias for limiting to accounts
which are neither deleted nor deactivated by moderators (both indicated
by is_active) and also are not newly created account requests still
pending an admin approval (is_approved) or necessary email confirmation
(is_confirmed); in short as the alias suggests whether the account is
active. Two highly similar parameter names like this would be much too
confusing.

The renamed "is_active" on the other hand does not actually suffice to
say whether an account is actually active, only whether it has (not yet)
ceased to be active (by its own volition or moderator action).
Meaning its "new" name is actively misleading. Arguably the rename
made things worse for no reason whatsoever and should not ever have
happened.

For now, we’ll just revert the incorrect query helper parameter renames.

Fixes: https://akkoma.dev/AkkomaGang/akkoma/ issues/ 1078
2026-03-12 00:00:00 +00:00
Oneric
d2fda68afd user/fetch: properly flag remote, hidden follow* counts
Instead of treating them like a public zero count.
2026-03-12 00:00:00 +00:00
Oneric
4bae78d419 user/fetcher: assume collection to be private on fetch errors
With the follow info update now actually running after being fixed
a bunch of errors about :not_found and :forbidden collection fetches
started to be logged
2026-03-12 00:00:00 +00:00
Oneric
f3821628e3 test: fix module name of GettextCompanion tests
Oversight in 54fd8379ad
2026-03-12 00:00:00 +00:00
Oneric
2a1b6e2873 user/fetcher: drop nonsense type-based follow update skip
The real intent behind the commit introducing this seemed to have been
avoiding running this when the actor does not expose follow collection ids
ec24c70db8.
This is already taken care of with the :collections_available check.
Some Implementations use other actor type like Group etc for visible,
followable actors making skipping undesirable.

Notably though, this actually has _always_ skipped counter updates
as even when this check was introduced, the user changeset data and
struct used the :actor_type key not :type.

In some situations fetch_follow_information_for_user is called directly
from other modules thus occasionally counters still got updated
for accounts with closer federation relationships masking the issue.
2026-03-12 00:00:00 +00:00
Oneric
c80aec05de webfinger: rewrite finger query and validation from and to actors
Resolves all security issues discussed in 5a120417fd86bbd8d1dd1ab720b24ba02c879f09
and thus reactivates skipped tests.
Since the necessary logic significantly differs for WebFinger handle dicovery/validation
and fetching of actors from just the webfinger handle the relevant public function was split
necessitating also a partial rewrite of the user fetch logic.

This works with all of the following:
  - ActivityPub domain is identical to WebFinger handle domain
  - AP domain set up host-meta LRDD link to WebFinger domain
  - AP domain set up a HTTP redirect on /.well-known/webfinger
    to the WebFinger domain
  - Mastodon style: WebFinger domain set up a HTTP redirect
    on its well-known path to AP backend (only for discovery
    from nickname though until Mastodon supports FEP-2c59)

This intentionally does not work for setups where FEP-2c59 is not
supported and the initially queried domain simply directly responds with
data containing a nickname from another domain’s authority without any
redirecty. (This includes the setup currently recommended by Mastodon,
when enriching an AP actor. Once Mastodon supports FEP-2c59 though its
setup will start to work again too automatically).
While technically possible to cross-verify the data with the nickname
domain, the existing validation logic is already complex enough and
such cross-validation needs extra safety measures to not get trapped
into infinite loops. Such setups are considered broken.
2026-03-12 00:00:00 +00:00
Oneric
69622b3321 Drop obsolete kludge for a specific, dead instance
It doesn’t make sense in general (many implementations use ids not nicks in ap_id)
and just wastes time by making additional, unnecessary, failing network requests.
This arguably should have never been committed.
2026-03-12 00:00:00 +00:00
Oneric
1e6332039f user/fetcher: also validate user data from Update
And fixup sloppy test data
2026-03-12 00:00:00 +00:00
Oneric
eb15e04d24 Split user fetching out of general ActivityPub module
The ActivityPub module is already overloaded and way too large.
Logic for fetching users and user information is isolated from
all other parts of the ActivityPub module, so let’s split it out.
2026-03-12 00:00:00 +00:00
Oneric
25461b75f7 webfinger: split remote queries and local data generation
They do not share any logic and the lack of separation makese it easy
to end up in the wrong section with ensuing confusion.
2026-03-12 00:00:00 +00:00
Oneric
4a35cbd23d fed/out: expose webfinger property in local actors (FEP-2c59)
It makes discovery and validation of the desired webfinger address
much easier. Future commits will actually use it for validation
and nick change discovery.
2026-03-12 00:00:00 +00:00
Oneric
1cdc247c63 Temporarily disable customised webfinger hosts
Proper validation of nicknames must consider both the domain
the nickname is associated with _and_ the actor to be assigned this
nickname consent to this.
Prior attempts at securing this wer emade in
a953b1d927 and
0d66237205 but they do not suffice.

The existing code attempted to validate webfinger responses independent
of the actual ActivityPub actor data and only ever consider the former
(yet failed to properly validate even this).

When resolving a user via a user-provided nickname the assignment
done by the provided URL was simply trusted regardless of the actors
AP host or data. When the nresolving the AP id, the nickname from this
original WebFinger query was passed along as pre-trusted data overriding
any discovery or validation from the actual actors side.
This allowed malicious actors to serve rogue WebFinger data associating
arbitrary actors with any nicknames they wished. Prompting servers to
resolve this rogue nickname then creates this nonconsensual assignment.

Notably, the existing code’s attempt at verification (only for domain
consent) used the originally requested URL for comparison against the
domain in the nickname handle. This effectively disabled custom
WebFinger domains for honest servers unless using an host-meta LRDD link.
(While LRDD links were recommend in the past by both *oma nad Mastodon,
 today most implementations other than *oma instead
 recommend setups emplyoing HTTP redirects.)
Still, this strictness did not prevent spoofing by malicious server.
It did however mean that rogue nickname assignments from an initial
nickname-based discovery were at least undone on the next user refresh
provided :pleroma, Pleroma.Web.WebFinger, :update_nickname_on_user_fetch
was not changed from its default truthy value.
(A renewed fetch via the rogue nickname would re-establish it though)

When enriching an already resolved ActivityPub actor to discover its
nickname the WebFinger query was not done with the unique AP id as a
resource, but a guessed nickname handle.
Furthermore, the received WebFinger response was not validated
to ensure the ActivityPub ID the WebFinger server pointed to
for the final nickname matched the actual ID in the considered
AP actor data.
While the faulty request URI check described above provides some
friction for malicious actors, it is still possible for mischiveous
AP instances to setup a rogue LRDD link poitning to a third-party
domain’s WebFInger and using the freedom provided by the LRDD link
to overwrite the resource value we provide in the lookup. Thus usurping
existing nicknames in another domains authority.

Proposed tweaks to the existing, faulty checks to work with
HTTP-redirect-based custom WebFInger domains would have made it
even easier to usurp nicknames from foreign domains.

For now simply disable custom WebFinger domains as a quick hotfix.
Subsequent commits will partially de-spaghettify the relevant code
and completely overhaul webfinger and nickname handling and validation.
2026-03-12 00:00:00 +00:00
Oneric
4c63243692 emoji/pack: fix in-place changes
All checks were successful
ci/woodpecker/pr/test/2 Pipeline was successful
ci/woodpecker/pr/test/1 Pipeline was successful
ci/woodpecker/push/docs Pipeline was successful
ci/woodpecker/push/publish/4 Pipeline was successful
ci/woodpecker/push/publish/1 Pipeline was successful
ci/woodpecker/push/publish/2 Pipeline was successful
Deleting a whole pack at once didn’t remove its emoji from memory
and ewly updated or added emoji used a wrong path. While the pack
also contains a path, this is the filesystem path while in-memory
Emoji need the URL path constructed from a constant prefix,
pack name and just the filename component of the filesystem file.
Test used to not check for this at all.

Fixes oversight in 318ee6ee17
2026-03-12 00:00:00 +00:00
1721746ece Update test and config for Akkoma
Some checks are pending
ci/woodpecker/pr/test/1 Pipeline is pending approval
ci/woodpecker/pr/test/2 Pipeline is pending approval
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2026-03-03 00:15:59 +01:00
Lain Soykaf
dc4f02f6f7 ConfigController: Don't allow updating the whitelist
Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
2026-03-02 23:50:25 +01:00
Lain Soykaf
ac91a42f3e ConfigTest: Don't crash when whitelist is unset / disabled 2026-03-02 23:48:43 +01:00