Creator Marketplace: Improving Model Safety

There is so many better ways you could’ve gone around this Roblox why did you not ask the community before just acting. You need to think about the community and not just yourself!

It doesn’t matter what the dependency is, automatically updating is dangerous. What happens if the owner of Adonis gets compromised and a malicious update is pushed to the model? Suddenly, thousands of games have a backdoor that is free to abuse until it’s removed. If a developer has more sinister intentions they could keep a backdoor there once the model gains a following and abuse games that may not be updated anymore.

Granted, there are upsides to automatic updates, but they do not outweigh the risks. If you want to keep on top of the updates for a dependency you use then you should follow it in the appropriate channels (DevForum, GitHub, Discord, etc) and petition Roblox to provide better versioning tools for public models.

12 Likes

They already do terminate malicious models. Besides the “root of the problem” isn’t the malicious models per say, (there isn’t any fool proof thing to fix this), but the fact that features like 3rd party requires exist and there doesn’t exist any very god ways to contain them.

Doing something about potentially malicious features to contain them is a much better approach (and has been proven to be the most effective with fighting malicious scripts, examples include 3rd party sales and teleport restrictions, and plugin permissions.)

But yeah I do think this change was made too quickly, they should have given a 4-5 month period at minimum to migrate, this currently is made too quickly so people can’t migarete their systems in time.

Many old projects depend on requires and fenvs so its too short of a timeline for migration, more time should be allowed.

1 Like

well, this does help others from falling victim of false account deletions (which happened to my main ive had since 2013) (and also my dev fourm acc still exists somehow)

i was really hoping to make my own admin panel script, but this prevents development entirely for everyone. i cant even make an autoupdate in my scripts anymore. please revert the update, and instead LISTEN to the community and allow us to OPT OUT of requires. we should NOT all be punished over a small part of our community behaving badly. this entirely kills off organized scripts, and smaller admin panels. (we can live without getfenv)

the biggest giveaway to a bad module is a module called “luaparser” or “loadstring” so people can exploit on infected games. and they always use “rerubi” or something along the lines of that. theres many solutions you could have chose, and were open in the air yet you chose the worst one possible to do. revert this update immediately, you know it says something when even the owner of HD admin does not think this is a good change

also we need a moderation overhaul, i provided proof in my appeal and yet i did not get my account back. which is infuriating since ive had my account since i was 4 years old. and its all gone! i was looking forward to having my acc become 10 years old but thats not happening anymore i guess, thanks for listening to the community roblox devs.

2 Likes

Yes, I didn’t think of this, and I agree, But using httpservice for auto updating isn’t very much of a solution. As many games dont allow httprequests. And as of now, there is no api for auto update tools. The only way to have this functionality without httpservice is module scripts.

There is one hacky workaround and that is BaseScript.LinkedSource

1 Like

Sorry, I’m confused about how HTTPService fits in here. Automatic updates shouldn’t be a thing, period.

4 Likes

Auto updates should be able to opt out of not removed entirely they are a really useful feature for some things

Many games don’t allow web requests specifically for the reason you’re arguing against. You should NOT be doing anything that would affect another person’s game. What if one of your bugfix updates breaks a large game that uses your module? Are you going to pay for their losses? You likely claim no liability but require that your users rely on your updates. If the version is out of date, you can notify the developer and they can manually update. This is the way everyone in the real world does it.

1 Like

I second this.
Modern obfuscators significantly shuffle the AST of the output to prevent exactly this kind of analysis. If the marketplace models are going to be put under a static AST analysis then either the success rate will be very low or the amount of false positives will be very high.

2 Likes

This will help, but maybe the idea of permissions in properties or disabling Getfenv id in games would be more accurate, according to most replies.

1 Like

It would be nice to know though what counts as obfuscated code.

4 Likes

If they tell us, It would help people get around it.

1 Like

Yeah, being vague only makes me nervous as to what does or does not count as obfuscated code. An example is necessary, crucial even.

These exactly! In an ideal marketplace we wouldn’t have to depend upon MainModules although Roblox’s attitude over the years has been to burn everything down instead of actually developing useful safer alternatives.

For us in the past, MainModules have been vital in deploying fixes for critical vulnerabilities and bugs. Without this functionality I doubt many developers would have manually updated their models, although I agree that we should absolutely advocate for better alternatives such as versioning.

It’s worth noting that a lot of younger users or less experiences developers are the ones utilising marketplace applications. If versioning tools were introduced they should be straight-forward to use, review and update.

Roblox did mention something along the lines of using packages (I believe?) to replace the behaviour of MainModules, although as fair as I’m aware they’re really limited right now and require the creator to individually grant permissions to users (which isn’t scalable at all).

17 Likes

I can assure you Mr. Bones will not get compromised, along with the rest of the Adonis Development Team, Nor will ForeverHD. Please understand the system you’re talking about before making drastic opinions on it. Adonis undergoes many updates a year including new features, and most imporantly, security fixes, which have prevented semi-major games from being backdoored multiple times in history. This should be a given. Nearly every maintained user-facing system has an automatic update system and the update server being compromised is never a realistic main concern.

Contributors, Developers, and Users are all acutely aware of what goes on inside the repo and when the nightly and mainmodule is updated. We are notified upon a new nightly and major release.

4 Likes

If the marketplace was a door that leaks when it rains, Roblox just replaces it with a wall instead of making the door more secure. They do this with most things.

8 Likes

This is why Roblox needs to learn that replacing the door with a wall is not better then replacing the door with a new door or heck even repairing it.

I can’t believe they have made these crazy changes the past few months

2 Likes

Anyways if someone needs a replacement for having a virtual Lua run thing which doesn’t use fenvs then here is one (I know this isn’t the #resources:community-resources page but i feel like its very important for me to share this)

Here is a virtual env implementation you can use for free

--!strict
--[[
	Description: A virtual enviroment implementation to replace the legacy function enviroments
	Author: github@ccuser44/ALE111_boiPNG
	Date: 15.2.2022
--]]

type dictionary = { [string]: any }
type func = (...any?) -> (...any?)

local globalEnv: dictionary = {
	-- // Libraries
	coroutine = coroutine,
	debug = debug,
	math = math,
	os = os,
	string = string,
	table = table,
	utf8 = utf8,
	bit32 = bit32,
	task = task,

	-- // Lua globals
	assert = assert,
	collectgarbage = function(action: string): number -- Use gcinfo instead
		assert(type(action) == "string", "invalid argument #1 to 'collectgarbage' (string expected, got "..type(action)..")")
		assert(action == "count", "collectgarbage must be called with 'count'; use gcinfo() instead")

		return gcinfo()
	end,
	error = error,
	getmetatable = getmetatable,
	ipairs = ipairs,
	newproxy = newproxy,
	next = next,
	pairs = pairs,
	pcall = pcall,
	print = print,
	rawequal = rawequal,
	rawget = rawget,
	rawset = rawset,
	select = select,
	setmetatable = setmetatable,
	tonumber = tonumber,
	tostring = tostring,
	type = type,
	unpack = unpack,
	xpcall = xpcall,
	warn = warn,
	gcinfo = gcinfo,
	_G = _G,
	_VERSION = _VERSION,

	-- // Roblox globals
	settings = settings,
	time = time,
	typeof = typeof,
	UserSettings = UserSettings,
	require = require,
	game = game,
	workspace = workspace,
	shared = shared,

	-- // Deprecated Roblox globals (Please don't use, use the alternative instead)
	delay = task.delay,-- Use task.delay instead
	spawn = task.defer,-- Use task.spawn instead
	wait = task.wait,-- Use task.wait instead
	elapsedTime = os.clock,-- Use os.clock instead
	stats = function(): Stats
		return game:GetService("Stats")
	end,-- Use game:GetService("Stats") instead
	tick = tick,-- Use os.time or os.clock instead

	-- // Roblox datatypes
	Axes = Axes,
	BrickColor = BrickColor,
	CatalogSearchParams = CatalogSearchParams,
	CFrame = CFrame,
	Color3 = Color3,
	ColorSequence = ColorSequence,
	ColorSequenceKeypoint = ColorSequenceKeypoint,
	DateTime = DateTime,
	DockWidgetPluginGuiInfo = DockWidgetPluginGuiInfo,
	Enum = Enum,
	Faces = Faces,
	FloatCurveKey = FloatCurveKey,
	Instance = Instance,
	NumberRange = NumberRange,
	NumberSequence = NumberSequence,
	NumberSequenceKeypoint = NumberSequenceKeypoint,
	OverlapParams = OverlapParams,
	PathWaypoint = PathWaypoint,
	PhysicalProperties = PhysicalProperties,
	Random = Random,
	Ray = Ray,
	RaycastParams = RaycastParams,
	Rect = Rect,
	Region3 = Region3,
	Region3int16 = Region3int16,
	TweenInfo = TweenInfo,
	UDim = UDim,
	UDim2 = UDim2,
	Vector2 = Vector2,
	Vector2int16 = Vector2int16,
	Vector3 = Vector3,
	Vector3int16 = Vector3int16,
}

table.freeze(globalEnv)

return function()
	local env: dictionary = {}

	for k, v in pairs(globalEnv) do
		env[k] = v
	end

	env._ENV = env :: dictionary

	env["getf".."env"] = function(target: (func | number)?): dictionary
		assert(type(target) == "number" or type(target) == "function" or type(target) == "nil", "invalid argument #1 to 'setf".."env' (number expected, got "..type(target)..")")
		assert(type(target) == "number" and target >= 0 or type(target) ~= "number", "invalid argument #1 to 'setf".."env' (level must be non-negative)")

		return env
	end

	env["setf".."env"] = function(target: func | number, newEnv: dictionary): ()
		assert(type(newEnv) == "table", "invalid argument #2 to 'setf".."env' (table expected, got "..type(newEnv)..")")
		assert(type(target) == "number" or type(target) == "function", "invalid argument #1 to 'setf".."env' (number expected, got "..type(target)..")")
		assert(type(target) == "number" and target >= 0, "invalid argument #1 to 'setf".."env' (level must be non-negative)")

		table.clear(env)

		for k: string, v: any in pairs(newEnv) do
			if type(k) == "string" then
				env[k] = v
			end
		end
	end

	-- // Stupid luau linter cant even recognise a metatable
	setmetatable(env, table.freeze({
		__index = globalEnv,
		__metatable = "The metatable is locked"
	}))

	return env
end

You can use this LBI made by Rerumu https://github.com/Rerumu/FiOne and input the virtual env to it.

Here is a full loadstring module which works with a VirtualEnv. \ /

https://roblox.com/library/9657684824/virtual-env-loadstring
Loadstring.rbxmx (192.4 KB)

You probably should also remove require, _G and shared from the VEnv script because Roblox might not like them. (Possibly)

7 Likes

Well, I think the community is partly to blame, We must drive Roblox crazy with our complaints and requested features/changes. But yeah they remove stuff instead of fixing it lol.

4 Likes