AI Agent Safety for PHP Applications
SafeClaw by Authensor provides deny-by-default action gating for PHP-based AI agents. Every exec(), file_get_contents(), curl_exec(), and shell_exec() call is checked against your YAML policy before it runs. Install with npx @authensor/safeclaw and call its local API from your PHP application — zero PHP dependencies required, works with Claude and OpenAI.
PHP Agent Risk Surface
PHP applications running AI agents face unique risks because PHP commonly runs as a web server process with broad filesystem permissions:
exec(),shell_exec(),system(),passthru(),proc_open()— shell executionfile_get_contents(),file_put_contents(),fopen()— filesystem accesscurl_exec(),file_get_contents('http://...')— outbound HTTPinclude(),require()— load and execute arbitrary PHP code
Installation
npx @authensor/safeclaw
SafeClaw runs as a sidecar. Your PHP application communicates with it over HTTP.
Policy
version: 1
defaultAction: deny
rules:
- action: file.read
path:
glob: "/var/www/app/data/**"
decision: allow
- action: file.write
path:
glob: "/var/www/app/storage/**"
decision: allow
- action: process.exec
command:
startsWith: "php"
decision: allow
- action: process.exec
command:
startsWith: "composer"
decision: prompt
- action: network.request
host:
in: ["api.openai.com", "api.anthropic.com"]
decision: allow
- action: file.read
path:
glob: "*/.env"
decision: deny
- action: file.read
path:
glob: "**/config/database.php"
decision: deny
PHP Integration
<?php
class SafeClawGate
{
private string $endpoint;
public function __construct(string $endpoint = 'http://localhost:9800')
{
$this->endpoint = $endpoint;
}
public function check(array $request): array
{
$ch = curl_init("{$this->endpoint}/check");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($request),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
]);
$response = curl_exec($ch);
$error = curl_error($ch);
curl_close($ch);
if ($error) {
// Fail closed
return ['allowed' => false, 'reason' => 'SafeClaw unreachable'];
}
return json_decode($response, true);
}
}
Using the Gate
<?php
$gate = new SafeClawGate();
function safeExec(SafeClawGate $gate, string $command): string
{
$decision = $gate->check([
'action' => 'process.exec',
'command' => $command,
]);
if (!$decision['allowed']) {
throw new RuntimeException("SafeClaw denied: {$decision['reason']}");
}
$output = [];
exec($command, $output, $returnCode);
return implode("\n", $output);
}
function safeReadFile(SafeClawGate $gate, string $path): string
{
$decision = $gate->check([
'action' => 'file.read',
'path' => $path,
]);
if (!$decision['allowed']) {
throw new RuntimeException("SafeClaw denied: {$decision['reason']}");
}
return file_get_contents($path);
}
function safeHttpGet(SafeClawGate $gate, string $url): string
{
$host = parse_url($url, PHP_URL_HOST);
$decision = $gate->check([
'action' => 'network.request',
'host' => $host,
'url' => $url,
'method' => 'GET',
]);
if (!$decision['allowed']) {
throw new RuntimeException("SafeClaw denied: {$decision['reason']}");
}
return file_get_contents($url);
}
// Usage
$data = safeReadFile($gate, '/var/www/app/data/input.json');
$result = safeExec($gate, 'php artisan queue:work --once');
$response = safeHttpGet($gate, 'https://api.openai.com/v1/models');
Laravel Middleware Approach
For Laravel applications, create a service provider:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class SafeClawServiceProvider extends ServiceProvider
{
public function register(): void
{
$this->app->singleton(SafeClawGate::class, function () {
return new SafeClawGate(config('safeclaw.endpoint', 'http://localhost:9800'));
});
}
}
Every decision is hash-chained. MIT licensed, provider-agnostic.
Cross-References
Try SafeClaw
Action-level gating for AI agents. Set it up in your browser in 60 seconds.
$ npx @authensor/safeclaw