You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
pxSentinel is a server-side FiveM resource that scans all loaded resources for known backdoor and malware signatures. When a match is found, it logs a detailed report to the console with remediation guidance, stops the infected resource, and optionally halts the server entirely.
7
+
**Server-side malware scanner for FiveM.** pxSentinel scans all loaded resources for known backdoor and malware signatures, logs detailed detection reports with remediation guidance to the console, alerts your team via Discord, and optionally stops infected resources or halts the server.
8
8
9
9
---
10
10
11
11
## Features
12
12
13
-
* Performs a full scan of every loaded resource after the server finishes starting
14
-
* Continues scanning any resource that is started dynamically at runtime
15
-
* Stops infected resources immediately without requiring a full server shutdown
16
-
* Sends a formatted Discord embed alert via webhook on any detection
17
-
* Configurable allow list so trusted resources are never unnecessarily scanned
18
-
* Uses plain-text signature matching — Lua pattern characters in signatures are always treated as literals
13
+
|||
14
+
|---|---|
15
+
|**Full startup scan**| Scans every loaded resource once the server finishes starting. |
16
+
|**Runtime detection**| Monitors dynamically started resources throughout the session. |
17
+
|**Immediate containment**| Stops infected resources without requiring a full server restart. |
18
+
|**Discord alerting**| Sends a formatted embed to a configured webhook on any detection. |
19
+
|**Allow list**| Trusted resources are excluded from scanning entirely. |
20
+
|**Safe matching**| Plain-text signature matching — Lua pattern characters are always treated as literals. |
19
21
20
22
---
21
23
22
24
## Requirements
23
25
24
-
* FiveM server running artifact 5181 or newer
25
-
* Lua 5.4 (`lua54 'yes'` in `fxmanifest.lua`)
26
+
- FiveM server artifact `22934` or newer
27
+
- Lua 5.4 (`lua54 'yes'` in `fxmanifest.lua`)
26
28
27
29
---
28
30
29
31
## Installation
30
32
31
-
1.Download or clone this repository into your server's `resources` directory.
32
-
2. Ensure the folder is named `pxSentinel`.
33
-
3. Add the following line to the **end** of your `server.cfg`, after all other resources:
33
+
1.Clone or download this repository into your server's `resources` directory and name the folder `pxSentinel`.
34
+
35
+
2. Add the following line to the **end** of your `server.cfg`, after all other resources:
34
36
```
35
37
ensure pxSentinel
36
38
```
37
-
Placing it last gives all other resources time to register before the scan runs.
39
+
> Placing pxSentinel last ensures all other resources have registered before the scan runs.
38
40
39
-
4. Set your Discord webhook via a server convar (recommended — keeps the URL out of source files):
41
+
3. Configure your Discord webhook via a server convar (recommended — keeps credentials out of source files):
40
42
```
41
43
set pxSentinel:webhook "https://discord.com/api/webhooks/YOUR_WEBHOOK_HERE"
42
44
```
43
45
44
-
5. Review `config.lua`, `blocked.lua`, and `allowed.lua` and adjust them to suit your server.
46
+
4. Review `config.lua`, `blocked.lua`, and `allowed.lua` and adjust them to suit your server.
45
47
46
48
---
47
49
48
50
## Configuration
49
51
50
52
Configuration is split across three files to keep concerns separate.
51
53
52
-
### config.lua
53
-
54
-
General behaviour settings.
54
+
### `config.lua` — General settings
55
55
56
56
| Option | Type | Default | Description |
57
57
|---|---|---|---|
58
58
|`Config.Enable`|`boolean`|`true`| Enable or disable the scanner entirely. |
59
-
|`Config.ConsolePrint`|`boolean`|`true`| Print a formatted detection report and remediation steps to the server console. |
60
-
|`Config.StopResources`|`boolean`|`false`| Stop each infected resource immediately upon detection. **Disabled by default** — see warning below. |
61
-
|`Config.StopServer`|`boolean`|`false`| Halt the entire server after handling detections. Use only if you require zero tolerance. |
62
-
|`Config.ScanDelay`|`number`|`5000`| Milliseconds to wait before the initial full scan runs. Allows all resources time to register their file metadata. Increase this for servers with very large resource lists. |
63
-
|`Config.Discord.Enabled`|`boolean`|`true`| Send a Discord alert when a detection occurs. |
64
-
|`Config.Discord.Webhook`|`string`|`""`| Webhook URL. Prefer setting this via the `pxSentinel:webhook` convar rather than hardcoding it. |
65
-
66
-
> **Warning — kill-switch backdoors:** Some sophisticated backdoors hook the `onResourceStop` event and call `os.exit()` as a self-defence mechanism when they detect they are being stopped. Enabling `Config.StopResources` causes pxSentinel to call `StopResource()` on the infected resource, which fires that hook, kills the server process, and causes txAdmin to interpret the exit as a crash and automatically restart the server — potentially with the backdoor still present.
59
+
|`Config.ConsolePrint`|`boolean`|`true`| Print a formatted detection report and remediation steps to the console. |
60
+
|`Config.StopResources`|`boolean`|`false`| Stop each infected resource immediately upon detection. See warning below. |
61
+
|`Config.StopServer`|`boolean`|`false`| Halt the server after all detections are handled. |
62
+
|`Config.ScanDelay`|`number`|`5000`| Milliseconds to wait before the initial scan runs. Increase for large resource lists. |
63
+
|`Config.Discord.Enabled`|`boolean`|`true`| Send a Discord alert on detection. |
64
+
|`Config.Discord.Webhook`|`string`|`""`| Webhook URL. Prefer the `pxSentinel:webhook` convar over hardcoding. |
65
+
66
+
> [!WARNING]
67
+
> **Kill-switch backdoors** — Some backdoors hook `onResourceStop` and call `os.exit()` as a self-defense mechanism. When `Config.StopResources` is enabled, pxSentinel calls `StopResource()` on infected resources, which fires that hook, terminates the server process, and causes txAdmin to treat it as a crash — automatically restarting with the backdoor potentially still in place.
67
68
>
68
-
> **Recommended workflow when a detection fires:**
69
-
> 1. Note which resource is infected (console output + Discord alert).
69
+
> **Recommended response when a detection fires:**
70
+
> 1. Note the infected resource name from the console output or Discord alert.
70
71
> 2. Use txAdmin to **stop** the server (not restart).
71
-
> 3. Delete the infected resource from your server folder.
72
+
> 3. Delete the infected resource from your server directory.
72
73
> 4. Start the server again.
73
74
>
74
-
> Set`Config.StopResources = true` only if you have confirmed no kill-switch is present, or if you accept the risk of an automatic txAdmin restart.
75
+
> Enable`Config.StopResources` only if you have confirmed no kill-switch is present, or if you accept the risk of an automatic txAdmin restart.
75
76
76
-
**Note:** If both `Config.StopResources` and `Config.StopServer` are `true`, pxSentinel stops each infected resource first and then halts the server after the Discord alert has been dispatched.
77
+
> [!NOTE]
78
+
> When both `Config.StopResources` and `Config.StopServer` are enabled, pxSentinel stops each infected resource first, then halts the server after the Discord alert has been dispatched.
77
79
78
80
---
79
81
80
-
### blocked.lua
82
+
### `blocked.lua` — Malware signatures
81
83
82
-
Defines `Config.Signatures`, a list of plain-text strings that are scanned against the contents of every server script file in every loaded resource.
84
+
Defines `Config.Signatures`, a list of plain-text strings matched against every server script in every loaded resource. Entries are grouped by category: known panel domains, C2 infrastructure, exfiltration patterns, and obfuscator watermarks.
83
85
84
-
Entries are grouped by category — known panel domains, C2 infrastructure, exfiltration patterns, and common obfuscator watermarks.
85
-
86
-
To add your own signatures, append them to the list:
86
+
To add a signature, append it to the list:
87
87
88
88
```lua
89
89
Config.Signatures= {
@@ -92,15 +92,15 @@ Config.Signatures = {
92
92
}
93
93
```
94
94
95
-
All entries must be plain strings. Lua pattern metacharacters such as `.`, `%`, `(`, and `)`are always treated as literals and will never cause false positives or matching errors.
95
+
All entries must be plain strings. Lua pattern metacharacters (`.`, `%`, `(`, `)`, etc.) are always treated as literals.
96
96
97
97
---
98
98
99
-
### allowed.lua
99
+
### `allowed.lua` — Safe resources
100
100
101
-
Defines `Config.SafeResources`, a list of resource folder names that pxSentinel will never scan. Any resource on this list is skipped entirely, without reading any of its files.
101
+
Defines `Config.SafeResources`, a list of resource folder names that pxSentinel will never scan. Any listed resource is skipped without reading any of its files.
102
102
103
-
The list includes the CFx platform resources, the ox stack, QBCore, ESX, and a set of common trusted standalone resources out of the box. Add your own trusted resources at the bottom of the list:
103
+
The default list covers CFx platform resources, the ox stack, QBCore, ESX, and common trusted standalone resources. Add your own at the bottom:
104
104
105
105
```lua
106
106
Config.SafeResources= {
@@ -109,45 +109,43 @@ Config.SafeResources = {
109
109
}
110
110
```
111
111
112
-
Use the exact resource folder name. Wildcards are not supported.
112
+
> Use the exact resource folder name. Wildcards are not supported.
113
113
114
114
---
115
115
116
116
## How It Works
117
117
118
-
When pxSentinel starts, it waits for `Config.ScanDelay` milliseconds to allow all other resources to finish registering their metadata. It then iterates every loaded resource, reads each declared server script file, and checks the file content against every entry in `Config.Signatures` using plain-text matching.
119
-
120
-
Resources listed in `Config.SafeResources` are excluded from scanning entirely.
118
+
On start, pxSentinel waits `Config.ScanDelay` milliseconds for all resources to finish registering, then iterates every loaded resource, reads each declared server script file, and checks its content against every signature in `Config.Signatures` using plain-text matching. Resources listed in `Config.SafeResources` are skipped entirely.
121
119
122
-
On a positive detection, pxSentinel:
120
+
**On a positive detection, pxSentinel:**
123
121
124
-
1. Groups all findings by resource and prints a formatted report to the console, including the resource name, file path, matched signature, and a numbered list of recommended remediation steps.
122
+
1. Groups findings by resource and prints a report to the console — resource name, file path, matched signature, and recommended remediation steps.
125
123
2. Sends a Discord embed alert to the configured webhook.
126
-
3. Calls `StopResource()` on each infected resource if `Config.StopResources` is enabled. Note that backdoors with an `onResourceStop` kill-switch will call `os.exit()` at this point — see the warning in the configuration table above.
124
+
3. Calls `StopResource()` on the infected resource if `Config.StopResources` is enabled.
127
125
4. Calls `os.exit(1)` to halt the server if `Config.StopServer` is enabled.
128
126
129
-
After the initial scan completes, pxSentinel listens for the `onResourceStart`event and scans any resource that starts dynamically at runtime. Resources that start during the initial settle window are already covered by the full scan and are not scanned twice.
127
+
After the initial scan, pxSentinel listens for `onResourceStart` and scans any resource started dynamically at runtime. Resources that start within the settle window are covered by the full scan and are not scanned twice.
130
128
131
129
---
132
130
133
131
## Keeping Signatures Up to Date
134
132
135
-
The built-in signature list covers known backdoor panels, C2 domains, exfiltration patterns, and obfuscator watermarks at the time of release. As new threats emerge, `blocked.lua`will be updated in the repository.
133
+
The built-in signature list targets known backdoor panels, C2 domains, exfiltration patterns, and obfuscator watermarks at the time of release. `blocked.lua`is updated in the repository as new threats are identified.
136
134
137
-
To contribute a new signature, open a pull request with the string, a short description of what it targets, and any hex-encoded variants you are aware of.
135
+
To contribute a signature, open a pull request with the string, a brief description of what it targets, and any known hex-encoded variants.
138
136
139
137
---
140
138
141
139
## Further Reading
142
140
143
141
| Document | Description |
144
142
|---|---|
145
-
|[`.github/BACKDOORS.md`](.github/BACKDOORS.md)|A running catalogue of real backdoor samples observed in the wild, with structural analysis, the signatures that detect each one, and remediation steps. Start here if you want to understand what pxSentinel is actually protecting against. |
146
-
|[`.github/DEVELOPMENT.md`](.github/DEVELOPMENT.md)| Architecture decisions, design rationale, and a detailed account of how pxSentinel was hardened against a live backdoor during development. Useful if you want to extend the scanner or understand why specific choices were made. |
147
-
|[`.github/SECURITY.md`](.github/SECURITY.md)|Security policy supported versions and the responsible disclosure process for reporting vulnerabilities in pxSentinel itself. |
143
+
|[BACKDOORS.md](.github/BACKDOORS.md)|Catalogue of real backdoor samples with structural analysis, detection signatures, and remediation steps. |
144
+
|[DEVELOPMENT.md](.github/DEVELOPMENT.md)| Architecture decisions, design rationale, and an account of how pxSentinel was hardened against a live backdoor during development. |
145
+
|[SECURITY.md](.github/SECURITY.md)|Supported versions and the responsible disclosure process for reporting vulnerabilities in pxSentinel itself. |
148
146
149
147
---
150
148
151
149
## License
152
150
153
-
This project is licensed under the [AGPL-3.0-or-later](LICENSE) license.
0 commit comments