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.
- package/LICENSE +21 -0
- package/README.md +140 -0
- package/bin/nox.js +2 -0
- package/dist/branding.d.ts +39 -0
- package/dist/branding.d.ts.map +1 -0
- package/dist/branding.js +66 -0
- package/dist/branding.js.map +1 -0
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +94 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/export.d.ts +21 -0
- package/dist/commands/export.d.ts.map +1 -0
- package/dist/commands/export.js +616 -0
- package/dist/commands/export.js.map +1 -0
- package/dist/commands/index.d.ts +8 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +8 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/isolate.d.ts +30 -0
- package/dist/commands/isolate.d.ts.map +1 -0
- package/dist/commands/isolate.js +547 -0
- package/dist/commands/isolate.js.map +1 -0
- package/dist/commands/purge.d.ts +22 -0
- package/dist/commands/purge.d.ts.map +1 -0
- package/dist/commands/purge.js +295 -0
- package/dist/commands/purge.js.map +1 -0
- package/dist/commands/scan.d.ts +23 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +155 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/detector/app-bundle.d.ts +13 -0
- package/dist/detector/app-bundle.d.ts.map +1 -0
- package/dist/detector/app-bundle.js +27 -0
- package/dist/detector/app-bundle.js.map +1 -0
- package/dist/detector/cli-binary.d.ts +12 -0
- package/dist/detector/cli-binary.d.ts.map +1 -0
- package/dist/detector/cli-binary.js +66 -0
- package/dist/detector/cli-binary.js.map +1 -0
- package/dist/detector/config.d.ts +21 -0
- package/dist/detector/config.d.ts.map +1 -0
- package/dist/detector/config.js +337 -0
- package/dist/detector/config.js.map +1 -0
- package/dist/detector/detection-config.d.ts +24 -0
- package/dist/detector/detection-config.d.ts.map +1 -0
- package/dist/detector/detection-config.js +242 -0
- package/dist/detector/detection-config.js.map +1 -0
- package/dist/detector/docker.d.ts +10 -0
- package/dist/detector/docker.d.ts.map +1 -0
- package/dist/detector/docker.js +94 -0
- package/dist/detector/docker.js.map +1 -0
- package/dist/detector/index.d.ts +50 -0
- package/dist/detector/index.d.ts.map +1 -0
- package/dist/detector/index.js +155 -0
- package/dist/detector/index.js.map +1 -0
- package/dist/detector/network.d.ts +34 -0
- package/dist/detector/network.d.ts.map +1 -0
- package/dist/detector/network.js +205 -0
- package/dist/detector/network.js.map +1 -0
- package/dist/detector/process.d.ts +16 -0
- package/dist/detector/process.d.ts.map +1 -0
- package/dist/detector/process.js +47 -0
- package/dist/detector/process.js.map +1 -0
- package/dist/detector/service.d.ts +17 -0
- package/dist/detector/service.d.ts.map +1 -0
- package/dist/detector/service.js +51 -0
- package/dist/detector/service.js.map +1 -0
- package/dist/enforcer/docker-cleaner.d.ts +30 -0
- package/dist/enforcer/docker-cleaner.d.ts.map +1 -0
- package/dist/enforcer/docker-cleaner.js +163 -0
- package/dist/enforcer/docker-cleaner.js.map +1 -0
- package/dist/enforcer/file-remover.d.ts +34 -0
- package/dist/enforcer/file-remover.d.ts.map +1 -0
- package/dist/enforcer/file-remover.js +137 -0
- package/dist/enforcer/file-remover.js.map +1 -0
- package/dist/enforcer/index.d.ts +33 -0
- package/dist/enforcer/index.d.ts.map +1 -0
- package/dist/enforcer/index.js +142 -0
- package/dist/enforcer/index.js.map +1 -0
- package/dist/enforcer/process-killer.d.ts +18 -0
- package/dist/enforcer/process-killer.d.ts.map +1 -0
- package/dist/enforcer/process-killer.js +80 -0
- package/dist/enforcer/process-killer.js.map +1 -0
- package/dist/enforcer/service-stopper.d.ts +23 -0
- package/dist/enforcer/service-stopper.d.ts.map +1 -0
- package/dist/enforcer/service-stopper.js +95 -0
- package/dist/enforcer/service-stopper.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/isolator/firewall.d.ts +25 -0
- package/dist/isolator/firewall.d.ts.map +1 -0
- package/dist/isolator/firewall.js +114 -0
- package/dist/isolator/firewall.js.map +1 -0
- package/dist/isolator/index.d.ts +63 -0
- package/dist/isolator/index.d.ts.map +1 -0
- package/dist/isolator/index.js +201 -0
- package/dist/isolator/index.js.map +1 -0
- package/dist/isolator/lockdown.d.ts +22 -0
- package/dist/isolator/lockdown.d.ts.map +1 -0
- package/dist/isolator/lockdown.js +401 -0
- package/dist/isolator/lockdown.js.map +1 -0
- package/dist/isolator/quarantine.d.ts +39 -0
- package/dist/isolator/quarantine.d.ts.map +1 -0
- package/dist/isolator/quarantine.js +364 -0
- package/dist/isolator/quarantine.js.map +1 -0
- package/dist/mdm/index.d.ts +93 -0
- package/dist/mdm/index.d.ts.map +1 -0
- package/dist/mdm/index.js +414 -0
- package/dist/mdm/index.js.map +1 -0
- package/dist/mdm/intune.d.ts +69 -0
- package/dist/mdm/intune.d.ts.map +1 -0
- package/dist/mdm/intune.js +409 -0
- package/dist/mdm/intune.js.map +1 -0
- package/dist/mdm/jamf.d.ts +58 -0
- package/dist/mdm/jamf.d.ts.map +1 -0
- package/dist/mdm/jamf.js +441 -0
- package/dist/mdm/jamf.js.map +1 -0
- package/dist/mdm/jumpcloud.d.ts +73 -0
- package/dist/mdm/jumpcloud.d.ts.map +1 -0
- package/dist/mdm/jumpcloud.js +470 -0
- package/dist/mdm/jumpcloud.js.map +1 -0
- package/dist/mdm/templates/detect.ps1.d.ts +30 -0
- package/dist/mdm/templates/detect.ps1.d.ts.map +1 -0
- package/dist/mdm/templates/detect.ps1.js +463 -0
- package/dist/mdm/templates/detect.ps1.js.map +1 -0
- package/dist/mdm/templates/detect.sh.d.ts +30 -0
- package/dist/mdm/templates/detect.sh.d.ts.map +1 -0
- package/dist/mdm/templates/detect.sh.js +474 -0
- package/dist/mdm/templates/detect.sh.js.map +1 -0
- package/dist/mdm/templates/enforce.ps1.d.ts +33 -0
- package/dist/mdm/templates/enforce.ps1.d.ts.map +1 -0
- package/dist/mdm/templates/enforce.ps1.js +681 -0
- package/dist/mdm/templates/enforce.ps1.js.map +1 -0
- package/dist/mdm/templates/enforce.sh.d.ts +33 -0
- package/dist/mdm/templates/enforce.sh.d.ts.map +1 -0
- package/dist/mdm/templates/enforce.sh.js +591 -0
- package/dist/mdm/templates/enforce.sh.js.map +1 -0
- package/dist/platform/darwin.d.ts +6 -0
- package/dist/platform/darwin.d.ts.map +1 -0
- package/dist/platform/darwin.js +192 -0
- package/dist/platform/darwin.js.map +1 -0
- package/dist/platform/index.d.ts +43 -0
- package/dist/platform/index.d.ts.map +1 -0
- package/dist/platform/index.js +27 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/linux.d.ts +6 -0
- package/dist/platform/linux.d.ts.map +1 -0
- package/dist/platform/linux.js +134 -0
- package/dist/platform/linux.js.map +1 -0
- package/dist/platform/windows.d.ts +6 -0
- package/dist/platform/windows.d.ts.map +1 -0
- package/dist/platform/windows.js +134 -0
- package/dist/platform/windows.js.map +1 -0
- package/dist/reporter/console.d.ts +27 -0
- package/dist/reporter/console.d.ts.map +1 -0
- package/dist/reporter/console.js +431 -0
- package/dist/reporter/console.js.map +1 -0
- package/dist/reporter/index.d.ts +11 -0
- package/dist/reporter/index.d.ts.map +1 -0
- package/dist/reporter/index.js +13 -0
- package/dist/reporter/index.js.map +1 -0
- package/dist/reporter/json.d.ts +61 -0
- package/dist/reporter/json.d.ts.map +1 -0
- package/dist/reporter/json.js +75 -0
- package/dist/reporter/json.js.map +1 -0
- package/dist/reporter/webhook.d.ts +57 -0
- package/dist/reporter/webhook.d.ts.map +1 -0
- package/dist/reporter/webhook.js +230 -0
- package/dist/reporter/webhook.js.map +1 -0
- package/dist/types/config.d.ts +116 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +6 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/detection.d.ts +85 -0
- package/dist/types/detection.d.ts.map +1 -0
- package/dist/types/detection.js +5 -0
- package/dist/types/detection.js.map +1 -0
- package/dist/types/enforcement.d.ts +33 -0
- package/dist/types/enforcement.d.ts.map +1 -0
- package/dist/types/enforcement.js +5 -0
- package/dist/types/enforcement.js.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/isolation.d.ts +55 -0
- package/dist/types/isolation.d.ts.map +1 -0
- package/dist/types/isolation.js +5 -0
- package/dist/types/isolation.js.map +1 -0
- package/dist/utils/exec.d.ts +48 -0
- package/dist/utils/exec.d.ts.map +1 -0
- package/dist/utils/exec.js +103 -0
- package/dist/utils/exec.js.map +1 -0
- package/dist/utils/fs.d.ts +34 -0
- package/dist/utils/fs.d.ts.map +1 -0
- package/dist/utils/fs.js +111 -0
- package/dist/utils/fs.js.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +7 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +48 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/intune.md +390 -0
- package/docs/jamf.md +400 -0
- package/docs/jumpcloud.md +510 -0
- package/package.json +65 -0
|
@@ -0,0 +1,681 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PowerShell enforcement 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 enforcement PowerShell script.
|
|
38
|
+
*/
|
|
39
|
+
export function generateEnforcePowerShellScript(options = {}) {
|
|
40
|
+
const { webhookUrl, webhookToken, gatewayPort = 18789, verbose = false, dryRun = false, quarantine = 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.enforcement"
|
|
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
|
+
actions = $Details
|
|
76
|
+
dryRun = $${dryRun ? 'true' : 'false'}
|
|
77
|
+
source = @{
|
|
78
|
+
tool = "nox-openclaw-detector"
|
|
79
|
+
version = "${VERSION}"
|
|
80
|
+
vendor = "${COMPANY}"
|
|
81
|
+
}
|
|
82
|
+
} | ConvertTo-Json -Depth 10
|
|
83
|
+
|
|
84
|
+
try {
|
|
85
|
+
$headers = @{
|
|
86
|
+
"Content-Type" = "application/json"
|
|
87
|
+
}
|
|
88
|
+
if ($WebhookToken) {
|
|
89
|
+
$headers["Authorization"] = "Bearer $WebhookToken"
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
Invoke-RestMethod -Uri $WebhookUrl -Method Post -Headers $headers -Body $payload -TimeoutSec 30 -ErrorAction SilentlyContinue | Out-Null
|
|
93
|
+
} catch {
|
|
94
|
+
# Silently ignore webhook errors
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
`
|
|
98
|
+
: '';
|
|
99
|
+
const verboseLog = verbose
|
|
100
|
+
? `
|
|
101
|
+
function Write-VerboseLog {
|
|
102
|
+
param([string]$Message)
|
|
103
|
+
Write-Host "[DEBUG] $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') $Message" -ForegroundColor Gray
|
|
104
|
+
}
|
|
105
|
+
`
|
|
106
|
+
: `
|
|
107
|
+
function Write-VerboseLog {
|
|
108
|
+
param([string]$Message)
|
|
109
|
+
# No-op when not verbose
|
|
110
|
+
}
|
|
111
|
+
`;
|
|
112
|
+
const quarantineSection = quarantine
|
|
113
|
+
? `
|
|
114
|
+
# Quarantine configuration
|
|
115
|
+
$QuarantineBase = "C:\\ProgramData\\NoxQuarantine"
|
|
116
|
+
$QuarantineId = "$(Get-Date -Format 'yyyyMMdd_HHmmss')_$env:USERNAME"
|
|
117
|
+
$QuarantineDir = Join-Path $QuarantineBase $QuarantineId
|
|
118
|
+
|
|
119
|
+
function Initialize-Quarantine {
|
|
120
|
+
if ($DryRun) {
|
|
121
|
+
Log-Action "[DRY RUN] Would create quarantine directory: $QuarantineDir"
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
New-Item -ItemType Directory -Path "$QuarantineDir\\binaries" -Force | Out-Null
|
|
126
|
+
New-Item -ItemType Directory -Path "$QuarantineDir\\config" -Force | Out-Null
|
|
127
|
+
New-Item -ItemType Directory -Path "$QuarantineDir\\services" -Force | Out-Null
|
|
128
|
+
New-Item -ItemType Directory -Path "$QuarantineDir\\registry" -Force | Out-Null
|
|
129
|
+
|
|
130
|
+
# Create manifest
|
|
131
|
+
$manifest = @{
|
|
132
|
+
id = $QuarantineId
|
|
133
|
+
timestamp = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
|
|
134
|
+
hostname = $env:COMPUTERNAME
|
|
135
|
+
user = $env:USERNAME
|
|
136
|
+
artifacts = @()
|
|
137
|
+
} | ConvertTo-Json
|
|
138
|
+
|
|
139
|
+
$manifest | Out-File (Join-Path $QuarantineDir "manifest.json") -Encoding UTF8
|
|
140
|
+
|
|
141
|
+
Log-Action "Quarantine directory created: $QuarantineDir"
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function Move-ToQuarantine {
|
|
145
|
+
param(
|
|
146
|
+
[string]$Source,
|
|
147
|
+
[string]$Category
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
$destDir = Join-Path $QuarantineDir $Category
|
|
151
|
+
$destPath = Join-Path $destDir (Split-Path $Source -Leaf)
|
|
152
|
+
|
|
153
|
+
if ($DryRun) {
|
|
154
|
+
Log-Action "[DRY RUN] Would quarantine: $Source -> $destPath"
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (Test-Path $Source) {
|
|
159
|
+
try {
|
|
160
|
+
Move-Item -Path $Source -Destination $destPath -Force -ErrorAction Stop
|
|
161
|
+
Log-Action "Quarantined: $Source -> $destPath"
|
|
162
|
+
} catch {
|
|
163
|
+
# If move fails, try copy and delete
|
|
164
|
+
Copy-Item -Path $Source -Destination $destPath -Recurse -Force -ErrorAction SilentlyContinue
|
|
165
|
+
Remove-Item -Path $Source -Recurse -Force -ErrorAction SilentlyContinue
|
|
166
|
+
Log-Action "Quarantined (via copy): $Source -> $destPath"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
`
|
|
171
|
+
: `
|
|
172
|
+
function Move-ToQuarantine {
|
|
173
|
+
param(
|
|
174
|
+
[string]$Source,
|
|
175
|
+
[string]$Category
|
|
176
|
+
)
|
|
177
|
+
# No quarantine, just remove
|
|
178
|
+
Remove-PathSafely -Path $Source
|
|
179
|
+
}
|
|
180
|
+
`;
|
|
181
|
+
// Build webhook notification section for main function
|
|
182
|
+
const webhookNotificationSection = safeWebhookUrl
|
|
183
|
+
? `
|
|
184
|
+
if ($OpenClawDetected) {
|
|
185
|
+
if ($FailedActions.Count -eq 0) {
|
|
186
|
+
Send-Webhook -Status "success" -Severity "high" -Details $actionsString
|
|
187
|
+
} else {
|
|
188
|
+
Send-Webhook -Status "partial" -Severity "high" -Details $actionsString
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
Send-Webhook -Status "clean" -Severity "info" -Details "No OpenClaw installation found"
|
|
192
|
+
}
|
|
193
|
+
`
|
|
194
|
+
: '';
|
|
195
|
+
const dryRunMessage = dryRun
|
|
196
|
+
? ' Write-Host "[DRY RUN MODE - No changes will be made]" -ForegroundColor Yellow'
|
|
197
|
+
: '';
|
|
198
|
+
const initQuarantine = quarantine ? ' Initialize-Quarantine' : '';
|
|
199
|
+
const quarantineLocation = quarantine
|
|
200
|
+
? ' Write-Host "Quarantine location: $QuarantineDir"'
|
|
201
|
+
: '';
|
|
202
|
+
const quarantineOrRemove = quarantine
|
|
203
|
+
? 'Move-ToQuarantine -Source $installPath -Category "binaries"'
|
|
204
|
+
: 'Remove-PathSafely -Path $installPath';
|
|
205
|
+
const quarantineOrRemoveConfig = quarantine
|
|
206
|
+
? 'Move-ToQuarantine -Source $configPath -Category "config"'
|
|
207
|
+
: 'Remove-PathSafely -Path $configPath';
|
|
208
|
+
const quarantineOrRemoveOther = quarantine
|
|
209
|
+
? 'Move-ToQuarantine -Source $otherConfig -Category "config"'
|
|
210
|
+
: 'Remove-PathSafely -Path $otherConfig';
|
|
211
|
+
const blockPortSection = quarantine
|
|
212
|
+
? `
|
|
213
|
+
# Block gateway port via Windows Firewall
|
|
214
|
+
function Block-GatewayPort {
|
|
215
|
+
Log-Action "Blocking gateway port $GatewayPort..."
|
|
216
|
+
|
|
217
|
+
if ($DryRun) {
|
|
218
|
+
Log-Action "[DRY RUN] Would create firewall rule to block port $GatewayPort"
|
|
219
|
+
return
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
try {
|
|
223
|
+
# Remove existing rule if present
|
|
224
|
+
Remove-NetFirewallRule -DisplayName "Nox Block OpenClaw" -ErrorAction SilentlyContinue
|
|
225
|
+
|
|
226
|
+
# Create new blocking rule
|
|
227
|
+
New-NetFirewallRule -DisplayName "Nox Block OpenClaw" -Direction Outbound -Action Block -Protocol TCP -RemotePort $GatewayPort -ErrorAction Stop | Out-Null
|
|
228
|
+
|
|
229
|
+
Log-Action "Created firewall rule to block port $GatewayPort"
|
|
230
|
+
} catch {
|
|
231
|
+
Log-Failure "Could not create firewall rule: $_"
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
`
|
|
235
|
+
: `
|
|
236
|
+
# Block gateway port (disabled - quarantine mode not enabled)
|
|
237
|
+
function Block-GatewayPort {
|
|
238
|
+
# Port blocking only enabled in quarantine mode
|
|
239
|
+
}
|
|
240
|
+
`;
|
|
241
|
+
return `<#
|
|
242
|
+
.SYNOPSIS
|
|
243
|
+
Nox OpenClaw Enforcement Script for Windows
|
|
244
|
+
|
|
245
|
+
.DESCRIPTION
|
|
246
|
+
This script removes OpenClaw AI agent installations from Windows systems.
|
|
247
|
+
Generated by nox-openclaw-detector v${VERSION}
|
|
248
|
+
${COMPANY} - https://nox.security
|
|
249
|
+
|
|
250
|
+
WARNING: This script will remove OpenClaw installations!
|
|
251
|
+
Run as Administrator for full enforcement capabilities.
|
|
252
|
+
|
|
253
|
+
.OUTPUTS
|
|
254
|
+
Exit Code 0 - Enforcement successful
|
|
255
|
+
Exit Code 1 - Enforcement partially failed
|
|
256
|
+
Exit Code 2 - Script error
|
|
257
|
+
Exit Code 3 - Nothing to enforce (clean system)
|
|
258
|
+
|
|
259
|
+
.EXAMPLE
|
|
260
|
+
.\\enforce-openclaw.ps1
|
|
261
|
+
|
|
262
|
+
.NOTES
|
|
263
|
+
Version: ${VERSION}
|
|
264
|
+
Author: ${COMPANY}
|
|
265
|
+
#>
|
|
266
|
+
|
|
267
|
+
#Requires -Version 5.1
|
|
268
|
+
#Requires -RunAsAdministrator
|
|
269
|
+
|
|
270
|
+
[CmdletBinding()]
|
|
271
|
+
param()
|
|
272
|
+
|
|
273
|
+
$ErrorActionPreference = "SilentlyContinue"
|
|
274
|
+
|
|
275
|
+
# Configuration
|
|
276
|
+
$GatewayPort = ${gatewayPort}
|
|
277
|
+
$DryRun = $${dryRun ? 'true' : 'false'}
|
|
278
|
+
$OpenClawDetected = $false
|
|
279
|
+
$EnforcementActions = [System.Collections.ArrayList]::new()
|
|
280
|
+
$FailedActions = [System.Collections.ArrayList]::new()
|
|
281
|
+
${verboseLog}
|
|
282
|
+
${webhookSection}
|
|
283
|
+
${quarantineSection}
|
|
284
|
+
|
|
285
|
+
# Log enforcement action
|
|
286
|
+
function Log-Action {
|
|
287
|
+
param([string]$Message)
|
|
288
|
+
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
|
|
289
|
+
Write-Host "[$timestamp] $Message"
|
|
290
|
+
[void]$script:EnforcementActions.Add($Message)
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
# Log failed action
|
|
294
|
+
function Log-Failure {
|
|
295
|
+
param([string]$Message)
|
|
296
|
+
$timestamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
|
|
297
|
+
Write-Host "[$timestamp] FAILED: $Message" -ForegroundColor Red
|
|
298
|
+
[void]$script:FailedActions.Add($Message)
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
# Remove file or directory safely
|
|
302
|
+
function Remove-PathSafely {
|
|
303
|
+
param([string]$Path)
|
|
304
|
+
|
|
305
|
+
if (-not (Test-Path $Path)) {
|
|
306
|
+
return $true
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
$script:OpenClawDetected = $true
|
|
310
|
+
|
|
311
|
+
if ($DryRun) {
|
|
312
|
+
Log-Action "[DRY RUN] Would remove: $Path"
|
|
313
|
+
return $true
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
try {
|
|
317
|
+
Remove-Item -Path $Path -Recurse -Force -ErrorAction Stop
|
|
318
|
+
Log-Action "Removed: $Path"
|
|
319
|
+
return $true
|
|
320
|
+
} catch {
|
|
321
|
+
Log-Failure "Could not remove: $Path - $_"
|
|
322
|
+
return $false
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
# Check if running as Administrator
|
|
327
|
+
function Test-Administrator {
|
|
328
|
+
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
|
|
329
|
+
if (-not $isAdmin) {
|
|
330
|
+
Write-Host "Warning: Not running as Administrator. Some enforcement actions may fail." -ForegroundColor Yellow
|
|
331
|
+
Write-Host "For complete enforcement, run PowerShell as Administrator." -ForegroundColor Yellow
|
|
332
|
+
Write-Host ""
|
|
333
|
+
}
|
|
334
|
+
return $isAdmin
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
# Kill OpenClaw processes
|
|
338
|
+
function Stop-OpenClawProcesses {
|
|
339
|
+
Log-Action "Checking for OpenClaw processes..."
|
|
340
|
+
|
|
341
|
+
$processes = Get-Process -Name "*openclaw*" -ErrorAction SilentlyContinue
|
|
342
|
+
|
|
343
|
+
# Also check by command line
|
|
344
|
+
$wmiProcesses = Get-CimInstance Win32_Process |
|
|
345
|
+
Where-Object { $_.CommandLine -like "*openclaw*" -or $_.ExecutablePath -like "*openclaw*" }
|
|
346
|
+
|
|
347
|
+
$allPids = @()
|
|
348
|
+
if ($processes) { $allPids += $processes.Id }
|
|
349
|
+
if ($wmiProcesses) { $allPids += $wmiProcesses.ProcessId }
|
|
350
|
+
$allPids = $allPids | Select-Object -Unique
|
|
351
|
+
|
|
352
|
+
if ($allPids.Count -gt 0) {
|
|
353
|
+
$script:OpenClawDetected = $true
|
|
354
|
+
|
|
355
|
+
if ($DryRun) {
|
|
356
|
+
Log-Action "[DRY RUN] Would kill processes: $($allPids -join ', ')"
|
|
357
|
+
return
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
foreach ($pid in $allPids) {
|
|
361
|
+
try {
|
|
362
|
+
Stop-Process -Id $pid -Force -ErrorAction Stop
|
|
363
|
+
Log-Action "Killed process: $pid"
|
|
364
|
+
} catch {
|
|
365
|
+
Log-Failure "Could not kill process: $pid"
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
} else {
|
|
369
|
+
Write-VerboseLog "No OpenClaw processes found"
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
# Stop and remove Windows services
|
|
374
|
+
function Remove-OpenClawServices {
|
|
375
|
+
Log-Action "Checking for Windows services..."
|
|
376
|
+
|
|
377
|
+
$serviceNames = @(
|
|
378
|
+
"openclaw",
|
|
379
|
+
"OpenClawGateway",
|
|
380
|
+
"bot.molt.gateway"
|
|
381
|
+
)
|
|
382
|
+
|
|
383
|
+
# Find by name patterns
|
|
384
|
+
$services = Get-Service -ErrorAction SilentlyContinue |
|
|
385
|
+
Where-Object { $_.DisplayName -like "*openclaw*" -or $_.Name -like "*openclaw*" -or $serviceNames -contains $_.Name }
|
|
386
|
+
|
|
387
|
+
foreach ($service in $services) {
|
|
388
|
+
$script:OpenClawDetected = $true
|
|
389
|
+
|
|
390
|
+
if ($DryRun) {
|
|
391
|
+
Log-Action "[DRY RUN] Would stop and remove service: $($service.Name)"
|
|
392
|
+
continue
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
try {
|
|
396
|
+
# Stop the service
|
|
397
|
+
if ($service.Status -ne 'Stopped') {
|
|
398
|
+
Stop-Service -Name $service.Name -Force -ErrorAction Stop
|
|
399
|
+
Log-Action "Stopped service: $($service.Name)"
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
# Delete the service
|
|
403
|
+
$result = sc.exe delete $service.Name 2>&1
|
|
404
|
+
if ($LASTEXITCODE -eq 0) {
|
|
405
|
+
Log-Action "Removed service: $($service.Name)"
|
|
406
|
+
} else {
|
|
407
|
+
Log-Failure "Could not remove service: $($service.Name)"
|
|
408
|
+
}
|
|
409
|
+
} catch {
|
|
410
|
+
Log-Failure "Error handling service $($service.Name): $_"
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
# Remove CLI binaries and installation directories
|
|
416
|
+
function Remove-OpenClawBinaries {
|
|
417
|
+
Log-Action "Checking for CLI binaries..."
|
|
418
|
+
|
|
419
|
+
$installPaths = @(
|
|
420
|
+
"$env:LOCALAPPDATA\\Programs\\openclaw",
|
|
421
|
+
"$env:ProgramFiles\\OpenClaw",
|
|
422
|
+
"\${env:ProgramFiles(x86)}\\OpenClaw",
|
|
423
|
+
"$env:USERPROFILE\\AppData\\Local\\Programs\\openclaw",
|
|
424
|
+
"$env:USERPROFILE\\.local\\bin\\openclaw.exe"
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
foreach ($installPath in $installPaths) {
|
|
428
|
+
if (Test-Path $installPath) {
|
|
429
|
+
$script:OpenClawDetected = $true
|
|
430
|
+
${quarantineOrRemove}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
# Remove configuration directories
|
|
436
|
+
function Remove-OpenClawConfig {
|
|
437
|
+
Log-Action "Checking for configuration directories..."
|
|
438
|
+
|
|
439
|
+
$configPaths = @(
|
|
440
|
+
"$env:USERPROFILE\\.openclaw",
|
|
441
|
+
"$env:APPDATA\\OpenClaw",
|
|
442
|
+
"$env:LOCALAPPDATA\\OpenClaw"
|
|
443
|
+
)
|
|
444
|
+
|
|
445
|
+
foreach ($configPath in $configPaths) {
|
|
446
|
+
if (Test-Path $configPath) {
|
|
447
|
+
$script:OpenClawDetected = $true
|
|
448
|
+
${quarantineOrRemoveConfig}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
# Check other user profiles (requires admin)
|
|
453
|
+
if (([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
|
454
|
+
$userProfiles = Get-ChildItem "C:\\Users" -Directory -ErrorAction SilentlyContinue |
|
|
455
|
+
Where-Object { $_.Name -notin @("Public", "Default", "Default User", "All Users") }
|
|
456
|
+
|
|
457
|
+
foreach ($profile in $userProfiles) {
|
|
458
|
+
$otherConfigPaths = @(
|
|
459
|
+
(Join-Path $profile.FullName ".openclaw"),
|
|
460
|
+
(Join-Path $profile.FullName "AppData\\Roaming\\OpenClaw"),
|
|
461
|
+
(Join-Path $profile.FullName "AppData\\Local\\OpenClaw")
|
|
462
|
+
)
|
|
463
|
+
|
|
464
|
+
foreach ($otherConfig in $otherConfigPaths) {
|
|
465
|
+
if ((Test-Path $otherConfig) -and ($otherConfig -ne "$env:USERPROFILE\\.openclaw")) {
|
|
466
|
+
$script:OpenClawDetected = $true
|
|
467
|
+
${quarantineOrRemoveOther}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
# Remove scheduled tasks
|
|
475
|
+
function Remove-OpenClawScheduledTasks {
|
|
476
|
+
Log-Action "Checking for scheduled tasks..."
|
|
477
|
+
|
|
478
|
+
try {
|
|
479
|
+
$tasks = Get-ScheduledTask -ErrorAction SilentlyContinue |
|
|
480
|
+
Where-Object { $_.TaskName -like "*openclaw*" -or $_.TaskPath -like "*openclaw*" }
|
|
481
|
+
|
|
482
|
+
foreach ($task in $tasks) {
|
|
483
|
+
$script:OpenClawDetected = $true
|
|
484
|
+
|
|
485
|
+
if ($DryRun) {
|
|
486
|
+
Log-Action "[DRY RUN] Would remove scheduled task: $($task.TaskName)"
|
|
487
|
+
continue
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
try {
|
|
491
|
+
Unregister-ScheduledTask -TaskName $task.TaskName -Confirm:$false -ErrorAction Stop
|
|
492
|
+
Log-Action "Removed scheduled task: $($task.TaskName)"
|
|
493
|
+
} catch {
|
|
494
|
+
Log-Failure "Could not remove scheduled task: $($task.TaskName)"
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
} catch {
|
|
498
|
+
Write-VerboseLog "Error checking scheduled tasks: $_"
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
# Remove registry entries
|
|
503
|
+
function Remove-OpenClawRegistry {
|
|
504
|
+
Log-Action "Checking for registry entries..."
|
|
505
|
+
|
|
506
|
+
$registryPaths = @(
|
|
507
|
+
"HKLM:\\SOFTWARE\\OpenClaw",
|
|
508
|
+
"HKCU:\\SOFTWARE\\OpenClaw",
|
|
509
|
+
"HKLM:\\SOFTWARE\\WOW6432Node\\OpenClaw"
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
foreach ($regPath in $registryPaths) {
|
|
513
|
+
if (Test-Path $regPath) {
|
|
514
|
+
$script:OpenClawDetected = $true
|
|
515
|
+
|
|
516
|
+
if ($DryRun) {
|
|
517
|
+
Log-Action "[DRY RUN] Would remove registry key: $regPath"
|
|
518
|
+
continue
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
try {
|
|
522
|
+
Remove-Item -Path $regPath -Recurse -Force -ErrorAction Stop
|
|
523
|
+
Log-Action "Removed registry key: $regPath"
|
|
524
|
+
} catch {
|
|
525
|
+
Log-Failure "Could not remove registry key: $regPath"
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
# Remove startup entries
|
|
531
|
+
$runKeys = @(
|
|
532
|
+
"HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
|
|
533
|
+
"HKCU:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
foreach ($runKey in $runKeys) {
|
|
537
|
+
try {
|
|
538
|
+
$entries = Get-ItemProperty $runKey -ErrorAction SilentlyContinue
|
|
539
|
+
$entries.PSObject.Properties | Where-Object { $_.Value -like "*openclaw*" } | ForEach-Object {
|
|
540
|
+
$script:OpenClawDetected = $true
|
|
541
|
+
|
|
542
|
+
if ($DryRun) {
|
|
543
|
+
Log-Action "[DRY RUN] Would remove startup entry: $($_.Name) from $runKey"
|
|
544
|
+
return
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
try {
|
|
548
|
+
Remove-ItemProperty -Path $runKey -Name $_.Name -Force -ErrorAction Stop
|
|
549
|
+
Log-Action "Removed startup entry: $($_.Name)"
|
|
550
|
+
} catch {
|
|
551
|
+
Log-Failure "Could not remove startup entry: $($_.Name)"
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
} catch {}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
# Clean Docker artifacts
|
|
559
|
+
function Remove-OpenClawDocker {
|
|
560
|
+
$dockerCmd = Get-Command "docker" -ErrorAction SilentlyContinue
|
|
561
|
+
if (-not $dockerCmd) {
|
|
562
|
+
return
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
Log-Action "Checking for Docker artifacts..."
|
|
566
|
+
|
|
567
|
+
try {
|
|
568
|
+
# Stop and remove containers
|
|
569
|
+
$containers = docker ps -a --filter "name=openclaw" --format "{{.ID}}" 2>$null
|
|
570
|
+
if ($containers) {
|
|
571
|
+
$script:OpenClawDetected = $true
|
|
572
|
+
|
|
573
|
+
if ($DryRun) {
|
|
574
|
+
Log-Action "[DRY RUN] Would remove Docker containers: $($containers -join ', ')"
|
|
575
|
+
} else {
|
|
576
|
+
foreach ($container in $containers) {
|
|
577
|
+
docker stop $container 2>$null
|
|
578
|
+
docker rm -f $container 2>$null
|
|
579
|
+
Log-Action "Removed Docker container: $container"
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
# Remove images
|
|
585
|
+
$images = docker images --filter "reference=*openclaw*" --format "{{.ID}}" 2>$null
|
|
586
|
+
if ($images) {
|
|
587
|
+
$script:OpenClawDetected = $true
|
|
588
|
+
|
|
589
|
+
if ($DryRun) {
|
|
590
|
+
Log-Action "[DRY RUN] Would remove Docker images: $($images -join ', ')"
|
|
591
|
+
} else {
|
|
592
|
+
foreach ($image in $images) {
|
|
593
|
+
docker rmi -f $image 2>$null
|
|
594
|
+
Log-Action "Removed Docker image: $image"
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
} catch {
|
|
599
|
+
Write-VerboseLog "Error cleaning Docker artifacts: $_"
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
${blockPortSection}
|
|
603
|
+
|
|
604
|
+
# Main enforcement routine
|
|
605
|
+
function Invoke-Enforcement {
|
|
606
|
+
Write-Host "==============================================" -ForegroundColor Cyan
|
|
607
|
+
Write-Host "Nox OpenClaw Enforcement" -ForegroundColor Cyan
|
|
608
|
+
Write-Host "==============================================" -ForegroundColor Cyan
|
|
609
|
+
${dryRunMessage}
|
|
610
|
+
Write-Host ""
|
|
611
|
+
|
|
612
|
+
Test-Administrator | Out-Null
|
|
613
|
+
|
|
614
|
+
${initQuarantine}
|
|
615
|
+
|
|
616
|
+
# Execute enforcement actions in order
|
|
617
|
+
Stop-OpenClawProcesses
|
|
618
|
+
Remove-OpenClawServices
|
|
619
|
+
Remove-OpenClawBinaries
|
|
620
|
+
Remove-OpenClawConfig
|
|
621
|
+
Remove-OpenClawScheduledTasks
|
|
622
|
+
Remove-OpenClawRegistry
|
|
623
|
+
Remove-OpenClawDocker
|
|
624
|
+
Block-GatewayPort
|
|
625
|
+
|
|
626
|
+
# Compile results
|
|
627
|
+
$actionsString = if ($EnforcementActions.Count -gt 0) { $EnforcementActions -join "; " } else { "" }
|
|
628
|
+
|
|
629
|
+
Write-Host ""
|
|
630
|
+
Write-Host "==============================================" -ForegroundColor Cyan
|
|
631
|
+
Write-Host "Enforcement Summary" -ForegroundColor Cyan
|
|
632
|
+
Write-Host "==============================================" -ForegroundColor Cyan
|
|
633
|
+
|
|
634
|
+
# Send webhook notification
|
|
635
|
+
${webhookNotificationSection}
|
|
636
|
+
|
|
637
|
+
if (-not $OpenClawDetected) {
|
|
638
|
+
Write-Host "No OpenClaw installation detected. System is clean." -ForegroundColor Green
|
|
639
|
+
exit 3
|
|
640
|
+
} elseif ($FailedActions.Count -gt 0) {
|
|
641
|
+
Write-Host "Enforcement partially completed with $($FailedActions.Count) failures:" -ForegroundColor Yellow
|
|
642
|
+
foreach ($failure in $FailedActions) {
|
|
643
|
+
Write-Host " - $failure" -ForegroundColor Yellow
|
|
644
|
+
}
|
|
645
|
+
exit 1
|
|
646
|
+
} else {
|
|
647
|
+
Write-Host "Enforcement completed successfully." -ForegroundColor Green
|
|
648
|
+
Write-Host "Actions taken: $($EnforcementActions.Count)"
|
|
649
|
+
${quarantineLocation}
|
|
650
|
+
exit 0
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
# Run main function
|
|
655
|
+
try {
|
|
656
|
+
Invoke-Enforcement
|
|
657
|
+
} catch {
|
|
658
|
+
Write-Host "Enforcement error: $_" -ForegroundColor Red
|
|
659
|
+
exit 2
|
|
660
|
+
}
|
|
661
|
+
`;
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Get script metadata for documentation.
|
|
665
|
+
*/
|
|
666
|
+
export function getEnforcePowerShellMetadata() {
|
|
667
|
+
return {
|
|
668
|
+
filename: 'enforce-openclaw.ps1',
|
|
669
|
+
extension: '.ps1',
|
|
670
|
+
platform: 'windows',
|
|
671
|
+
description: 'PowerShell enforcement script for Windows',
|
|
672
|
+
requirements: ['PowerShell 5.1+', 'Administrator privileges', 'Windows 8/Server 2012 or later'],
|
|
673
|
+
exitCodes: {
|
|
674
|
+
0: 'Enforcement successful',
|
|
675
|
+
1: 'Enforcement partially failed',
|
|
676
|
+
2: 'Script error',
|
|
677
|
+
3: 'Nothing to enforce (clean system)',
|
|
678
|
+
},
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
//# sourceMappingURL=enforce.ps1.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enforce.ps1.js","sourceRoot":"","sources":["../../../src/mdm/templates/enforce.ps1.ts"],"names":[],"mappings":"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"}
|