nox-openclaw-hunter 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (211) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +140 -0
  3. package/bin/nox.js +2 -0
  4. package/dist/branding.d.ts +39 -0
  5. package/dist/branding.d.ts.map +1 -0
  6. package/dist/branding.js +66 -0
  7. package/dist/branding.js.map +1 -0
  8. package/dist/cli.d.ts +15 -0
  9. package/dist/cli.d.ts.map +1 -0
  10. package/dist/cli.js +94 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/export.d.ts +21 -0
  13. package/dist/commands/export.d.ts.map +1 -0
  14. package/dist/commands/export.js +616 -0
  15. package/dist/commands/export.js.map +1 -0
  16. package/dist/commands/index.d.ts +8 -0
  17. package/dist/commands/index.d.ts.map +1 -0
  18. package/dist/commands/index.js +8 -0
  19. package/dist/commands/index.js.map +1 -0
  20. package/dist/commands/isolate.d.ts +30 -0
  21. package/dist/commands/isolate.d.ts.map +1 -0
  22. package/dist/commands/isolate.js +547 -0
  23. package/dist/commands/isolate.js.map +1 -0
  24. package/dist/commands/purge.d.ts +22 -0
  25. package/dist/commands/purge.d.ts.map +1 -0
  26. package/dist/commands/purge.js +295 -0
  27. package/dist/commands/purge.js.map +1 -0
  28. package/dist/commands/scan.d.ts +23 -0
  29. package/dist/commands/scan.d.ts.map +1 -0
  30. package/dist/commands/scan.js +155 -0
  31. package/dist/commands/scan.js.map +1 -0
  32. package/dist/detector/app-bundle.d.ts +13 -0
  33. package/dist/detector/app-bundle.d.ts.map +1 -0
  34. package/dist/detector/app-bundle.js +27 -0
  35. package/dist/detector/app-bundle.js.map +1 -0
  36. package/dist/detector/cli-binary.d.ts +12 -0
  37. package/dist/detector/cli-binary.d.ts.map +1 -0
  38. package/dist/detector/cli-binary.js +66 -0
  39. package/dist/detector/cli-binary.js.map +1 -0
  40. package/dist/detector/config.d.ts +21 -0
  41. package/dist/detector/config.d.ts.map +1 -0
  42. package/dist/detector/config.js +337 -0
  43. package/dist/detector/config.js.map +1 -0
  44. package/dist/detector/detection-config.d.ts +24 -0
  45. package/dist/detector/detection-config.d.ts.map +1 -0
  46. package/dist/detector/detection-config.js +242 -0
  47. package/dist/detector/detection-config.js.map +1 -0
  48. package/dist/detector/docker.d.ts +10 -0
  49. package/dist/detector/docker.d.ts.map +1 -0
  50. package/dist/detector/docker.js +94 -0
  51. package/dist/detector/docker.js.map +1 -0
  52. package/dist/detector/index.d.ts +50 -0
  53. package/dist/detector/index.d.ts.map +1 -0
  54. package/dist/detector/index.js +155 -0
  55. package/dist/detector/index.js.map +1 -0
  56. package/dist/detector/network.d.ts +34 -0
  57. package/dist/detector/network.d.ts.map +1 -0
  58. package/dist/detector/network.js +205 -0
  59. package/dist/detector/network.js.map +1 -0
  60. package/dist/detector/process.d.ts +16 -0
  61. package/dist/detector/process.d.ts.map +1 -0
  62. package/dist/detector/process.js +47 -0
  63. package/dist/detector/process.js.map +1 -0
  64. package/dist/detector/service.d.ts +17 -0
  65. package/dist/detector/service.d.ts.map +1 -0
  66. package/dist/detector/service.js +51 -0
  67. package/dist/detector/service.js.map +1 -0
  68. package/dist/enforcer/docker-cleaner.d.ts +30 -0
  69. package/dist/enforcer/docker-cleaner.d.ts.map +1 -0
  70. package/dist/enforcer/docker-cleaner.js +163 -0
  71. package/dist/enforcer/docker-cleaner.js.map +1 -0
  72. package/dist/enforcer/file-remover.d.ts +34 -0
  73. package/dist/enforcer/file-remover.d.ts.map +1 -0
  74. package/dist/enforcer/file-remover.js +137 -0
  75. package/dist/enforcer/file-remover.js.map +1 -0
  76. package/dist/enforcer/index.d.ts +33 -0
  77. package/dist/enforcer/index.d.ts.map +1 -0
  78. package/dist/enforcer/index.js +142 -0
  79. package/dist/enforcer/index.js.map +1 -0
  80. package/dist/enforcer/process-killer.d.ts +18 -0
  81. package/dist/enforcer/process-killer.d.ts.map +1 -0
  82. package/dist/enforcer/process-killer.js +80 -0
  83. package/dist/enforcer/process-killer.js.map +1 -0
  84. package/dist/enforcer/service-stopper.d.ts +23 -0
  85. package/dist/enforcer/service-stopper.d.ts.map +1 -0
  86. package/dist/enforcer/service-stopper.js +95 -0
  87. package/dist/enforcer/service-stopper.js.map +1 -0
  88. package/dist/index.d.ts +6 -0
  89. package/dist/index.d.ts.map +1 -0
  90. package/dist/index.js +10 -0
  91. package/dist/index.js.map +1 -0
  92. package/dist/isolator/firewall.d.ts +25 -0
  93. package/dist/isolator/firewall.d.ts.map +1 -0
  94. package/dist/isolator/firewall.js +114 -0
  95. package/dist/isolator/firewall.js.map +1 -0
  96. package/dist/isolator/index.d.ts +63 -0
  97. package/dist/isolator/index.d.ts.map +1 -0
  98. package/dist/isolator/index.js +201 -0
  99. package/dist/isolator/index.js.map +1 -0
  100. package/dist/isolator/lockdown.d.ts +22 -0
  101. package/dist/isolator/lockdown.d.ts.map +1 -0
  102. package/dist/isolator/lockdown.js +401 -0
  103. package/dist/isolator/lockdown.js.map +1 -0
  104. package/dist/isolator/quarantine.d.ts +39 -0
  105. package/dist/isolator/quarantine.d.ts.map +1 -0
  106. package/dist/isolator/quarantine.js +364 -0
  107. package/dist/isolator/quarantine.js.map +1 -0
  108. package/dist/mdm/index.d.ts +93 -0
  109. package/dist/mdm/index.d.ts.map +1 -0
  110. package/dist/mdm/index.js +414 -0
  111. package/dist/mdm/index.js.map +1 -0
  112. package/dist/mdm/intune.d.ts +69 -0
  113. package/dist/mdm/intune.d.ts.map +1 -0
  114. package/dist/mdm/intune.js +409 -0
  115. package/dist/mdm/intune.js.map +1 -0
  116. package/dist/mdm/jamf.d.ts +58 -0
  117. package/dist/mdm/jamf.d.ts.map +1 -0
  118. package/dist/mdm/jamf.js +441 -0
  119. package/dist/mdm/jamf.js.map +1 -0
  120. package/dist/mdm/jumpcloud.d.ts +73 -0
  121. package/dist/mdm/jumpcloud.d.ts.map +1 -0
  122. package/dist/mdm/jumpcloud.js +470 -0
  123. package/dist/mdm/jumpcloud.js.map +1 -0
  124. package/dist/mdm/templates/detect.ps1.d.ts +30 -0
  125. package/dist/mdm/templates/detect.ps1.d.ts.map +1 -0
  126. package/dist/mdm/templates/detect.ps1.js +463 -0
  127. package/dist/mdm/templates/detect.ps1.js.map +1 -0
  128. package/dist/mdm/templates/detect.sh.d.ts +30 -0
  129. package/dist/mdm/templates/detect.sh.d.ts.map +1 -0
  130. package/dist/mdm/templates/detect.sh.js +474 -0
  131. package/dist/mdm/templates/detect.sh.js.map +1 -0
  132. package/dist/mdm/templates/enforce.ps1.d.ts +33 -0
  133. package/dist/mdm/templates/enforce.ps1.d.ts.map +1 -0
  134. package/dist/mdm/templates/enforce.ps1.js +681 -0
  135. package/dist/mdm/templates/enforce.ps1.js.map +1 -0
  136. package/dist/mdm/templates/enforce.sh.d.ts +33 -0
  137. package/dist/mdm/templates/enforce.sh.d.ts.map +1 -0
  138. package/dist/mdm/templates/enforce.sh.js +591 -0
  139. package/dist/mdm/templates/enforce.sh.js.map +1 -0
  140. package/dist/platform/darwin.d.ts +6 -0
  141. package/dist/platform/darwin.d.ts.map +1 -0
  142. package/dist/platform/darwin.js +192 -0
  143. package/dist/platform/darwin.js.map +1 -0
  144. package/dist/platform/index.d.ts +43 -0
  145. package/dist/platform/index.d.ts.map +1 -0
  146. package/dist/platform/index.js +27 -0
  147. package/dist/platform/index.js.map +1 -0
  148. package/dist/platform/linux.d.ts +6 -0
  149. package/dist/platform/linux.d.ts.map +1 -0
  150. package/dist/platform/linux.js +134 -0
  151. package/dist/platform/linux.js.map +1 -0
  152. package/dist/platform/windows.d.ts +6 -0
  153. package/dist/platform/windows.d.ts.map +1 -0
  154. package/dist/platform/windows.js +134 -0
  155. package/dist/platform/windows.js.map +1 -0
  156. package/dist/reporter/console.d.ts +27 -0
  157. package/dist/reporter/console.d.ts.map +1 -0
  158. package/dist/reporter/console.js +431 -0
  159. package/dist/reporter/console.js.map +1 -0
  160. package/dist/reporter/index.d.ts +11 -0
  161. package/dist/reporter/index.d.ts.map +1 -0
  162. package/dist/reporter/index.js +13 -0
  163. package/dist/reporter/index.js.map +1 -0
  164. package/dist/reporter/json.d.ts +61 -0
  165. package/dist/reporter/json.d.ts.map +1 -0
  166. package/dist/reporter/json.js +75 -0
  167. package/dist/reporter/json.js.map +1 -0
  168. package/dist/reporter/webhook.d.ts +57 -0
  169. package/dist/reporter/webhook.d.ts.map +1 -0
  170. package/dist/reporter/webhook.js +230 -0
  171. package/dist/reporter/webhook.js.map +1 -0
  172. package/dist/types/config.d.ts +116 -0
  173. package/dist/types/config.d.ts.map +1 -0
  174. package/dist/types/config.js +6 -0
  175. package/dist/types/config.js.map +1 -0
  176. package/dist/types/detection.d.ts +85 -0
  177. package/dist/types/detection.d.ts.map +1 -0
  178. package/dist/types/detection.js +5 -0
  179. package/dist/types/detection.js.map +1 -0
  180. package/dist/types/enforcement.d.ts +33 -0
  181. package/dist/types/enforcement.d.ts.map +1 -0
  182. package/dist/types/enforcement.js +5 -0
  183. package/dist/types/enforcement.js.map +1 -0
  184. package/dist/types/index.d.ts +8 -0
  185. package/dist/types/index.d.ts.map +1 -0
  186. package/dist/types/index.js +8 -0
  187. package/dist/types/index.js.map +1 -0
  188. package/dist/types/isolation.d.ts +55 -0
  189. package/dist/types/isolation.d.ts.map +1 -0
  190. package/dist/types/isolation.js +5 -0
  191. package/dist/types/isolation.js.map +1 -0
  192. package/dist/utils/exec.d.ts +48 -0
  193. package/dist/utils/exec.d.ts.map +1 -0
  194. package/dist/utils/exec.js +103 -0
  195. package/dist/utils/exec.js.map +1 -0
  196. package/dist/utils/fs.d.ts +34 -0
  197. package/dist/utils/fs.d.ts.map +1 -0
  198. package/dist/utils/fs.js +111 -0
  199. package/dist/utils/fs.js.map +1 -0
  200. package/dist/utils/index.d.ts +7 -0
  201. package/dist/utils/index.d.ts.map +1 -0
  202. package/dist/utils/index.js +7 -0
  203. package/dist/utils/index.js.map +1 -0
  204. package/dist/utils/logger.d.ts +14 -0
  205. package/dist/utils/logger.d.ts.map +1 -0
  206. package/dist/utils/logger.js +48 -0
  207. package/dist/utils/logger.js.map +1 -0
  208. package/docs/intune.md +390 -0
  209. package/docs/jamf.md +400 -0
  210. package/docs/jumpcloud.md +510 -0
  211. package/package.json +65 -0
@@ -0,0 +1,463 @@
1
+ /**
2
+ * PowerShell detection script template for MDM deployment.
3
+ * Targets Windows systems.
4
+ */
5
+ import { VERSION, COMPANY } from '../../branding.js';
6
+ /**
7
+ * Escape a string for safe use in PowerShell scripts.
8
+ * Escapes characters that could enable script injection.
9
+ */
10
+ function escapePowerShellString(str) {
11
+ // Remove null bytes
12
+ let escaped = str.replace(/\0/g, '');
13
+ // Escape backticks (PowerShell escape character)
14
+ escaped = escaped.replace(/`/g, '``');
15
+ // Escape dollar signs (variable interpolation)
16
+ escaped = escaped.replace(/\$/g, '`$');
17
+ // Escape double quotes
18
+ escaped = escaped.replace(/"/g, '`"');
19
+ return escaped;
20
+ }
21
+ /**
22
+ * Validate URL format for MDM scripts.
23
+ */
24
+ function validateMdmUrl(url) {
25
+ try {
26
+ const parsed = new URL(url);
27
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
28
+ throw new Error('Invalid protocol');
29
+ }
30
+ return escapePowerShellString(url);
31
+ }
32
+ catch {
33
+ throw new Error(`Invalid webhook URL: ${url}`);
34
+ }
35
+ }
36
+ /**
37
+ * Generate detection PowerShell script.
38
+ */
39
+ export function generateDetectPowerShellScript(options = {}) {
40
+ const { webhookUrl, webhookToken, gatewayPort = 18789, verbose = false } = options;
41
+ // Validate and sanitize inputs to prevent script injection
42
+ const safeWebhookUrl = webhookUrl ? validateMdmUrl(webhookUrl) : undefined;
43
+ const safeWebhookToken = webhookToken ? escapePowerShellString(webhookToken) : undefined;
44
+ // Validate gateway port
45
+ if (gatewayPort < 1 || gatewayPort > 65535 || !Number.isInteger(gatewayPort)) {
46
+ throw new Error(`Invalid gateway port: ${gatewayPort}`);
47
+ }
48
+ const webhookSection = safeWebhookUrl
49
+ ? `
50
+ # Webhook configuration
51
+ $WebhookUrl = "${safeWebhookUrl}"
52
+ $WebhookToken = "${safeWebhookToken || ''}"
53
+
54
+ function Send-Webhook {
55
+ param(
56
+ [string]$Status,
57
+ [string]$Severity,
58
+ [string]$Details
59
+ )
60
+
61
+ $payload = @{
62
+ event = "openclaw.detection"
63
+ version = "1.0"
64
+ timestamp = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
65
+ status = $Status
66
+ severity = $Severity
67
+ host = @{
68
+ hostname = $env:COMPUTERNAME
69
+ os = "Windows"
70
+ osVersion = [System.Environment]::OSVersion.VersionString
71
+ arch = $env:PROCESSOR_ARCHITECTURE
72
+ user = $env:USERNAME
73
+ domain = $env:USERDOMAIN
74
+ }
75
+ details = $Details
76
+ source = @{
77
+ tool = "nox-openclaw-detector"
78
+ version = "${VERSION}"
79
+ vendor = "${COMPANY}"
80
+ }
81
+ } | ConvertTo-Json -Depth 10
82
+
83
+ try {
84
+ $headers = @{
85
+ "Content-Type" = "application/json"
86
+ }
87
+ if ($WebhookToken) {
88
+ $headers["Authorization"] = "Bearer $WebhookToken"
89
+ }
90
+
91
+ Invoke-RestMethod -Uri $WebhookUrl -Method Post -Headers $headers -Body $payload -TimeoutSec 30 -ErrorAction SilentlyContinue | Out-Null
92
+ } catch {
93
+ # Silently ignore webhook errors
94
+ }
95
+ }
96
+ `
97
+ : '';
98
+ const verboseLog = verbose
99
+ ? `
100
+ function Write-VerboseLog {
101
+ param([string]$Message)
102
+ Write-Host "[DEBUG] $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $Message" -ForegroundColor Gray
103
+ }
104
+ `
105
+ : `
106
+ function Write-VerboseLog {
107
+ param([string]$Message)
108
+ # No-op when not verbose
109
+ }
110
+ `;
111
+ return `<#
112
+ .SYNOPSIS
113
+ Nox OpenClaw Detection Script for Windows
114
+
115
+ .DESCRIPTION
116
+ This script detects OpenClaw AI agent installations on Windows systems.
117
+ Generated by nox-openclaw-detector v${VERSION}
118
+ ${COMPANY} - https://nox.security
119
+
120
+ .OUTPUTS
121
+ Exit Code 0 - OpenClaw NOT detected (clean)
122
+ Exit Code 1 - OpenClaw DETECTED
123
+ Exit Code 2 - Script error
124
+
125
+ .EXAMPLE
126
+ .\\detect-openclaw.ps1
127
+
128
+ .NOTES
129
+ Version: ${VERSION}
130
+ Author: ${COMPANY}
131
+ #>
132
+
133
+ #Requires -Version 5.1
134
+
135
+ [CmdletBinding()]
136
+ param()
137
+
138
+ $ErrorActionPreference = "SilentlyContinue"
139
+
140
+ # Configuration
141
+ $GatewayPort = ${gatewayPort}
142
+ $OpenClawFound = $false
143
+ $DetectionDetails = [System.Collections.ArrayList]::new()
144
+ ${verboseLog}
145
+ ${webhookSection}
146
+
147
+ # Add detection detail
148
+ function Add-Detail {
149
+ param([string]$Detail)
150
+ [void]$script:DetectionDetails.Add($Detail)
151
+ Write-VerboseLog "Detection: $Detail"
152
+ }
153
+
154
+ # Check environment
155
+ function Test-Environment {
156
+ Write-VerboseLog "Running as user: $env:USERNAME"
157
+ Write-VerboseLog "Computer: $env:COMPUTERNAME"
158
+ Write-VerboseLog "OS: $([System.Environment]::OSVersion.VersionString)"
159
+ Write-VerboseLog "Architecture: $env:PROCESSOR_ARCHITECTURE"
160
+ Write-VerboseLog "Running as Admin: $([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)"
161
+ }
162
+
163
+ # Check for CLI binary in common locations
164
+ function Test-CliBinary {
165
+ Write-VerboseLog "Checking for CLI binary..."
166
+
167
+ $cliPaths = @(
168
+ "$env:LOCALAPPDATA\\Programs\\openclaw\\openclaw.exe",
169
+ "$env:ProgramFiles\\OpenClaw\\openclaw.exe",
170
+ "\${env:ProgramFiles(x86)}\\OpenClaw\\openclaw.exe",
171
+ "$env:USERPROFILE\\AppData\\Local\\Programs\\openclaw\\openclaw.exe",
172
+ "$env:USERPROFILE\\.local\\bin\\openclaw.exe"
173
+ )
174
+
175
+ foreach ($cliPath in $cliPaths) {
176
+ if (Test-Path $cliPath) {
177
+ $script:OpenClawFound = $true
178
+
179
+ # Try to get version
180
+ $version = ""
181
+ try {
182
+ $versionOutput = & $cliPath --version 2>$null
183
+ if ($versionOutput) {
184
+ $version = $versionOutput.Trim()
185
+ }
186
+ } catch {}
187
+
188
+ if ($version) {
189
+ Add-Detail "CLI binary found at $cliPath (version: $version)"
190
+ } else {
191
+ Add-Detail "CLI binary found at $cliPath"
192
+ }
193
+ return
194
+ }
195
+ }
196
+
197
+ # Check PATH
198
+ $cliInPath = Get-Command "openclaw" -ErrorAction SilentlyContinue
199
+ if ($cliInPath) {
200
+ $script:OpenClawFound = $true
201
+ Add-Detail "CLI binary found in PATH: $($cliInPath.Source)"
202
+ }
203
+ }
204
+
205
+ # Check for configuration directories
206
+ function Test-ConfigDirectory {
207
+ Write-VerboseLog "Checking for configuration directories..."
208
+
209
+ $configPaths = @(
210
+ "$env:USERPROFILE\\.openclaw",
211
+ "$env:APPDATA\\OpenClaw",
212
+ "$env:LOCALAPPDATA\\OpenClaw"
213
+ )
214
+
215
+ foreach ($configPath in $configPaths) {
216
+ if (Test-Path $configPath -PathType Container) {
217
+ $script:OpenClawFound = $true
218
+
219
+ $configFile = Join-Path $configPath "openclaw.json"
220
+ if (Test-Path $configFile) {
221
+ Add-Detail "Config directory found at $configPath (with config file)"
222
+ } else {
223
+ Add-Detail "Config directory found at $configPath"
224
+ }
225
+ }
226
+ }
227
+
228
+ # Check other user profiles (requires admin)
229
+ if (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
230
+ $userProfiles = Get-ChildItem "C:\\Users" -Directory -ErrorAction SilentlyContinue | Where-Object { $_.Name -notin @("Public", "Default", "Default User", "All Users") }
231
+ foreach ($profile in $userProfiles) {
232
+ $otherConfigPath = Join-Path $profile.FullName ".openclaw"
233
+ if ((Test-Path $otherConfigPath) -and ($otherConfigPath -ne "$env:USERPROFILE\\.openclaw")) {
234
+ $script:OpenClawFound = $true
235
+ Add-Detail "Config directory found for user $($profile.Name): $otherConfigPath"
236
+ }
237
+ }
238
+ }
239
+ }
240
+
241
+ # Check for running processes
242
+ function Test-Processes {
243
+ Write-VerboseLog "Checking for running processes..."
244
+
245
+ $processes = Get-Process -Name "*openclaw*" -ErrorAction SilentlyContinue
246
+ if ($processes) {
247
+ $script:OpenClawFound = $true
248
+ $processInfo = $processes | ForEach-Object { "$($_.Name) (PID: $($_.Id))" }
249
+ Add-Detail "OpenClaw processes running: $($processInfo -join ', ')"
250
+ }
251
+
252
+ # Also check by path/command line
253
+ $wmiProcesses = Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
254
+ Where-Object { $_.CommandLine -like "*openclaw*" -or $_.ExecutablePath -like "*openclaw*" }
255
+
256
+ if ($wmiProcesses) {
257
+ foreach ($proc in $wmiProcesses) {
258
+ if (-not ($processes | Where-Object { $_.Id -eq $proc.ProcessId })) {
259
+ $script:OpenClawFound = $true
260
+ Add-Detail "OpenClaw-related process: $($proc.Name) (PID: $($proc.ProcessId))"
261
+ }
262
+ }
263
+ }
264
+ }
265
+
266
+ # Check for gateway port
267
+ function Test-GatewayPort {
268
+ Write-VerboseLog "Checking for gateway port $GatewayPort..."
269
+
270
+ # Use Test-NetConnection (Windows 8+/Server 2012+)
271
+ try {
272
+ $portTest = Test-NetConnection -ComputerName localhost -Port $GatewayPort -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
273
+ if ($portTest.TcpTestSucceeded) {
274
+ $script:OpenClawFound = $true
275
+ Add-Detail "Gateway port $GatewayPort is listening"
276
+ return
277
+ }
278
+ } catch {}
279
+
280
+ # Fallback: check listening ports via netstat
281
+ try {
282
+ $listening = netstat -an | Select-String ":$GatewayPort.*LISTENING"
283
+ if ($listening) {
284
+ $script:OpenClawFound = $true
285
+ Add-Detail "Gateway port $GatewayPort is listening (via netstat)"
286
+ }
287
+ } catch {}
288
+ }
289
+
290
+ # Check for Windows service
291
+ function Test-WindowsService {
292
+ Write-VerboseLog "Checking for Windows services..."
293
+
294
+ $serviceNames = @(
295
+ "openclaw",
296
+ "OpenClawGateway",
297
+ "bot.molt.gateway"
298
+ )
299
+
300
+ foreach ($serviceName in $serviceNames) {
301
+ $service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
302
+ if ($service) {
303
+ $script:OpenClawFound = $true
304
+ Add-Detail "Windows service found: $($service.Name) (Status: $($service.Status))"
305
+ }
306
+ }
307
+
308
+ # Also search by display name
309
+ $services = Get-Service -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -like "*openclaw*" -or $_.Name -like "*openclaw*" }
310
+ foreach ($service in $services) {
311
+ if ($service.Name -notin $serviceNames) {
312
+ $script:OpenClawFound = $true
313
+ Add-Detail "Windows service found: $($service.DisplayName) ($($service.Name)) - Status: $($service.Status)"
314
+ }
315
+ }
316
+ }
317
+
318
+ # Check for scheduled tasks
319
+ function Test-ScheduledTasks {
320
+ Write-VerboseLog "Checking for scheduled tasks..."
321
+
322
+ try {
323
+ $tasks = Get-ScheduledTask -ErrorAction SilentlyContinue |
324
+ Where-Object { $_.TaskName -like "*openclaw*" -or $_.TaskPath -like "*openclaw*" }
325
+
326
+ foreach ($task in $tasks) {
327
+ $script:OpenClawFound = $true
328
+ Add-Detail "Scheduled task found: $($task.TaskName) (State: $($task.State))"
329
+ }
330
+ } catch {}
331
+ }
332
+
333
+ # Check for registry entries
334
+ function Test-Registry {
335
+ Write-VerboseLog "Checking registry entries..."
336
+
337
+ $registryPaths = @(
338
+ "HKLM:\\SOFTWARE\\OpenClaw",
339
+ "HKCU:\\SOFTWARE\\OpenClaw",
340
+ "HKLM:\\SOFTWARE\\WOW6432Node\\OpenClaw"
341
+ )
342
+
343
+ foreach ($regPath in $registryPaths) {
344
+ if (Test-Path $regPath) {
345
+ $script:OpenClawFound = $true
346
+ Add-Detail "Registry key found: $regPath"
347
+ }
348
+ }
349
+
350
+ # Check Run keys for startup entries
351
+ $runKeys = @(
352
+ "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
353
+ "HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
354
+ )
355
+
356
+ foreach ($runKey in $runKeys) {
357
+ try {
358
+ $entries = Get-ItemProperty $runKey -ErrorAction SilentlyContinue
359
+ $entries.PSObject.Properties | Where-Object { $_.Value -like "*openclaw*" } | ForEach-Object {
360
+ $script:OpenClawFound = $true
361
+ Add-Detail "Startup entry found: $($_.Name) in $runKey"
362
+ }
363
+ } catch {}
364
+ }
365
+ }
366
+
367
+ # Check for Docker containers and images
368
+ function Test-Docker {
369
+ $dockerCmd = Get-Command "docker" -ErrorAction SilentlyContinue
370
+ if (-not $dockerCmd) {
371
+ return
372
+ }
373
+
374
+ Write-VerboseLog "Checking for Docker artifacts..."
375
+
376
+ try {
377
+ # Check running containers
378
+ $containers = docker ps --filter "name=openclaw" --format "{{.Names}}" 2>$null
379
+ if ($containers) {
380
+ $script:OpenClawFound = $true
381
+ Add-Detail "Docker containers running: $($containers -join ', ')"
382
+ }
383
+
384
+ # Check stopped containers
385
+ $stoppedContainers = docker ps -a --filter "name=openclaw" --filter "status=exited" --format "{{.Names}}" 2>$null
386
+ if ($stoppedContainers) {
387
+ $script:OpenClawFound = $true
388
+ Add-Detail "Docker containers (stopped): $($stoppedContainers -join ', ')"
389
+ }
390
+
391
+ # Check images
392
+ $images = docker images --filter "reference=*openclaw*" --format "{{.Repository}}:{{.Tag}}" 2>$null
393
+ if ($images) {
394
+ $script:OpenClawFound = $true
395
+ Add-Detail "Docker images found: $($images -join ', ')"
396
+ }
397
+ } catch {}
398
+ }
399
+
400
+ # Main detection routine
401
+ function Invoke-Detection {
402
+ Test-Environment
403
+
404
+ # Run all detection checks
405
+ Test-CliBinary
406
+ Test-ConfigDirectory
407
+ Test-Processes
408
+ Test-GatewayPort
409
+ Test-WindowsService
410
+ Test-ScheduledTasks
411
+ Test-Registry
412
+ Test-Docker
413
+
414
+ # Compile results
415
+ $detailsString = if ($DetectionDetails.Count -gt 0) { $DetectionDetails -join "; " } else { "" }
416
+
417
+ # Send webhook notification
418
+ ${safeWebhookUrl ? `
419
+ if ($OpenClawFound) {
420
+ Send-Webhook -Status "detected" -Severity "high" -Details $detailsString
421
+ } else {
422
+ Send-Webhook -Status "clean" -Severity "info" -Details "No OpenClaw installation detected"
423
+ }
424
+ ` : ''}
425
+
426
+ # Output results
427
+ if ($OpenClawFound) {
428
+ Write-Host "OPENCLAW DETECTED" -ForegroundColor Red
429
+ Write-Host "Details: $detailsString"
430
+ exit 1
431
+ } else {
432
+ Write-Host "OpenClaw not detected" -ForegroundColor Green
433
+ exit 0
434
+ }
435
+ }
436
+
437
+ # Run main function
438
+ try {
439
+ Invoke-Detection
440
+ } catch {
441
+ Write-Host "Detection error: $_" -ForegroundColor Red
442
+ exit 2
443
+ }
444
+ `;
445
+ }
446
+ /**
447
+ * Get script metadata for documentation.
448
+ */
449
+ export function getDetectPowerShellMetadata() {
450
+ return {
451
+ filename: 'detect-openclaw.ps1',
452
+ extension: '.ps1',
453
+ platform: 'windows',
454
+ description: 'PowerShell detection script for Windows',
455
+ requirements: ['PowerShell 5.1+', 'Windows 8/Server 2012 or later'],
456
+ exitCodes: {
457
+ 0: 'OpenClaw not detected (clean)',
458
+ 1: 'OpenClaw detected',
459
+ 2: 'Script error',
460
+ },
461
+ };
462
+ }
463
+ //# sourceMappingURL=detect.ps1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.ps1.js","sourceRoot":"","sources":["../../../src/mdm/templates/detect.ps1.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Shell detection script template for MDM deployment.
3
+ * Targets macOS and Linux systems.
4
+ */
5
+ export interface DetectShellOptions {
6
+ webhookUrl?: string;
7
+ webhookToken?: string;
8
+ gatewayPort?: number;
9
+ verbose?: boolean;
10
+ }
11
+ /**
12
+ * Generate detection shell script.
13
+ */
14
+ export declare function generateDetectShellScript(options?: DetectShellOptions): string;
15
+ /**
16
+ * Get script metadata for documentation.
17
+ */
18
+ export declare function getDetectShellMetadata(): {
19
+ filename: string;
20
+ extension: string;
21
+ platform: string;
22
+ description: string;
23
+ requirements: string[];
24
+ exitCodes: {
25
+ 0: string;
26
+ 1: string;
27
+ 2: string;
28
+ };
29
+ };
30
+ //# sourceMappingURL=detect.sh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.sh.d.ts","sourceRoot":"","sources":["../../../src/mdm/templates/detect.sh.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAmCD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,GAAE,kBAAuB,GAAG,MAAM,CAoalF;AAED;;GAEG;AACH,wBAAgB,sBAAsB;;;;;;;;;;;EAarC"}