mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-06-22 18:54:10 +00:00
fix(shell): block exec writes to history.jsonl and cursor files (#2989)
This commit is contained in:
parent
a81e4c1791
commit
00fb491bc9
@ -61,6 +61,14 @@ class ExecTool(Tool):
|
|||||||
r">\s*/dev/sd", # write to disk
|
r">\s*/dev/sd", # write to disk
|
||||||
r"\b(shutdown|reboot|poweroff)\b", # system power
|
r"\b(shutdown|reboot|poweroff)\b", # system power
|
||||||
r":\(\)\s*\{.*\};\s*:", # fork bomb
|
r":\(\)\s*\{.*\};\s*:", # fork bomb
|
||||||
|
# Block writes to nanobot internal state files (#2989).
|
||||||
|
# history.jsonl / .dream_cursor are managed by append_history();
|
||||||
|
# direct writes corrupt the cursor format and crash /dream.
|
||||||
|
r">>?\s*\S*(?:history\.jsonl|\.dream_cursor)", # > / >> redirect
|
||||||
|
r"\btee\b[^|;&<>]*(?:history\.jsonl|\.dream_cursor)", # tee / tee -a
|
||||||
|
r"\b(?:cp|mv)\b[^|;&<>]*(?:history\.jsonl|\.dream_cursor)", # cp/mv target
|
||||||
|
r"\bdd\b[^|;&<>]*\bof=\S*(?:history\.jsonl|\.dream_cursor)", # dd of=
|
||||||
|
r"\bsed\s+-i[^|;&<>]*(?:history\.jsonl|\.dream_cursor)", # sed -i
|
||||||
]
|
]
|
||||||
self.allow_patterns = allow_patterns or []
|
self.allow_patterns = allow_patterns or []
|
||||||
self.restrict_to_workspace = restrict_to_workspace
|
self.restrict_to_workspace = restrict_to_workspace
|
||||||
|
|||||||
@ -67,3 +67,49 @@ async def test_exec_blocks_chained_internal_url():
|
|||||||
command="echo start && curl http://169.254.169.254/latest/meta-data/ && echo done"
|
command="echo start && curl http://169.254.169.254/latest/meta-data/ && echo done"
|
||||||
)
|
)
|
||||||
assert "Error" in result
|
assert "Error" in result
|
||||||
|
|
||||||
|
|
||||||
|
# --- #2989: block writes to nanobot internal state files -----------------
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"command",
|
||||||
|
[
|
||||||
|
"cat foo >> history.jsonl",
|
||||||
|
"echo '{}' > history.jsonl",
|
||||||
|
"echo '{}' > memory/history.jsonl",
|
||||||
|
"echo '{}' > ./workspace/memory/history.jsonl",
|
||||||
|
"tee -a history.jsonl < foo",
|
||||||
|
"tee history.jsonl",
|
||||||
|
"cp /tmp/fake.jsonl history.jsonl",
|
||||||
|
"mv backup.jsonl memory/history.jsonl",
|
||||||
|
"dd if=/dev/zero of=memory/history.jsonl",
|
||||||
|
"sed -i 's/old/new/' history.jsonl",
|
||||||
|
"echo x > .dream_cursor",
|
||||||
|
"cp /tmp/x memory/.dream_cursor",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_exec_blocks_writes_to_history_jsonl(command):
|
||||||
|
"""Direct writes to history.jsonl / .dream_cursor must be blocked (#2989)."""
|
||||||
|
tool = ExecTool()
|
||||||
|
result = tool._guard_command(command, "/tmp")
|
||||||
|
assert result is not None
|
||||||
|
assert "dangerous pattern" in result.lower()
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"command",
|
||||||
|
[
|
||||||
|
"cat history.jsonl",
|
||||||
|
"wc -l history.jsonl",
|
||||||
|
"tail -n 5 history.jsonl",
|
||||||
|
"grep foo history.jsonl",
|
||||||
|
"ls memory/",
|
||||||
|
"echo history.jsonl",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_exec_allows_reads_of_history_jsonl(command):
|
||||||
|
"""Read-only access to history.jsonl must still be allowed."""
|
||||||
|
tool = ExecTool()
|
||||||
|
result = tool._guard_command(command, "/tmp")
|
||||||
|
assert result is None
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user