mirror of
https://github.com/shareAI-lab/analysis_claude_code.git
synced 2026-09-21 21:03:38 +08:00
fix(s03): let Gate 2 own the workspace boundary instead of safe_path
safe_path hard-raised on out-of-workspace paths while Gate 2 asked about the same condition, so approving an out-of-workspace write never took effect. Make the permission pipeline the sole boundary authority: drop safe_path, resolve paths directly in the file tools, and extend the Gate 2 rule to read_file. Sync all three READMEs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -54,16 +54,9 @@ SYSTEM = f"You are a coding agent at {WORKDIR}. All destructive operations requi
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
# FROM s02 (unchanged): Tool Implementations
|
||||
# FROM s02 : Tool Implementations
|
||||
# ═══════════════════════════════════════════════════════════
|
||||
|
||||
def safe_path(p: str) -> Path:
|
||||
path = (WORKDIR / p).resolve()
|
||||
if not path.is_relative_to(WORKDIR):
|
||||
raise ValueError(f"Path escapes workspace: {p}")
|
||||
return path
|
||||
|
||||
|
||||
def run_bash(command: str) -> str:
|
||||
try:
|
||||
r = subprocess.run(command, shell=True, cwd=WORKDIR,
|
||||
@@ -76,7 +69,7 @@ def run_bash(command: str) -> str:
|
||||
|
||||
def run_read(path: str, limit: int | None = None) -> str:
|
||||
try:
|
||||
lines = safe_path(path).read_text().splitlines()
|
||||
lines = (WORKDIR / path).resolve().read_text().splitlines()
|
||||
if limit and limit < len(lines):
|
||||
lines = lines[:limit] + [f"... ({len(lines) - limit} more lines)"]
|
||||
return "\n".join(lines)
|
||||
@@ -86,7 +79,7 @@ def run_read(path: str, limit: int | None = None) -> str:
|
||||
|
||||
def run_write(path: str, content: str) -> str:
|
||||
try:
|
||||
file_path = safe_path(path)
|
||||
file_path = (WORKDIR / path).resolve()
|
||||
file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
file_path.write_text(content)
|
||||
return f"Wrote {len(content)} bytes to {path}"
|
||||
@@ -96,7 +89,7 @@ def run_write(path: str, content: str) -> str:
|
||||
|
||||
def run_edit(path: str, old_text: str, new_text: str) -> str:
|
||||
try:
|
||||
file_path = safe_path(path)
|
||||
file_path = (WORKDIR / path).resolve()
|
||||
text = file_path.read_text()
|
||||
if old_text not in text:
|
||||
return f"Error: text not found in {path}"
|
||||
@@ -157,7 +150,7 @@ def check_deny_list(command: str) -> str | None:
|
||||
|
||||
# Gate 2: Rule matching — context-dependent checks
|
||||
PERMISSION_RULES = [
|
||||
{"tools": ["write_file", "edit_file"],
|
||||
{"tools": ["read_file", "write_file", "edit_file"],
|
||||
"check": lambda args: not (WORKDIR / args.get("path", "")).resolve().is_relative_to(WORKDIR),
|
||||
"message": "Writing outside workspace"},
|
||||
{"tools": ["bash"],
|
||||
|
||||
Reference in New Issue
Block a user