Hard-deny: PowerShell patterns + drift-proof the label list
Four new compiled-in hard-deny rules covering PowerShell + cmd.exe catastrophic patterns (mirror of the POSIX 10): - Remove-Item / del / rd / ri / rm / erase / rmdir targeting C:\ or user home / appdata - Format-Volume / Clear-Disk with any flag (= an invocation, not a Get-Help lookup) - iwr | iex pipe form (PowerShell web-to-execute) - iex (irm ...) parenthesized form Universal application — no shell-aware scoping yet. PS cmdlet identifiers are distinctive enough that bash false-positives are vanishingly unlikely. Shell-aware policy scoping remains a known follow-up. Drift-proof the "Always blocked" label list: backend now exposes hard_deny_rules() via a new mcp_hard_deny_labels Tauri command, and PolicyTab loads it at mount instead of hardcoding the list. Avoids the 11→15 manual sync that would have been needed (and that had already drifted twice this week). cargo test --lib: 138 passed; 0 failed (118 prior + 20 new fuzz cases for rules 11-14; hard_deny_rules_count bumped 10 → 14). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
f3ab54252e
commit
5b970f8b48
6 changed files with 264 additions and 16 deletions
|
|
@ -1,18 +1,10 @@
|
|||
import { useEffect, useState, useRef } from "react";
|
||||
import { mcpPolicyLoad, mcpPolicySave, type McpPolicy } from "../ipc";
|
||||
|
||||
const HARD_DENY_LABELS = [
|
||||
"rm -rf /",
|
||||
"rm -rf ~",
|
||||
"rm -rf /*",
|
||||
"fork bomb",
|
||||
"mkfs on device",
|
||||
"dd to raw disk",
|
||||
"overwrite system auth file",
|
||||
"pipe to shell from network",
|
||||
"chmod -R 777 /",
|
||||
"find / -delete",
|
||||
];
|
||||
import {
|
||||
mcpHardDenyLabels,
|
||||
mcpPolicyLoad,
|
||||
mcpPolicySave,
|
||||
type McpPolicy,
|
||||
} from "../ipc";
|
||||
|
||||
type Bucket = "deny" | "ask" | "allow";
|
||||
|
||||
|
|
@ -89,12 +81,14 @@ function RuleList({ bucket, rules, onRemove, onAdd }: RuleListProps) {
|
|||
|
||||
export default function PolicyTab() {
|
||||
const [policy, setPolicy] = useState<McpPolicy | null>(null);
|
||||
const [hardDenyLabels, setHardDenyLabels] = useState<string[]>([]);
|
||||
const [dirty, setDirty] = useState(false);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [saveError, setSaveError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
void mcpPolicyLoad().then(setPolicy);
|
||||
void mcpHardDenyLabels().then(setHardDenyLabels);
|
||||
}, []);
|
||||
|
||||
function mutate(updater: (p: McpPolicy) => McpPolicy) {
|
||||
|
|
@ -243,7 +237,7 @@ export default function PolicyTab() {
|
|||
<div className="policy-hard-deny">
|
||||
<div className="policy-hard-deny-header">Always blocked (built-in)</div>
|
||||
<ul className="policy-hard-deny-list">
|
||||
{HARD_DENY_LABELS.map((label) => (
|
||||
{hardDenyLabels.map((label) => (
|
||||
<li key={label} className="policy-hard-deny-rule">
|
||||
<code>{label}</code>
|
||||
<span className="policy-hard-deny-badge">Cannot be disabled</span>
|
||||
|
|
|
|||
|
|
@ -180,6 +180,11 @@ export const mcpPolicyLoad = (): Promise<McpPolicy> =>
|
|||
export const mcpPolicySave = (policy: McpPolicy): Promise<void> =>
|
||||
invoke("mcp_policy_save", { policy });
|
||||
|
||||
/** Compiled-in hard-deny rule labels (the patterns the user CANNOT
|
||||
* override). Loaded once at PolicyTab mount; backend is the SoT. */
|
||||
export const mcpHardDenyLabels = (): Promise<string[]> =>
|
||||
invoke("mcp_hard_deny_labels");
|
||||
|
||||
/** Subscribe to MCP action requests from the backend. Each request is a
|
||||
* tool call the frontend must handle (mutate state) and reply to via
|
||||
* {@link mcpActionReply}. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue