fix(ne-exec): allow read-only pipe filters in managed NE CLI

Whitelist include/exclude/begin/section/count/match/grep/one-line after show/display pipes while blocking redirect/append/tee/send.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-07-14 16:24:47 +08:00
parent c5973eec69
commit 33af0efc98
2 changed files with 58 additions and 6 deletions

View file

@ -33,16 +33,48 @@ class NeExecValidationTests(unittest.TestCase):
_validate_command(cmd)
self.assertEqual(ctx.exception.detail, "command_not_allowed_prefix")
def test_blocks_pipe(self) -> None:
with self.assertRaises(HTTPException) as ctx:
_validate_command("show run | include hostname")
self.assertEqual(ctx.exception.status_code, 400)
self.assertEqual(ctx.exception.detail, "command_chars_not_allowed")
def test_allows_pipe_filter_subcommands(self) -> None:
for cmd in (
"show run | include hostname",
"show configuration | include hostname",
"display current-configuration | include sysname",
"show run | exclude ^!",
"show run | begin interface",
"show run | section ^router",
"show ip route | count",
"show run | match hostname",
"show run | grep hostname",
"show run | one-line",
"show run | include x | include y",
):
with self.subTest(cmd=cmd):
_validate_command(cmd)
def test_blocks_pipe_redirect_and_unknown(self) -> None:
for cmd in (
"show run | redirect tftp://1.1.1.1/config",
"show run | append flash:cfg.txt",
"show run | tee flash:cfg.txt",
"show run | send log",
"show run | unknown-filter x",
"show run |",
"show run | | include x",
):
with self.subTest(cmd=cmd):
with self.assertRaises(HTTPException) as ctx:
_validate_command(cmd)
self.assertEqual(ctx.exception.status_code, 400)
self.assertEqual(ctx.exception.detail, "command_pipe_not_allowed")
def test_blocks_configure(self) -> None:
with self.assertRaises(HTTPException):
_validate_command("configure terminal")
def test_blocks_configure_after_pipe(self) -> None:
with self.assertRaises(HTTPException) as ctx:
_validate_command("show run | configure terminal")
self.assertEqual(ctx.exception.detail, "command_blocked")
def test_blocks_non_show_prefix(self) -> None:
with self.assertRaises(HTTPException) as ctx:
_validate_command("interface GigabitEthernet0/0")