PMs are accesible by admins if the admin has the link

I just found out that if someone sends a PM to other person. Let’s say from account joe to jane, and for some reason someone (logged in) finds out the right “topic ID” it can read the PM.

I know is kinda a edge-case and is rather difficult to find out, but automating some kind of scraper to cicle trough all the topics ID anyone could read all the PMs.

I found out because a user replied to the notification email, and I was able to click the link and read the PM in question.

I’m assuming you are a staff member on the forum? You should only be able to do this if you are staff. Staff should have the ability to audit PMs by default, and admins and those with access to the DB would have access to the raw messages anyway.

If you’re needing to provide a truly private system, there is the discourse-encrypt plugin which provides end-to-end encryption of messages.

9 Likes

It’s not a necessity, just didn’t got a thought in that one.

I’ll test with a normal account and update this, just in case.

1 Like

This is only true for admins, not moderators, so I am editing your title which is incorrect. Moderators also only have access to PMs when they are flagged.

If this is a concern, demote yourself to moderator (by logging in under a different account to taste), or enable logging of PM visits by admins in your site settings.

5 Likes

Potentially dumb question - where exactly is this setting? We’re on stable (which really should have this toggle, in theory) and I can’t find it for the life of me.

Edit: Our other admin found it - it’s “log personal messages views” in the “Users” tab. I’d argue that should be a Security tab thing, but can see why it would be there instead if I think about it for a minute.

2 Likes

Follow-up question - is it possible to enable logging when an admin has viewed the messages an account has, even if they didn’t open a message to read its contents?

In the context of our forum, it would be possible for admins to abuse their power by merely seeing the details of certain PMs a user may be a part of - reading the contents is not necessarily more damaging than knowing the name and which users have access, which is currently not logged despite having that setting enabled. Ideally, we’d like to fix this, and also log whenever an admin views the messages a user is a part of rather than just when they view a specific message’s contents.

1 Like

The best way to do this is with end-to-end encryption, made possible by our discourse-encrypt plugin.

Admins are administrators of the forum and have access to all of the data. There’s lots of ways for admins to view message contents without it being logged:

  • downloading a backup
  • data explorer
  • impersonation
  • creating API keys

To fully protect users the best solution is to use encrypted messaging. If you don’t trust your admins, they shouldn’t be admins.

5 Likes

My understanding is that most of those things are log-able, which is all we really need - to be honest, I’m not sure I trust myself not to end up looking at a user’s messages page on accident and then just move on as if nothing happened, which in our case could be harmful (in particular, we don’t expect it to be a security risk, but an integrity risk - ie, longterm damage isn’t done as long as the user who has gained access to this knowledge is open about it and recuses themselves from relevant topics).

It would certainly make it much easier to ensure nobody does this on accident or on purpose without then reporting it if it were logged with all the other ways they could access the same data.

If those things you listed aren’t log-able then they really should be, but even so it would only help against a malicious admin and not a slightly careless one

1 Like

You can hide/obscure message titles in other users’ message lists using your site theme.

If it’s on purpose, that’s a different matter.

Other places you could get this audit information: the web server logs.

I’m sure a plugin to log this information wouldn’t be difficult, but I’m not sure if it should be on our internal roadmap.

2 Likes

How would it be possible to do this without also obscuring your own message lists? As far as I’m aware, there isn’t a slug with the username of the account you’re viewing you could use to affect only message pages that aren’t your own with CSS.

1 Like

You might be able to use a selector on the title on that page - “Messages” is yours vs. “Username — Messages” is someone else’s.

2 Likes

My main issue is my script seems to pull the data before it’s updated - ie, I can read the metadata on a page change, but it updates before the page data is updated.

<script type="text/discourse-plugin" version="0.8">
    api.onPageChange(() =>{
        window.onload = determineUser();
    });
    
    function determineUser() {
        var pageURL = document.querySelector("meta[property='og:url']").getAttribute("content");
        var userPage = pageURL.includes("https://www.fortressoflies.com/u/");
        document.documentElement.style.setProperty('--currUsername', pageURL);
        
        if(userPage)
        {
            document.documentElement.style.setProperty('--lastUsername', pageURL);
        }
    }
</script>

Basically, my --currUsername is updated, then the meta tag is updated with the new url, so my --currUsername is always a page behind what I’m actually looking at. This occurs regardless of whether or not I have the “window.onload” line.

Any idea what I’m goofing up here?

The end goal is pretty much to just add a class to the body based on what page you’re looking at, and then style based on that - should allow us to read, for example, that title field instead of the og:url field, and then slap a “myMessages” class on the body to get the desired effect in this instance. In theory.

1 Like

This is incredibly jank, but the following appears to work by forcing the JavaScript function to hold off for a twentieth of a second:

<script type="text/discourse-plugin" version="0.8">
    api.onPageChange(() =>{
        window.onload = determineUser();
    });
    
    async function determineUser() {
        await sleep(50);
        var pageURL = document.querySelector("meta[property='og:url']").getAttribute("content");
        var userPage = pageURL.includes("https://www.fortressoflies.com/u/");
        document.documentElement.style.setProperty('--currUsername', pageURL);
        if(userPage)
        {
            document.documentElement.style.setProperty('--lastUsername', pageURL);
        }
    }
    
    function sleep(ms)
    {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
</script>

Will see if I can make this work as intended.

2 Likes