2026-01-05 · Authensor

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:

SafeClaw gates each operation with 446 validated tests and logs every decision to a hash-chained audit trail.

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