diff --git a/agent/extensions/guardrails.json b/agent/extensions/guardrails.json index dea4e24..a9eea10 100644 --- a/agent/extensions/guardrails.json +++ b/agent/extensions/guardrails.json @@ -1,15 +1,16 @@ { - "$schema": "https://unpkg.com/@aliou/pi-guardrails@0.14.1/schema.json", + "$schema": "https://unpkg.com/@aliou/pi-guardrails@0.15.0/schema.json", "applyBuiltinDefaults": true, "version": "0.13.0-20260619", "onboarding": { "completed": true, - "completedAt": "2026-05-11T11:58:01.896Z", - "version": "0.9.0-20260327" + "completedAt": "2026-06-27T00:47:19.051Z", + "version": "0.13.0-20260619" }, "features": { - "pathAccess": true, - "policies": true + "policies": true, + "permissionGate": true, + "pathAccess": true }, "permissionGate": { "requireConfirmation": true, @@ -38,6 +39,42 @@ "pattern": "(?:^|[|&;]\\s*)glab\\s+api\\s+graphql\\b(?=[^|&;]*\\bmutation\\b)", "regex": true, "description": "GitLab GraphQL mutation via glab" + }, + { + "pattern": "git push .*(-f\\b|--force(?!-with-lease)|--force-with-lease)", + "regex": true, + "description": "Git force push (--force, -f, or --force-with-lease)" + }, + { + "pattern": "(?:npm|yarn|pnpm)\\s+publish", + "regex": true, + "description": "Package publishing (npm/yarn/pnpm)" + }, + { + "pattern": "DROP\\s+(?:DATABASE|TABLE)", + "regex": true, + "description": "SQL DROP DATABASE/TABLE" + }, + { + "pattern": "terraform\\s+(?:apply|destroy)", + "regex": true, + "description": "Terraform apply/destroy (infra changes)" + }, + { + "pattern": "kubectl delete", + "description": "Kubernetes resource deletion" + }, + { + "pattern": "docker system prune", + "description": "Docker system cleanup (removes images/containers/volumes)" + }, + { + "pattern": "aws s3 rm", + "description": "AWS S3 object deletion" + }, + { + "pattern": "aws ec2 terminate-instances", + "description": "AWS EC2 instance termination" } ] }, @@ -61,10 +98,7 @@ "pattern": "**/.secrets" }, { - "pattern": "**/*credentials*" - }, - { - "pattern": "~/.npmrc" + "pattern": "*credentials*" }, { "pattern": "~/.npmrc*" @@ -75,6 +109,9 @@ { "pattern": "~/.pi/agent/auth.json" }, + { + "pattern": "~/.pi/agent/mcp.json" + }, { "pattern": "~/.aws/config" }, @@ -115,6 +152,14 @@ "kind": "directory", "path": "~/.pi/agent/skills" }, + { + "kind": "directory", + "path": "~/.pi/agent/extensions" + }, + { + "kind": "file", + "path": "~/.pi/agent/settings" + }, { "kind": "file", "path": "~/.pi" diff --git a/agent/extensions/guardrails.test.mts b/agent/extensions/guardrails.test.mts index 6eb65cc..bbfc453 100644 --- a/agent/extensions/guardrails.test.mts +++ b/agent/extensions/guardrails.test.mts @@ -243,3 +243,68 @@ test("glab api mutation-style commands are flagged", () => { assert.notDeepEqual(matchingDescriptions(command), [], command); } }); + +test("1Password CLI (op) is flagged, including after a pipe", () => { + const flagged = [ + "op read", + "op signin", + "echo x && op get item foo", + "true || op item delete xxx", + ]; + for (const command of flagged) { + assert.ok( + matchingDescriptions(command).some((d) => d.includes("1Password CLI")), + command, + ); + } + + // "op" inside other words must not trigger. + const benign = ['echo "stop now"', "open index.html", "git rebase --continue"]; + for (const command of benign) { + assert.deepEqual(matchingDescriptions(command), [], command); + } +}); + +test("generic destructive commands are flagged", () => { + const flagged = [ + "git push --force origin main", + "git push origin main -f", + "git push --force-with-lease origin main", + "npm publish", + "pnpm publish", + "yarn publish", + "DROP TABLE users;", + "DROP DATABASE prod;", + "terraform apply", + "terraform destroy", + "kubectl delete pod foo", + "docker system prune -af", + "aws s3 rm s3://bucket/key", + "aws ec2 terminate-instances --instance-ids i-123", + ]; + for (const command of flagged) { + assert.ok(matchingDescriptions(command).length > 0, command); + } +}); + +test("benign lookalikes are not flagged", () => { + const benign = [ + "git push origin main", + "git push origin feature/update", + "npm install", + "npm run build", + "terraform plan", + "terraform validate", + "kubectl get pods", + "kubectl describe pod foo", + "docker ps", + "docker system df", + "aws s3 ls", + "aws s3 cp x.txt s3://bucket/", + "aws ec2 describe-instances", + 'psql -c "SELECT 1"', + ]; + for (const command of benign) { + assert.deepEqual(matchingDescriptions(command), [], command); + } +});