""" SPF-2 structured action parser safety tests. These tests cover the auto-execute kubectl grammar without mocking services. """ import pytest from src.services.action_parser import ( ActionKind, is_safe_kubectl_action, parse_kubectl_action, ) @pytest.mark.parametrize("cmd", [ "kubectl rollout restart deployment/awoooi-api -n awoooi-prod", "kubectl rollout restart statefulset/postgres-primary -n awoooi-prod", "kubectl rollout restart daemonset/node-exporter -n awoooi-prod", "kubectl rollout restart deployment awoooi-api -n awoooi-prod", "kubectl -n awoooi-prod rollout restart deploy/awoooi-api", "kubectl scale deployment awoooi-api --replicas=3 -n awoooi-prod", "kubectl autoscale deployment awoooi-api --cpu-percent=70 --min=2 --max=5 -n awoooi-prod", "kubectl set resources deployment/awoooi-api --limits=cpu=2000m,memory=1Gi -n awoooi-prod", "kubectl delete pod awoooi-api-7d6b776f78-4sgjl -n awoooi-prod", "kubectl get pods -n awoooi-prod", "kubectl describe node k3s-node-01", "kubectl logs -n awoooi-prod --tail=100 --selector=app=awoooi-api", "kubectl top pods -n awoooi-prod", ]) def test_safe_kubectl_actions_pass(cmd): assert is_safe_kubectl_action(cmd) is True @pytest.mark.parametrize("cmd", [ "kubectl get pods\nrm -rf /", "kubectl get pods -n prod $(echo injected)", "kubectl rollout restart deployment/$(cat /etc/passwd)", "kubectl rollout restart deployment/awoooi-api; rm -rf / -n prod", "kubectl rollout undo deployment/awoooi-api -n prod", "kubectl get pods -n prod && curl http://attacker.invalid", "kubectl delete deployment awoooi-api -n awoooi-prod", "kubectl delete pods --all -n awoooi-prod", "kubectl delete pod awoooi-api-7d6b776f78-4sgjl --force -n awoooi-prod", "kubectl scale deployment awoooi-api --replicas=0 -n awoooi-prod", "kubectl autoscale deployment awoooi-api --min=5 --max=2 -n awoooi-prod", "kubectl set resources deployment/awoooi-api --limits=ephemeral-storage=10Gi -n awoooi-prod", "kubectl patch deployment awoooi-api -p spec -n awoooi-prod", "ssh 192.168.0.188 docker restart openclaw", ]) def test_unsafe_kubectl_actions_fail(cmd): parsed = parse_kubectl_action(cmd) assert parsed.ok is False, parsed def test_parser_returns_structured_fields(): parsed = parse_kubectl_action( "kubectl -n awoooi-prod rollout restart deployment/awoooi-api" ) assert parsed.ok is True assert parsed.kind is ActionKind.ROLLOUT assert parsed.verb == "rollout" assert parsed.subverb == "restart" assert parsed.resource_type == "deployment" assert parsed.resource_name == "awoooi-api" assert parsed.namespace == "awoooi-prod" def test_parser_rejects_newline_without_regex_backtracking(): cmd = "kubectl get pods" + (" " * 400) + "\nrm -rf /" parsed = parse_kubectl_action(cmd) assert parsed.ok is False assert parsed.reason == "forbidden_shell_metachar"