Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: Secure external file access macro functions #5163

Open
fishface60 opened this issue Feb 2, 2025 · 3 comments
Open

[Feature]: Secure external file access macro functions #5163

fishface60 opened this issue Feb 2, 2025 · 3 comments
Labels
feature Adding functionality that adds value

Comments

@fishface60
Copy link
Contributor

Describe the Problem

#4728 #3826 and #4677 are open issues for various forms of external file access for reading.

#4728 and #3826 are possible to implement by using a HTML5 dialog to prompt to enter a path like https://discord.com/channels/296230822262865920/1222304280204279948
though some use-cases would find needing to prompt every time to be inconvenient.

#4677 is related and could be part of the same mechanism, but only needs to read and is a fully interactive process so has fewer security considerations.

I would like to associate tokens with an external file, like the herolab functions, but in a more generic way since I do not use herolab.
I would also like to be able to write changes to these external files since mid-round players may expend ammunition, FP and other resources, and these changes belong in the character sheet instead of the tokens since the character sheet is the canonical source of truth.
Additionally, prompting every time changes need to be made is going to be unusable, and deferring saving of changes for a manual (or prompted at the end of a round) write-back risks forgetting.

The Solution you'd like

TBD. I am reading through documentation and specifications of browser file access APIs since they have a similar security threat model since they involve running arbitrary scripts from a semi-trusted source.

Discussion has mostly occurred in https://discord.com/channels/296230822262865920/1334279244104077363

Craig has made the point that this mustn't provide automatic file access but prompting every session is an acceptable compromise.

Reverend has suggested the Resources interface is an existing mechanism for specifying directories to expose to MapTool.

Alternatives that you've considered.

Write a bot that handles external file access. This is less useful for other MapTool users and will require ongoing work to maintain.

Additional Context

No response

@fishface60 fishface60 added the feature Adding functionality that adds value label Feb 2, 2025
@fishface60
Copy link
Contributor Author

For browsers:

  • The <input type="file"> element is always available to read files, but prompts all the time.
  • The <a download="file_name"> element is always available to write files, but prompts, defaults to downloading in a specific path and may not be used to replace existing files.
  • The Drag and Drop API can receive files.

These first two are already available to MapTool by creating a HTML5 panel. Drag and Drop would require more effort.

In addition, Chrome has a File System access API which:

  1. Is only available in a Secure Context, which is essentially if your page was served by https, http on the loopback address, or a file:// URI.
    Since LetsEncrypt means essentially any website can support SSL this is less about trusting the identity of the server
    and more that it's not MITM'd so a third party can interfere.

    In the context of MapTool this would require that the connection between client and server involves some form of TLS.
    To meet this requirement we need to upgrade the WebRTC connection to use a wss:// socket to exchange SDPs and to upgrade MapTool's Socket connection to use SSL.

    In principle this is possible by:

    1. Implement a KeyManager that returns the existing RSA key and returns a self-signed certificate so that the server can provide a self-signed certificate.
    2. Implement a TrustManager backed by a MapTool-managed pre-shared certificate store.
    3. Optionally Servers could send their certificate to the Registry and clients that connect via the registry could use that certificate to encrypt.

    I don't know how this should integrate with the existing server handshake, since SSL does its own, or if it even should.
    Client certificates could be an alternative to the private key.

  2. Is only available as part of a user gesture, e.g. in the handler for clicking a button.

    I don't think MapTool has anything analogous to this,
    but if we're restricting access to resource libraries
    then an explicit user gesture has happened beforehand to preauthorize access.
    This is a weaker guarantee than everything is in the context of a user gesture, but might be acceptable.
    We might be able to add extra context to button presses or running macros by entering the text into chat,
    but this means execLink can't produce a prompt, and for HTML5 forms to support this the result of
    Event.isTrusted
    would need to be used in the XMLHttpRequest to propagate that context into the macro request.

  3. These showOpenFilePicker(), showSaveFilePicker() and showDirectoryPicker() functions return file handles
    that can be subsequently opened for reading and writing, and reopened
    so e.g. you can use showOpenFilePicker to pick a character sheet and read it,
    and then when stats change it can be written back to by calling
    requestPermission
    to prompt and createWritable
    to write to it.

    They take a startIn option that supports browsing from an existing directory handle and also an id option
    which if reused causes the prompt to default to the same location.

    The handles can be serialized to the IndexDB and use requestPermission to re-prompt for access to a file granted in a previous session.

  4. The navigator.storage.getDirectory()
    function grants access to the "origin" per-page storage directory that can be navigated and manipulated.
    Files in this directory do not need to prompt for access and it is available in Firefox.

    This would map to the proposed ~/.rptools-maptool/notes directory, or a subdirectory of it
    and FoundryVTT has something similar.

  5. If the page is installed as a Progressive Web Application then the permissions of saved handles are preserved.

    MapTool doesn't have an equivalent concept.
    I think the closest would be to deterministically hash all of the AddOns and Library Tokens and if the result is different next time you load the campaign then don't retain the file access permissions.

@fishface60
Copy link
Contributor Author

I think I can conclude that I was getting ahead of myself in pondering how to represent the file handle data structure in MTScript, and thinking that the read/write macro functions should pop up a progress bar.

There's a lot of work to break down for implementing this, and the Secure Context and user gesture tracking are necessary preconditions.

@fishface60
Copy link
Contributor Author

https://wicg.github.io/file-system-access/#privacy-considerations would be a useful reference for some things to restrict granting file access to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Adding functionality that adds value
Projects
None yet
Development

No branches or pull requests

1 participant