Most "this script is a backdoor" claims you find in a Discord chat are unverified. The useful question is not whether a script is called a backdoor, but what its code actually does before you install it on a server that holds real money and real player data.
A static scanner can answer part of that. It cannot answer all of it, and knowing where the line is makes the result usable.
What a static scan can tell you
A scanner reads the files in a resource and looks for code that has no business being in a paid script. The patterns that matter on FiveM are specific:
Code hidden behind whitespace. A loader appended to an otherwise normal line, padded with spaces so that it sits far to the right of the visible editor area. It is invisible in a screenshot of the file and easy to miss in review.
Code downloaded and executed. load() or loadstring() applied to the body of an HTTP response. Whoever controls that web server controls your server, and the control changes the moment the domain expires or is sold.
Runtime-decoded payloads. string.char lists, escaped byte sequences, base64 or hex blobs that only turn into readable code at runtime. A reviewer cannot check what they cannot decode.
Reads of server secrets. sv_licenseKey, rcon_password, sv_tebexSecret, or a database connection string, inside a file that also sends HTTP requests. That combination is what a key-stealing loader looks like.
Requests to raw IP addresses. A script that only talks to a domain can be reviewed. A script that talks to http://185.220.101.7/... cannot be attributed to anyone.
Writes outside its own folder. SaveResourceFile into another resource, io.open in write mode, os.execute, io.popen. A resource that rewrites a different resource is doing something no legitimate script needs.
Executables in the archive. A .exe, .bat or .ps1 inside a FiveM resource has no runtime purpose. So do archive entries that would extract outside their folder.
The RPScripts FiveM Backdoor Scanner checks exactly this list. Drop in a resource ZIP, a category folder or your whole resources folder — it handles Lua files with every check and JS files with the hidden-code check, up to 300 MB. The scan runs in the browser and your files are not uploaded.
What it cannot tell you
Intent. A call to PerformHttpRequest might be a licence check, a heartbeat or an exfiltration. The scanner reports the call; it does not read minds.
What a remote endpoint returns. The dangerous part of a downloader is usually the payload, and the payload arrives after the scan. The scanner can show you that your server would execute whatever that URL returns. It cannot tell you what is served tomorrow.
Runtime behaviour. Static analysis reads code, not execution. A script that behaves differently depending on a date, a license value or the server name passes every static check and is still a backdoor.
Your server's own files. The scan covers the files you hand it. A resource that was already installed, modified in place, or replaced by a later update is outside it.
A workflow that holds up
- Scan before you install, not after. The whole point is that the decision to install has not been made yet.
- Scan the dependency chain too. A clean resource that depends on a dirty one is still dirty. The scanner accepts a whole resources folder for exactly this reason.
- Keep a copy of what you installed. If a file changes later, you want to know which file and when.
- Watch the console and the outbound traffic on a staging server first. A script that phones home at boot is visible in the first minute.
- Do not store your Tebex or licence keys in a resource that can reach the network. Even for a legitimate script, this is a smaller blast radius.
Disclosure: this post is from RPScripts. The scanner linked above is ours and free to use in the browser. The findings are yours to verify — a scanner is evidence, not a verdict.
Top comments (0)