Skip to content

Commit 3ca2e53

Browse files
committed
docs/fix: remove domain blocking hacks on macOS and add dashboard warning
1 parent 523aa07 commit 3ca2e53

File tree

8 files changed

+43
-26
lines changed

8 files changed

+43
-26
lines changed

builder/compiler.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ def compile_macos_seatbelt(rules: dict[str, Any]) -> str:
146146
)
147147

148148
# Seatbelt does not support hostname-based filters; domain blocking is
149-
# enforced at the application layer by log_tailer.py / openclaw wrapper.
149+
# currently unsupported on macOS (no kernel-level hostname enforcement).
150150
blocked_domains = rules.get("blocked_domains", {})
151151
if blocked_domains:
152-
lines.append(";;; --- Blocked domains (enforced by log_tailer.py, not kernel-level) ---")
152+
lines.append(";;; --- Blocked domains (Unsupported on macOS) ---")
153153
for rule_id, domain in blocked_domains.items():
154154
lines.append(f';;; [{rule_id}] {domain}')
155155

deploy/dashboard/app.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,22 @@ def _trigger_enforcement():
205205
def _run():
206206
if platform.system() == "Darwin":
207207
# Re-generate the Seatbelt profile and notify user
208-
apply_script = os.path.join(os.path.dirname(__file__), "..", "apply_macos_policy.py")
209-
if os.path.exists(apply_script):
208+
# Try both the development layout and the installed flat layout
209+
base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
210+
candidates = [
211+
os.path.join(base_dir, "macos", "apply_macos_policy.py"),
212+
os.path.join(base_dir, "apply_macos_policy.py"),
213+
]
214+
apply_script = None
215+
for c in candidates:
216+
if os.path.exists(c):
217+
apply_script = c
218+
break
219+
220+
if apply_script:
210221
try:
211222
subprocess.run(["python3", apply_script], check=True, capture_output=True)
212-
logger.info("Triggered macOS policy applicator")
223+
logger.info("Triggered macOS policy applicator: %s", apply_script)
213224
except subprocess.CalledProcessError as e:
214225
logger.error("Failed to apply macOS policy: %s", e.stderr.decode() if e.stderr else str(e))
215226
else:

deploy/dashboard/templates/index.html

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1286,7 +1286,14 @@ <h2 id="modalTitle">Add Custom Rule</h2>
12861286
d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z">
12871287
</path>
12881288
</svg></div>
1289-
<div class="type-name">Domain/IP</div>
1289+
<div class="type-name">Domain/IP <svg width="14" height="14" viewBox="0 0 24 24" fill="none"
1290+
stroke="currentColor" stroke-width="2"
1291+
style="display:inline; margin-left:4px; opacity:0.6;"
1292+
title="Supported on Linux (eBPF). Not supported on macOS kernel.">
1293+
<circle cx="12" cy="12" r="10"></circle>
1294+
<line x1="12" y1="16" x2="12" y2="12"></line>
1295+
<line x1="12" y1="8" x2="12.01" y2="8"></line>
1296+
</svg></div>
12901297
</div>
12911298
<div class="type-card" data-type="hash" onclick="selectType('hash')">
12921299
<div class="type-icon"><svg width="24" height="24" viewBox="0 0 24 24" fill="none"
@@ -1322,6 +1329,20 @@ <h2 id="modalTitle">Add Custom Rule</h2>
13221329
<div class="form-hint" id="ruleHint">Select a rule type above</div>
13231330
<div class="form-error" id="ruleError"></div>
13241331
</div>
1332+
<div class="form-group" id="macDomainWarning" style="display:none; margin-top:12px;">
1333+
<div
1334+
style="background: rgba(255, 171, 0, 0.1); border-left: 4px solid #ffab00; padding: 12px; border-radius: 4px; display:flex; gap:12px; align-items:center;">
1335+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#ffab00" stroke-width="2">
1336+
<circle cx="12" cy="12" r="10"></circle>
1337+
<line x1="12" y1="8" x2="12" y2="12"></line>
1338+
<line x1="12" y1="16" x2="12.01" y2="16"></line>
1339+
</svg>
1340+
<div style="color: #ffab00; font-size: 13px; font-weight: 500;">
1341+
Domain blocking is currently only supported on Linux (eBPF). macOS Seatbelt sandboxing
1342+
limitation prevents kernel-level hostname enforcement.
1343+
</div>
1344+
</div>
1345+
</div>
13251346
<div class="form-group">
13261347
<label class="form-label" for="rulePlatform">Platform</label>
13271348
<select class="form-select" id="rulePlatform">
@@ -1627,6 +1648,7 @@ <h2 id="modalTitle">Add Custom Rule</h2>
16271648
const sel = document.querySelector(`.type-card[data-type="${rule.type}"]`);
16281649
if (sel) { sel.style.opacity = '1'; }
16291650
document.getElementById('ruleHint').textContent = TYPE_HINTS[rule.type] || '';
1651+
document.getElementById('macDomainWarning').style.display = (rule.type === 'domain') ? 'block' : 'none';
16301652
document.getElementById('ruleModal').classList.add('open');
16311653
}
16321654

@@ -1639,6 +1661,7 @@ <h2 id="modalTitle">Add Custom Rule</h2>
16391661
document.getElementById('ruleHint').textContent = TYPE_HINTS[type] || '';
16401662
document.getElementById('ruleError').classList.remove('visible');
16411663
document.getElementById('ruleValue').placeholder = TYPE_HINTS[type] || 'Enter value...';
1664+
document.getElementById('macDomainWarning').style.display = (type === 'domain') ? 'block' : 'none';
16421665
document.getElementById('ruleValue').focus();
16431666
}
16441667

deploy/install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ INNER
359359
if [ ! -e "$path" ]; then return 0; fi
360360
log "Installing ClawEDR wrapper at $path"
361361
rm -f "$path"
362-
cat > "$path" <<'WRAPPER'
362+
cat > "$path" <<'WRAPPER'
363363
#!/usr/bin/env sh
364364
# openclaw — ClawEDR Zero-Habit Hijack wrapper (macOS)
365365
CLAWEDR_SB="/usr/local/share/clawedr/clawedr.sb"

deploy/linux/monitor.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,8 +413,6 @@ def apply_policy(policy: dict) -> None:
413413

414414
if rtype == "executable":
415415
policy.setdefault("blocked_executables", {})[rid] = val
416-
elif rtype == "domain":
417-
policy.setdefault("blocked_domains", {})[rid] = val
418416
elif rtype == "hash":
419417
policy.setdefault("malicious_hashes", {})[rid] = val.removeprefix("sha256:")
420418
elif rtype == "path":

deploy/macos/apply_macos_policy.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,6 @@ def generate_seatbelt(policy: dict, exempted: set[str]) -> str:
8787
f'(deny process-exec (literal "{prefix}{name}"))'
8888
)
8989

90-
# ── Blocked domains (comment-only, enforced by log_tailer.py) ──
91-
blocked_domains = policy.get("blocked_domains", {})
92-
if blocked_domains:
93-
lines.append(";;; --- Blocked domains (enforced by log_tailer.py, not kernel-level) ---")
94-
for rule_id, domain in blocked_domains.items():
95-
if rule_id in exempted:
96-
lines.append(f";;; [{rule_id}] EXEMPTED by user: {domain}")
97-
else:
98-
lines.append(f";;; [{rule_id}] {domain}")
99-
10090
# ── Custom deny rules ──
10191
custom_rules = policy.get("deny_rules", {}).get("macos", {})
10292
if custom_rules:
@@ -171,8 +161,6 @@ def main() -> int:
171161

172162
if rtype == "executable":
173163
policy.setdefault("blocked_executables", {})[rid] = val
174-
elif rtype == "domain":
175-
policy.setdefault("blocked_domains", {})[rid] = val
176164
elif rtype == "path":
177165
policy.setdefault("blocked_paths", {}).setdefault("macos", {})[rid] = val
178166
elif rtype == "argument":

deploy/macos/clawedr.sb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@
224224
(deny process-exec (literal "/usr/local/bin/ptrace"))
225225
(deny process-exec (literal "/opt/homebrew/bin/ptrace"))
226226
(deny process-exec (literal "/opt/local/bin/ptrace"))
227-
;;; --- Blocked domains (enforced by log_tailer.py, not kernel-level) ---
227+
;;; --- Blocked domains (Unsupported on macOS) ---
228228
;;; [DOM-001] pool.supportxmr.com
229229
;;; [DOM-002] pool.minexmr.com
230230
;;; [DOM-003] xmr.pool.minergate.com

deploy/macos/log_tailer.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,6 @@ def _load_policy_rule_index() -> dict:
6464

6565
if rtype == "executable":
6666
policy.setdefault("blocked_executables", {})[rid] = val
67-
elif rtype == "domain":
68-
policy.setdefault("blocked_domains", {})[rid] = val
69-
elif rtype == "path":
70-
policy.setdefault("blocked_paths", {}).setdefault("macos", {})[rid] = val
7167
elif rtype == "argument":
7268
policy.setdefault("deny_rules", {}).setdefault("macos", {})[rid] = val
7369

@@ -146,6 +142,7 @@ def tail_sandbox_log():
146142
if isinstance(directive, str) and target in directive:
147143
rule_id = rid
148144
break
145+
149146

150147
# Discard system-wide sandbox noise that isn't ours
151148
if not rule_id:

0 commit comments

Comments
 (0)