diff --git a/src/lai_automation/security.py b/src/lai_automation/security.py index 5fe005e..4a37245 100644 --- a/src/lai_automation/security.py +++ b/src/lai_automation/security.py @@ -35,6 +35,11 @@ _PROTECTED_REPOSITORY_PATH = re.compile( _PARENT_PATH = re.compile(r"(?:^|[/\s'\"=])\.\.(?:/|$|[\s'\";&|])") _BACKGROUND_PROCESS = re.compile(r"(?])&(?![&>])") _SERVER_COMMAND = re.compile(r"(?]+\.(?:bak|backup|orig|rej|swp|temp|tmp)" + r"|(?:test_)?debug\.(?:php|py|js|ts)|scratch\.(?:php|py|js|ts))" + r"(?=$|[\s'\";&|<>])" +) _CHANGE_DIRECTORY = re.compile( r"(?:^|[;&|]\s*)cd\s+(?P'[^']*'|\"[^\"]*\"|[^\s;&|]+)" ) @@ -158,6 +163,8 @@ class SafeLocalEnvironment: raise ValueError("Command rejected by safety policy: path outside repository") if _PROTECTED_REPOSITORY_PATH.search(command): raise ValueError("Command rejected by safety policy: protected repository path") + if _TEMPORARY_ARTIFACT.search(command): + raise ValueError("Command rejected by safety policy: temporary artifact") if _BACKGROUND_PROCESS.search(command) or _SERVER_COMMAND.search(command): raise ValueError("Command rejected by safety policy: persistent process") for match in _CHANGE_DIRECTORY.finditer(command): diff --git a/tests/test_security.py b/tests/test_security.py index ab888a5..d8dd860 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -48,6 +48,9 @@ def test_environment_rejects_cwd_outside_repository(tmp_path: Path) -> None: "cd .. && pwd", "php -S 127.0.0.1:8000", "php artisan serve &", + "cp config/app.php config/app.php.bak", + "printf debug > test_debug.php", + "touch scratch.py", ], ) def test_environment_rejects_unsafe_commands(tmp_path: Path, command: str) -> None: