I mean, that’s just common sense, so why even mention it?
Because of ?p=, which I think most people who use WordPress aren’t aware of. This mechanism allows anyone to trivially download any media files you upload to WordPress, even without knowing the names of the files.
To backtrack a bit before going into the details of this problem (or “problem”): Yes, yes, you should never upload something secret to the Internet. And especially not to a place that’s publicly downloadable. But we all do it, right? When we want to send a big file to somebody (especially a (small) group of people), we just bang it on a web server somewhere and then send the URL to the people concerned. This is “safe-ish”, because nobody else knows the URL, right? And besides, we’re going to delete the file after a while anyway. Except when we forget.
Personally, I do this all the time with stuff — I mean, funny screenshots, jokes, pics — I bang them onto my WordPress and then share the URL in limited venues (irc, mail, whatever). Of course, nothing here is “secret” secret, but on the other hand, in these days when giving a milquetoast opinion like “I think killing children is bad” can get you landed on a terrorist list, you may prefer to be a bit more careful with this sort of thing.
So here’s the problem: Say I took a pic of my bookcase and put it on https://lars.ingebrigtsen.no/wp-content/uploads/2017/09/p1340399.jpg, and then mailed somebody the URL, and they were mildly impressed and then forgot about it. Nobody else will ever see it. But did you know that you can access (most) WordPress media items via URLs like https://lars.ingebrigtsen.no/?p=43041? No?
If a nefarious institution is interested in getting info on the general WordPress populace (*cough* Palantir *cough*), then can just loop through all those ?p= (on all WordPress sites in the world) starting from zero and going up to however many things that’s been put into the media library — unedited versions of images or videos, for instance.
Now, if somebody were to target you especially, there are, of course, other methods:
Because media file names have a tendency to be pretty regular, so you can just try a lot of https://lars.ingebrigtsen.no/wp-content/uploads/2025/07/DSC02869.jpg etc, and you’ll probably find something. But a targeted thing like this is impractical for most things — a general ?p= could be part of a general “sentiment” analysis that I bet sounds very attractive to some organisations.
But the ?p= thing is, of course, also super useful if you’re doing a targeted sploit — you can find (for instance) all PDFs an org has uploaded to their WordPress (along with all the cat pictures) without much work. The fun thing about ?p= is that you just loop through the numbers sequentially, and then you get everything, no matter what the media type is.
As far as I can tell, there’s no way to disable the ?p= thing without breaking other functionality:
After digging around in the WordPress source code, this seems to be the relevant code. Following the code afterwards, there doesn’t seem to be any way to mark a media item as “unavailable” — the closest you can get is to attach the item to an unpublished post, and then the ?p= will lead you to a 404 page instead of the image. If you have the direct URL to the item, you can always see it, as far as I can tell, but then we’re over in “find out the URL” land again, which isn’t as interesting.
So what I’ve done is to write a snippet for ewp to find all unattached files, and then include them all in a draft post, thereby making ?p= stop working for them. If this sounds really clumsy and awkward to you, then you’re totally right.
What I wish WordPress would do is to 1) make the ?p= an option — especially for unlinked media items — and 2) default it to “don’t do that” for all installations. And then the few people who want this surprising behaviour can switch it on.
This is more important now than ever, when there are vast resources that can ingest all this “hidden” data and process it in an efficient manner (using AI or not) — and especially since WordPress apparently powers a sizeable portion of the Internet.