% [⠠⠵](/) A pile of Mastodung
% avuko
% 2024-03-29

::: {role="main"}

[pdf version](/data/truth_social.pdf)

So, TruthSocial. Valued at \... \$8bn. Yes,
[really](https://www.theguardian.com/us-news/2024/mar/26/trump-truth-social-public-new-york).
And what do people get for that? Well, allow me to show you. You can
safely click on the links in this article, everything pointing to
truthsocial\[.\]com is a snapshot on
[archive.org](https://web.archive.org).

## Open Sores

TruthSocial is running on Open Source. They shared the software they use
on their website. The
[Mastodon](https://web.archive.org/web/20240326213218/https://opensource.truthsocial.com/mastodon-current.zip)
file called `mastodon-current.zip` is from **2022-06-08**, and the
[Soapbox](https://web.archive.org/web/20240326213222/https://opensource.truthsocial.com/soapbox-current.zip)
called `soapbox-current.zip` is from **2022-05-13**. [Alex
Gleason](https://web.archive.org/web/20240329070023/https://truthsocial.com/@alex)
(then Head of Engineering) was keen on keeping things up to date. See
this [leftover
page](https://web.archive.org/web/20240329081912/https://truthsocial.com/instance/mobile/index.html)
for another great flashback tot 2022!

## Fire and Forget

First I had a look at the `soapbox-current.zip` file TruthSocial
provided. Soapbox comes with [documentation](https://soapbox.pub/) if
you want to read along. In the .zip is a file called
`instance/soapbox.json` with links to `/mobile` and `/beta`. It used to
be the
[same](https://web.archive.org/web/20220531155159/https://truthsocial.com/instance/soapbox.json)
online, but has since been
[removed](https://web.archive.org/web/20240326214340/https://truthsocial.com/instance/soapbox.json).
All still contain the line: \'*copyright: \"©2022 TRUTH Social\"*\'. We
will see that date turn up everywhere.

A funny aside, both the zipfile and the website contain a file called
[report.html](https://web.archive.org/web/20240329075824/https://truthsocial.com/report.html)
which is
[part](https://gitlab.com/soapbox-pub/soapbox/-/blob/main/vite.config.ts)
of soapbox. For an Open Source project it does make sense to have a map
of every file of code of Soapbox. But to me it feels somewhat misplaced
on a production website supposedly worth \$8bn.

I ended up with the feeling TruthSocial\'s first \"Head of Engineering\"
installed Mastodon, and nobody has done anything but cosmetic changes
(and add advertisements!) since. Did I already mention the \"Head of
Engineering\"
[left](https://www.reuters.com/technology/head-engineering-trumps-truth-social-app-resigns-2023-07-17/)?
I do wonder If they still have a Head of Engineering. Or even just the
digital equivalent of a janitor.

Anyway, let\'s go dumpster-diving the TruthSocial website.

## So transparent you can\'t see it

![](/data/transparency.gif){style="zoom:50%;"}

First up is the
[`api/v1/instance`](https://web.archive.org/web/20240325145631/https://truthsocial.com/api/v1/instance)
endpoint. I went through the .zip of mastodon they provided. The code
that creates that endpoint seems like a cobbled together
`app/serializers/rest/instance_serializer.rb`, with certain
[parts](https://github.com/mastodon/mastodon/pull/16485) from a Mastodon
version newer than or equal to 3.4.2.

The **exact** part which could provide transparency about the number of
users (`user_count`) and number of posts (`status_count`) has been
disappeared since [day
one](https://web.archive.org/web/20220517224052/https://truthsocial.com/api/v1/instance).
If I was an investor in ~~this dumpster-fire~~
[DJT](https://edition.cnn.com/2024/03/26/politics/djt-stock-trump-what-matters/index.html),
that\'s the two most important numbers I\'d want to have. Make of that
what you will.

``` {.ruby lang="ruby"}
def stats
    {
      user_count: instance_presenter.user_count,
      status_count: instance_presenter.status_count,
      [...]
    }
                
```

The
[original](https://web.archive.org/web/20220517224052/https://truthsocial.com/api/v1/instance)
configuration showed it had a limit of 500 characters per post (excuse
me: *truth*), and no support for advertisements yet. The source code
shared in the zip also has a maximum of 500 characters and no ads
support, so they\'ve made changes since we can\'t discover looking at
the .zip file.

## On a throne of rusty cruft

![](/data/rusty.png){style="zoom:50%;"}

Truth Social\'s Head of Engineering has a tendency to use old, old
software. His current flagship product Soapbox requires a
[component](https://soapbox.pub/install/) (Erlang 24) from \...
[2021](https://erlang.org/download/OTP-24.0.README). Luckily it is not
End-Of-Life, like some other parts of TruthSocial. But we\'ll get to
that later.

Anyway, Soapbox mentions a \"route\", `instance/beta` . The route is
there, but there is nothing behind it, resulting in an error which
[exposes](https://web.archive.org/web/20240325145858/https://truthsocial.com/instance/beta)
the nginx server/proxy used by TruthSocial: `nginx/1.21.6`. It
shouldn\'t come as a surprise this version is also pretty old
([2022-01-25](https://nginx.org/2022.html)), a number of versions
behind, and coincidentally from around the time TruthSocial was set up.

The `about.example` page mentioned on the Soapbox
[docs](https://docs.soapbox.pub/frontend/customization/) is still
[there](https://web.archive.org/web/20240325150212/https://truthsocial.com/instance/about.example/).
So is an [example
configuration](https://web.archive.org/web/20240329071549/https://truthsocial.com/instance/soapbox.example.json)
(copyright 2020!).

But this is just the supporting software. The core behind TruthSocial is
Mastodon. To find out what is running behind the Soapbox facade, I
fiddled a little with the TruthSocial website. Nothing even remotely
like hacking, just poking around and posting (*truthing*) some messages.

First thing I discovered is that if you call an API url with an invalid
path, TruthSocial will show an [error
page](https://web.archive.org/web/20240325145721/https://truthsocial.com/api/v1/instance/bla)
with a cute little Mastodon.

![](/data/error.png){style="zoom:50%;"}

Inside the html code of that error page is a reference to a stylesheet.

``` {.html lang="html"}
<link rel="stylesheet" media="all" crossorigin="anonymous" href="/packs/css/common-6632dedd.css" integrity="sha256-aGjPsjGbYVFerGzqX5W/jc1MlRhL7G4+yFgS3DYjvlQ=" />
                
```

My curiosity got the better of me, so I grabbed the
[list](https://instances.social/list/old) of all the old instances and
collected the `500.html` page of 17316 of them. 50 had the same css file
name, but not all were from the 3.4 branch. I have no idea what those
four (4) people did to their installs! Anyway, as the table below shows,
the `6632dedd` version of common-*blablabla*-.css is most common in the
3.4 branch of mastodon. What is hopefully also apparent is there luckily
aren\'t many 3.4\'s around anymore.

  3.4         Count
  ----------- -------
  3.4.0       4
  3.4.1       16
  3.4.3       1
  3.4.4       9
  3.4.6       10
  3.4.7       2
  **\>3.4**    
  3.5.19      2
  4.2.7       1
  4.2.8       1

What we currently know is that this css file is most common in (if not
the default of) the 3.4 branch. What we also know is that, unless the
people at TruthSocial bothered to manually change the code that shows
the version number after they shared the source code, the Mastodon
running on their website is indeed version 3.4.1. You can tell from
the`"version":"3.4.1 (compatible; TruthSocial 1.0.0)"`[part](https://web.archive.org/web/20240325145631/https://truthsocial.com/api/v1/instance),
which is created by the code in
`app/serializers/rest/instance_serializer.rb`:

``` {.ruby lang="ruby"}
def version
    "#{Mastodon::Version} (compatible; TruthSocial 1.0.0)"
  end
                    
```

## Go fetch to proof

![](/data/squirrel.gif){style="zoom:67%;"}

In normal installations of Mastodon version 3.4, when you create a post
with a link, there is code that \"fetches\" the page to create that card
view of the website. The official code that does this looks like this:

`mastodon-3.4.1/app/services/fetch_link_card_service.rb`

``` {.ruby lang="ruby"}
Request.new(:get, @url).add_headers('Accept' => 'text/html', 'User-Agent' => Mastodon::Version.user_agent + ' Bot').perform do |res|
                    
```

Which returns entries like this:

``` {.htaccess lang="htaccess"}
46.4.156.213 - - [25/Mar/2024:00:46:16 +0100] "GET /truth.htm HTTP/1.1" 200 51 "-" "http.rb/5.1.1 (Mastodon/4.3.0-alpha.3+glitch; +https://infosec.exchange/) Bot"
                    
```

But for TruthSocial, the `app/services/fetch_link_card_service.rb` looks
like this:

``` {.ruby lang="ruby"}
Request.new(:get, @url).add_headers('Accept' => 'text/html', 'User-Agent' => "#{Mastodon::Version.user_agent} Bot").perform do |res|
                    
```

Which creates log entries like this:

``` {.htaccess lang="htaccess"}
107.152.38.217 - - [24/Mar/2024:12:02:28 +0100] "GET / HTTP/1.1" 200 1379 "-" "http.rb/4.4.1 Bot"
107.152.35.98 - - [24/Mar/2024:12:15:27 +0100] "GET / HTTP/1.1" 200 1379 "-" "http.rb/4.4.1 Bot"
104.192.5.44 - - [24/Mar/2024:12:17:31 +0100] "GET /truth.htm HTTP/1.1" 200 51 "-" "http.rb/4.4.1 Bot"
107.152.38.167 - - [24/Mar/2024:12:39:42 +0100] "GET /truth2.htm HTTP/1.1" 200 51 "-" "http.rb/4.4.1 Bot"
107.152.35.73 - - [24/Mar/2024:12:47:20 +0100] "GET /thruth.htm HTTP/1.1" 404 125 "-" "http.rb/4.4.1 Bot"
                    
```

Notice that `http.rb/4.4.1`? It is ancient (2020-03-29) and has long
since been [replaced](https://rubygems.org/gems/http/versions/4.4.1).
The Mastodon 3.4 branch was the last to use http gem version 4.4:

``` {.bash lang="bash"}
mastodon-3.4.0/Gemfile:gem 'http', '~> 4.4'
mastodon-3.4.1/Gemfile:gem 'http', '~> 4.4'
mastodon-3.4.7/Gemfile:gem 'http', '~> 4.4'
mastodon-3.4.8/Gemfile:gem 'http', '~> 4.4'
mastodon-3.4.9/Gemfile:gem 'http', '~> 4.4'
mastodon-3.4.10/Gemfile:gem 'http', '~> 4.4'
mastodon-3.5.0/Gemfile:gem 'http', '~> 5.0'
                    
```

Not sure why they changed this to `#{Mastodon::Version.user_agent}`, as
this \"interpolation\" with the `#` sign is not in any of the other 3.4
versions and clearly breaks the User-Agent string. But maybe there are
no mistakes, only happy little accidents? The upside of breaking the
Mastodon version string in the User-Agent, consciously or not, is people
can\'t immediately see TruthSocial is running on zombie-software.

## Security

Below I\'m simply listing the security issues for the 3.4 branch.
Figuring out if security issues in more recent versions also existed in
the v4.3.1 is left as an exercise for the reader. I have **not**
verified or tested whether any of the security issues are patched,
because that is shady territory. Please note there are plenty of other
parties who are not held back by such considerations.

According to
[https://endoflife.date/mastodon](https://endoflife.date/mastodon){.url
target="_blank"}, support for the 3.4 branch, specifically for version
3.4.10(!), ended **2022-11-06**. So TruthSocial runs on software that
has been out of support or security fixes for--and I\'m working from a
best-case scenario here-- one year and a couple of months. Version
[3.4.1](https://github.com/mastodon/mastodon/releases/tag/v3.4.1) was
released 2021-06-03.

### v3.4.9 {#v349}

-   Fix emoji substitution not applying only to text nodes in backend
    code
    ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20641))
-   Fix emoji substitution not applying only to text nodes in Web UI
    ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20640))
-   Fix rate limiting for paths with formats
    ([Gargron](https://github.com/mastodon/mastodon/pull/20675))
-   Fix out-of-bound reads in blurhash transcoder
    ([delroth](https://github.com/mastodon/mastodon/pull/20388))

### v3.4.8 {#v348}

-   Fix concurrent unfollowing decrementing follower count more than
    once ([Gargron](https://github.com/mastodon/mastodon/pull/18527))
-   Fix being able to report otherwise inaccessible statuses
    ([Gargron](https://github.com/mastodon/mastodon/pull/18528))
-   Fix suspended users being able to access APIs that don\'t require a
    user ([Gargron](https://github.com/mastodon/mastodon/pull/18524))
-   Fix empty votes arbitrarily increasing voters count in polls
    ([Gargron](https://github.com/mastodon/mastodon/pull/18526))
-   Fix confirmation redirect to app without `Location` header
    ([Gargron](https://github.com/mastodon/mastodon/pull/18523))

### v3.4.7 {#v347}

-   Fix being able to post URLs longer than 4096 characters
    ([Gargron](https://github.com/mastodon/mastodon/pull/17908))
-   Fix being able to bypass e-mail restrictions
    ([Gargron](https://github.com/mastodon/mastodon/pull/17909))

### v3.4.6 {#v346}

-   Fix error-prone SQL queries
    ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/15828))
-   Fix not compacting incoming signed JSON-LD activities
    ([puckipedia](https://github.com/mastodon/mastodon/pull/17426),
    [ClearlyClaire](https://github.com/mastodon/mastodon/pull/17428))
    ([CVE-2022-24307](https://github.com/advisories/GHSA-x7fq-6476-543v))
-   Fix insufficient sanitization of report comments
    ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17430))
-   Fix stop condition of a Common Table Expression
    ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17427))
-   Disable legacy XSS filtering
    ([Wonderfall](https://github.com/mastodon/mastodon/pull/17289))

### v3.4.4 {#v344}

-   Fix filtering DMs from non-followed users
    ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17042))
-   Fix handling of recursive toots in WebUI
    ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17041))

### v3.4.2 {#v342}

-   Fix user notes not having a length limit
    ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16942))
-   Fix revoking a specific session not working
    ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/16943))

## Treasures from the dumpster-fire

Thank you for reading this far, and as a reward, here are two things I
found google-dorking.

[Tankie
Trump](https://web.archive.org/web/20240329130457/https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/media_attachments/files/108/722/289/324/906/174/original/047d433bc9b7b0eb.mp4)

[Ads Best Practices & Buyer
Roadmap](https://web.archive.org/web/20240329130330/https://static-assets-1.truthsocial.com/tmtg:prime-ts-assets/files/060723_Ads_BestPractices_BuyerRoadmap.pdf)
(CONFIDENTIAL, FOR INTERNAL USE ONLY, TMTG, ©2023)

I also found `ocr/lang-data/eng.traineddata.gz`, which is available
without authentication, If you\'d like to cause about 11MB of gratuitous
bandwith cost.

source: [mastodung.md](mastodung.md)
:::
