2025-12-26 · Authensor

AI Agent Safety for Go Developers

SafeClaw by Authensor provides deny-by-default action gating for Go-based AI agents. Every call to exec.Command(), os.OpenFile(), and http.Get() is checked against your YAML policy before execution, blocking unauthorized operations at the action level. Install SafeClaw with npx @authensor/safeclaw and communicate with it from your Go agent via its local HTTP API.

Go Agent Attack Surface

Go's standard library gives AI agents direct access to dangerous system operations:

A Go AI agent with access to these packages and no gating is a privilege escalation vector. SafeClaw closes this gap with 446 validated tests and a tamper-proof hash-chained audit trail.

Installation

npx @authensor/safeclaw

SafeClaw runs as a sidecar. Your Go agent hits it over localhost:

# SafeClaw listens on localhost:9800 by default
curl http://localhost:9800/health

Policy

version: 1
defaultAction: deny

rules:
- action: file.read
path:
glob: "/app/data/**"
decision: allow

- action: file.write
path:
glob: "/app/output/**"
decision: allow

- action: process.exec
command:
startsWith: "go"
decision: allow

- action: network.request
host:
in: ["api.openai.com", "api.anthropic.com"]
decision: allow

Go Integration

package safeclaw

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)

type ActionRequest struct {
Action string json:"action"
Path string json:"path,omitempty"
Command string json:"command,omitempty"
Host string json:"host,omitempty"
URL string json:"url,omitempty"
Method string json:"method,omitempty"
}

type GateDecision struct {
Allowed bool json:"allowed"
Reason string json:"reason"
}

type Gate struct {
endpoint string
}

func NewGate() *Gate {
return &Gate{endpoint: "http://localhost:9800"}
}

func (g Gate) Check(req ActionRequest) (GateDecision, error) {
body, _ := json.Marshal(req)
resp, err := http.Post(g.endpoint+"/check", "application/json", bytes.NewReader(body))
if err != nil {
// Fail closed: deny if SafeClaw is unreachable
return &GateDecision{Allowed: false, Reason: "SafeClaw unreachable"}, err
}
defer resp.Body.Close()

var decision GateDecision
json.NewDecoder(resp.Body).Decode(&decision)
return &decision, nil
}

Using the Gate

package main

import (
"fmt"
"os"
"os/exec"

"yourapp/safeclaw"
)

func main() {
gate := safeclaw.NewGate()

// Gate a command execution
decision, err := gate.Check(safeclaw.ActionRequest{
Action: "process.exec",
Command: "go build ./...",
})
if err != nil || !decision.Allowed {
fmt.Fprintf(os.Stderr, "Denied: %s\n", decision.Reason)
os.Exit(1)
}
cmd := exec.Command("go", "build", "./...")
cmd.Stdout = os.Stdout
cmd.Run()

// Gate a file read
decision, _ = gate.Check(safeclaw.ActionRequest{
Action: "file.read",
Path: "/app/data/input.json",
})
if decision.Allowed {
data, _ := os.ReadFile("/app/data/input.json")
fmt.Println(string(data))
}

// Gate a network request
decision, _ = gate.Check(safeclaw.ActionRequest{
Action: "network.request",
Host: "api.openai.com",
URL: "https://api.openai.com/v1/chat/completions",
Method: "POST",
})
if !decision.Allowed {
fmt.Fprintf(os.Stderr, "Network request denied: %s\n", decision.Reason)
}
}

SafeClaw fails closed — if the sidecar is unreachable, all actions are denied. Every decision is recorded in the hash-chained audit trail. MIT licensed, works with Claude and OpenAI.

Cross-References

Try SafeClaw

Action-level gating for AI agents. Set it up in your browser in 60 seconds.

$ npx @authensor/safeclaw