Plugins shouldn't require HttpEnabled

I want to make a plugin to access my github, but to use it the user has to switch on HttpEnabled in order to make web requests. Since the sole purpose of my plugin relies on that connectivity it would be nice to not have to ask them to switch it on to use my plugin and instead just allow requests from Plugins automatically.

2 Likes

It should not be tied to HttpEnabled I agree, and maybe the user has to approve Http access for each plugin individually? For example this could help against shady plugins that are gathering information about you or your games without you knowing.

6 Likes

That could be potentially bad, because I could easily just send the entire place to an eternal server and steal any number of peoples games before the plugin got found out.

I like the suggestion of per plugin HTTP access, though. That might be better.

1 Like

Maybe there could be a permission system like how mobile apps and chrome extensions work.

2 Likes

It’s not really different in the current system anyway. If you open a game that already has it switched on then you’ve just allowed that user to send the place to their server. It’s down to the user to select the plugins they use and if their are some shady ones then perhaps it’s their fault for choosing it?

That sort of argument will never slide with ROBLOX, though, as evidenced by us not having clipboard support. :confused:

Ideally we would have a robust permissions system where you can grant the ability to make HTTP requests to certain plugins and not to others. Unfortunately our system was not designed this way. When you click play in Studio any script can make an HTTP request, so if we tried to impose restrictions when plugins make HTTP requests, we would also have to build a permission system for scripts as well.

The best short-term solution I can think of would be to prompt the user whenever an HTTP request is made to a new domain (e.g. www.example.com) and give them the option of allowing/blocking all requests from that domain. This would ensure that if you insert a script into your game which tries to steal your place, you would notice a suspicious domain and be able to reject the request. We might even be able to remove the HttpService setting if we did this.

4 Likes

If we’re being honest here, I’d prefer it if scripts had a permissions system, as it’d effectively eliminate plugins and normal scripts as a method for sending data without permission.

If you have suggestions on specifically how a permissions system could be implemented in the ROBLOX engine, please post them here. We are open to ideas.

WARNING: Wall of Text Ahead

After talking it over with friend, there are a few ways that a permissions system could be reliably implemented:

If we’re talking plugins, it’d be as ā€œsimpleā€ as adding a prompt when installing a plugin to allow access to certain APIs (Http, Datastore, Create place, that sort of thing). That’d presumably be stored either online or in the same folder as the settings.json for each plugin. This would let plugin owners not have to have their plugin whitelisted every time it updates, as well as give the user control over what they can do.

When we get to regular scripts, it gets a bit more complicated. You can obviously try to just have a list of properties per script that allow certain things to be done in it, but that raises some annoying problems. For starters, it’d have to take into account both pre-existing scripts, scripts inserted via plugins/models, and scripts created during run-time. These properties would have to have some form of security on them (either one of the thread identity tags or unscriptable), and be set automatically in some cases to avoid being annoying while making scripts. Ideally, if this were the way things were, they’d be set automatically when a user inserted a script themselves (via Advanced Objects or the like), and if they were inserted in studio from Free Models, Insert Service, or a Plugin, they would have to be manually set (via prompt or otherwise). As for scripts inserted during runtime, if it was inserted and in the developers inventory, it should inherit the permissions that it had while being published; otherwise, it should have no permissions. This system is a poor choice because it requires saving this sort of data per script, which is unnecessary, in addition to modifying scripts, ModuleScripts, the publishing system, and the inserting system.

Another system that could be implemented is similiar to the above but on a per-source basis. The idea would be that for every source in the game, it would have to be whitelisted in order to run certain members of the API. In practice however, this raises issues with plugins and free models. For plugins, their sources can be updated frequently, and this would require a re-whitelisting every single update (unless it was combined with the initial plugin suggestion, which is sound). For free models, it raises several issues. If you’re inserting something that relies upon a ModuleScript, does it just assume that ModuleScript’s permissions? What if that ModuleScript uses the HttpService or one of the other APIs that isn’t allowed in the initial script? If you’re requiring a module by ID, how do you confirm that that ID won’t be doing malicious things later on? There’s an argument for not caring, as even with the current system this could be put in place, but it may as well be brought up since we’re discussing this. There’s no easy way to address this, which brings me to our third and most drastic/involved method.

Google Play and services like it implement permissions upon install of applications and programs. These permissions are given to the user for confirmation upon request to install. If this were applied to ROBLOX as it is in those systems, it would fail miserably simply due to ROBLOX being unable to determine the permissions of a script (possibly, I’m not sure if this is true), and not being able to trust malicious users to give the correct permissions. The solution, if something were to be implemented like this, would be for ROBLOX to auto-generate permissions per-script. How they would do this is really up to them, but CntKillMe (the friend I mentioned above) suggested a VM based check in order to determine what functions would be called were the script to fully run. His suggestion included running every line, ignoring line-skips, and catching if any blacklisted functions were called, then tagging a script with that permission. I’m by no means an expert on the Lua VM, so I’m not sure how viable that is to do in practice, but it’d not be without its hardships. Provided it is possible, then the model would be tagged when it was published as either a plugin or an actual model and given permissions that could be prompted upon inserting. It would have to be done on ROBLOX’s servers, to prevent client-tampering, but it would be the most reasonable solution.

There are two major flaws in the above system, one of which is present throughout all three suggestions. This is, of course, the ModuleScript problem. You cannot reasonably assume that ModuleScripts are safe, if they’re required by ID. This means you’d have to do one of three things: Inherit permissions, warn the user that they’re using a ModuleScript they don’t own (would require a basic check on what was being called in a script), or do nothing. Inheriting permissions would be the easiest solution, but it falls apart because of how ModuleScripts are run: once per client/server, per identity. What is safe in one script may not be safe in another, so you cannot assume permissions. This leaves warning the user and doing nothing, of which one is obviously better than the other. There’s another option, which is an extension of the first, which is to make ModuleScripts run per permissions, per client/server, per identity. That’s obviously not ideal, so a warning would probably be for the best.

The second flaw is, well, a much harder one to solve. The problem with running a VM would be catching all the functions referenced. This is a problem that me and CntKillMe thought hard about, and couldn’t come up with a solution that wasn’t disgusting. By the very nature of Lua, there are literally infinite ways to reference and call a function, meaning there are literally infinite way to potentially bypass this catch. If it were run line by line, it would be very possible to set a variable to nil in a way that would only happen while the VM was running, ending in an unsafe script being tagged as ā€œsafeā€.

The two ā€˜gross’ methods we came up with are as follows:

1.) Run the entire script with every condition running as both true and false. This is disgusting because it would take forever, and is horribly inefficient.
2.) Run through the script and catch intentially hidden references somehow, whether it be through checking the previous contents of variables or something else.
(This assumes we’re using a VM, which may be a poor choice. I’m not an engineer, I don’t know what’s best for ROBLOX.)

EDIT: Might just be worth skipping over or flagging anything suspicious like ā€˜if false then’ or ā€˜if math.random() then’ and checking it thoroughly.

TL;DR: There’s no easy way to implement a permissions system for ROBLOX, but there are quite a few ways to almost implement one.

Something along to lines of.

-- Returns a boolean as to whether the user has granted the plugin permission
plugin:GetPermission(string permissionFlag)
-- Prompts the user for permission to use a certain feature
plugin:RequestPermission(string permissionFlag)
-- Executes the callback function or errors if the relevant flag is false
plugin:InvokePermission(string permissionFlag, function callback)

or

-- plugin:InvokePermission(string permissionFlag, httpService.GetAsync, variables)
-- Permission flag tells you that you need to pass httpService in internally
-- so it's not one of the variables
plugin:InvokePermission(string permissionFlag, InstanceMethod method, variables)

If it’s possible though the latter would be better if it didn’t require a callback and instead the plugins security would allow it to now use the method it has requested (such as those under HttpService)