RFC: Trust in multi-user TiddlyWikis

In my view what separates TiddlyWiki from other wikis (and makes it fun) is that everything is a tiddler, even widgets, macros and javascript tiddlers. There is no separation between content and code.

There’s been several threads on using TiddlyWiki in a multiuser context, but I haven’t seen a discussion of how we can keep TiddlyWiki extensible and powerful without becoming a security nightmare.

Potential for attacks

Naively allowing anyone to add tiddlers to a wiki could result in malicious code automatically doing the following without the victim’s consent:

  • impersonating other users towards third parties (eg: using their auth cookies in requests)
  • defacing the UI
  • accessing private information
  • deleting or updating users’ tiddlers (potentially with self-replicating code)

TiddlyWiki’s focus on “hackability” means it’s often enough to tag a tiddler with a $:/-prefixed tag for the code within to be triggered by a UI button or run automatically on wiki load. This is a good thing as long as we can figure out a way to keep it secure.

Single- and multiuser scenarios

In a single-user scenario, a single individual is both the author and the viewer of tiddlers. The trust model is simple: the author must trust the code in the official tiddlywiki release + any plugins they may be using (we can call this vendor code). Any additional logic is his own (author code).

Multi-user can refer to several scenarios:

  • multiple devices, single user. This is the same as the single device single user case from a trust perspective: vendor + author code.
  • multiple users, each read only. Since users cannot persist their modifications to the wiki, other users are still running only vendor code without augmentation from wiki users.
  • multiple isolated users. Each user can create new / shadow existing tiddler which are saved to a database, but other users don’t see these changes. To each user it’s like they have their own wiki, the union of vendor tiddlers coming from the wiki HTML and author tiddlers loaded from the database. There’s no way for users to collaborate, but also no attack surface (only vendor + author code).
  • multiple users with shared tiddlers. This is what most people generally think of when they say “multi user TiddlyWiki”. In addition to vendor and author code, users will also be running other wiki users’ code (other user code), potentially less trustworthy than the first two, but enjoying the same privileges. Tiddlers containing other user code would live in a database just like author code.

Trust with shared tiddlers

A possible compromise between hackability and security could be running other user code with limited privileges, while vendor and author code could continue to run at full privileges (exactly as in single user scenarios). We could prevent each type of attack listed above by placing restrictions on tiddlers shared by several users:

  • Impersonating other users towards third parties: by using sandboxed iframes to display tiddlers containing other user code the Origin would be null, so CORS won’t allow cookies to be sent with outgoing requests.
  • defacing the UI: no $:/-prefixed tags and restrictions on type and module-type fields for shared tiddlers.
  • accessing private information and deleting or updating users’ tiddlers: the “other user code sandbox” iframe has limited access to the wiki:

Other user code wiki permissions

Other user code should be able to:

  • persist some state for the current user only (a good example is a “dark mode” toggle).
  • persist some state for the entire wiki (a good example is a moving a card to a different lane in a kanban).

It should not be able to:

  • read fields of tiddlers it was not authorized to access.
  • alter/shadow/create new tiddlers which enjoy vendor or author trust status (this would allow it to escape the sandbox).
  • alter tiddlers containing other user code (this would allow self replication for example).

Perhaps a too restrictive, but one possible answer could be allowing other user code to:

  • read any tiddler (with the possible exception of tiddlers explicitly marked as private somehow).
  • write/delete only tiddlers application/json type tiddlers which are also shared.

As vendor code could still be run with full access to TiddlyWiki, tiddlers containing other user code which need greater privileges could be moved into the wiki HTML.

What would be your suggestions? What would be a sane policy to determine which tiddlers can be read / written by other user code? Since you participated in previous multi-user discussions, I would be particularly curious to hear your thoughts, @jeremyruston, @linonetwo, @Springer, @TW_Tones, @joshuafontany, @Charlie_Veniot, @TiddlyTweeter.

Identifying shared tiddlers

A new title prefix, such as €:/ could be used to denote the fact that a tiddler is shared among all wiki users (and thus requires restrictions in permitted tags and rendering mechanism).

2 Likes

Thanks for taking this subject seriously, and staring a sophisticated discussion.

I have a lot of experience but I am not a core developer.

The first point to kick the discussion along, I will makes is,

  • if you want to install a Javascript program or plugin containing one it needs to be saved and loaded before it can operate. When this is saved, if it can be saved to the server, then others can load this new code, if not it can not, or will not be active.
  • In some ways all tiddlers are shared to start with. I would think if we were to use another “name space” such as €:/ it would more likely be used to denote private tiddlers. Arguably private tiddlers could have the restrictions meaning it can not be pushed into the server.
  • I think the main question is what operates at a server level and what operates at the user level in the browser or user storage.

Note;
If you were not aware “tiddlywiki bob plugin” and “bob.exe” implements multi-access, multi-user and multi-wiki tiddlywikis. If you install plugins in the wiki they operate in the wiki, and load into the browser/user space, if you want to install them into the server you need access to the server file system. I understand there is no easy or absolutely secure way to easily get such a node driven wiki onto the internet. I suspect that this is the “lowest hanging fruit” we need to address to meet most of the security issues you raise.

Neumark,

It seems clear to me that the first baby-step is to engineer a solution for multiple trusted users.

For example, if my teaching assistant or research assistant could have password-protected co-author privileges at tiddlyhost or some other online interface, it would be tremendously helpful. I’m not worried about malicious hacking (by such people) at all. I just want a way to have our edits signed differently, and to have our changes co-exist in peace. It would also be nice to make certain system setting changes local-only (specific to one user, or to one browser location or session).

Even the risk of simultaneous conflicting edits to a particular tiddler is not an immediate deal-breaker. (It’s not terribly likely, and single tiddlers (ideally) don’t hold too much work. A single-tiddler-download backup process could help reconstruct in the case of such a hiccup). Eventually, some variation on the “Draft of” mechanism might helpfully play a role in flagging conflicting edits. I think Tones talked about a “check-out” process at some point, which would be super.

What’s vital: Avoid the risk that Author A saves (maybe having failed to refresh for a while), and overwrites ALL the work Author B has been laboring over. (Since I’m collaborating remotely, we don’t easily have the granularity of node.js tiddler-handling. Collaborators on an intranet with node.js would probably have an easier time in this respect, yes?)

Note, a fix for this risk would probably also reduce the fear some of us already live with: accidentally overwriting work done at home when we unwittingly make a change to a stale version left in an open browser tab at work (etc.).

It seems to me that we should START with making TW friendly to multiple trusted users, and troubleshoot the logistical challenges that emerge, which are not trivial.

Only after succeeding at this task should we peek into the Pandora’s box of wider access. The dangers of allowing a wiki to be modified by people we don’t necessarily trust, given that the guts of a TiddlyWiki are conveniently open to tinkering, are indeed serious.

-Springer

1 Like

Hi @TW_Tones, thanks for your response!

I agree, all tiddlers are generally shared among wiki users. To use the standard nodejs server as reference (I believe bob’s architecture is similar), there are three sources of tiddlers, with different levels of trust:

vendor code

Tiddlers which are included in TiddlyWiki and plugins referenced by tiddlywiki.info: these tiddlers are loaded when TiddlyWiki is loaded in the browser and starts running. The code within has full access to TiddlyWiki and the browser APIs. The files which contain these tiddlers are in the node_modules directory, editing these tiddlers will not update them. These tiddlers are available to all users.

author code

Tiddlers which are created by the user and saved by the nodejs server are stored under the tiddlers subdirectory. Tiddlers which override shadow tiddlers are also saved here. Javascript within these tiddlers is considered “author code” as long as other users can’t access these tiddlers. The standard nodejs server doesn’t have a concept of users, but bob and the -somewhat depracated- tw5-firebase do. With these backends it’s possible for a tiddler to be saved to the tiddlers folder or equivalent database so that only the author can access it later. These tiddlers can overwrite “vendor code” shadow tiddlers. Since they only affect the author’s experience, they can be trusted just as much as vendor code.

other users code

Tiddlers can be shared by multiple users and contain code (JS tiddlers, wikitext with fancy widgets or macros, sneaky SVGs with javascript inside, etc). These tiddlers are available to all users, may be returned by filter expressions meant to be extension points (eg: all buttons visible in the edit toolbar or sidebar, or modules to run on startup). Since all users have access and can make changes, any user can add code to these tiddlers which will potentially be run by all other users.
Sandboxing and restricting acceptable type and tag field values for these tiddlers may help, but to do that, we must be able to tell which tiddlers are editable any any user and contain code.

I used TiddlyDesktop with a wiki folder and synchronised via Syncthing for a while (also synced using git). What’s missing from such a solution that you need?

Bob has a lot of what is being discussed here. It can support multiple devices with single or multiple users and multiple wikis, individually or shared.

I am working on a secure server setup for it, I had a demo up a while ago that had multiple users. It can support multiple authentication levels and has access controls that can be per-user or by group. The access controls can also control what actions people can take in the wikis and what tiddlers are editable (in the sense of what gets saved to the server) or if they can create new tiddlers and similar fine-grained controls. It also has the option to filter specific tiddlers, so there could be one wiki and user-specific tiddlers that only individual users or people with authorization could see.

I haven’t touched the secure server part in a while because of my day job, but I am still planning on making it more usable.

Hi Jed!

Bob is really cool, looking forward to seeing your planned secure server changes. Unrelated, but I’m using your calendar plugin, it’s nice!

There a lot of different issues around multiuser (authentication, write locks, authorization, …). For this thread I’d like to concentrate on just the trust issue: when the wiki starts, certain tiddlers contain code and they will be executed with the privileges as the user opening the wiki.

For example, I could create a javascript tiddler which deletes all tiddlers in the wiki. The syncadaptor will happily sync these changes to the node backend which will then delete the files containing the tiddlers.

Tiddlywiki can’t replace MediaWiki, but it could be useful for small teams (5-10 people), where there’s enough of us that we don’t necessarily want to run everyone else’s code with full privileges. There doesn’t need to be malicious intent, it could be a bug in a tiddler created by one user which accidentally deletes tiddlers for another user without any action on their part. I would like to make sure this can’t happen.

G’day @neumark ,

I’ve done a significant amount of work investigating multi-user TiddlyWiki.

Too much info / observations to mention.

You’ll find a brutally rough (picture spaghetti thrown at a wall) partial cobbling of way too many intertwingled thoughts to coherently jot down: HERE.

Cheers and best regards!

For new javascript to execute in a TiddlyWiki instance, the TiddlyWiki has to be saved and then reloaded.

I haven’t tried this (somebody with the experience can chime in), but my understanding of TiddlyWiki on node.js is that the javascript will not become enabled until the node.js process for that TiddlyWiki is restarted. (I may be way off here in my understanding.)

Regardless, one would want a back-end automated process of some kind to monitor the TID files for every TiddlyWiki instance, and zap any TID file that involves “unsanctioned” (?) javascript. I think.

Personally, especially for a small tight-knit team: I’m thinking allow the risk of that low probability mess, and rely on regular backups as the undo-mess mechanism.

I’ve seen people delete critical information from a shared network drive. No sweat. Just restore from the latest backup.

TiddlyWiki is A-1 for content sharing between a whole bunch of people. For multi-user, in particular robust multi-user, I’d be looking at something that has everything right from inception designed with all things multi-user in mind.

No one thing can excel at everything. Any one thing’s greatest strength is the greatest weakness, and vice versa. To really excel at something, the related magic has to be in the DNA. Anything can be MacGyvered to handle anything (not meant as a put down, it is just a favourite word), and can be really well done. But if it ain’t DNA, as in baked-in from scratch, it probably ain’t going to be stellar, or resilient, or either.

All that said, though, my joy of doing stuff with TiddlyWiki and pushing the daylights out of it still has me researching and experimenting with multi-user potential. Very easy to geek out.

I might be more of a believer in the practicality of multi-user TiddlyWiki if I saw more proof in the pudding displays of it. A community/public/open multi-user sandbox, if there is one? (Great way to collaborate on documentation without getting into heavy process.)

@Charlie_Veniot I htink that everything you said is correct, you can do whatever you want to the wiki in the browser because it is completely in your browser and in your control, but the server-side component doesn’t have to accept changes if they aren’t authorized.

All of the danger comes from what gets synced to the server. The syncer has two components, the one in the browser and the part on the server. In the same way that on tiddlyhost you can go to someone elses wiki and edit it all you want, but it doesn’t save it to the server. The multi-user situations just need access controls that handle it the same way. The actions on the back-end can be controlled in a very detailed way, like you could only create tiddlers that won’t run javascript, or you can only modify specific tiddlers.

The danger and the need for caution is very real, but there are solutions demonstrated in other systems that can be used in a multi-user tiddlywiki environment.

Also, I made a public multi-user sandbox a few years ago, it got almost no attention or use. I haven’t touched it in a long time and I don’t think that it is still up, but given the interest shown recently I will try and devote some time to this project again.

4 Likes