The Autonomous Stack

AI Security & LLM Ops · LLM Security · v1.0.0

Webhook Guard Agent v1.0

Fail-closed signed webhook admission for autonomous agent pipelines.

$3.00one-timePay with crypto

webhook-security hmac replay-protection offline

agent ⟶ theautonomousstack.xyz

01GET /api/v1/pack/agent-webhook-guard-v1

402 Payment RequiredX-PAYMENT-REQUIRED

02sign TransferWithAuthorization3.00 USDC · Base (eip155:8453)

03GET + PAYMENT-SIGNATURE

200 OKapplication/zip · 17 files

pay per pack over x402no account

What's inside

Admit signed webhook events to an agent pipeline without trusting the payload.

Webhook Guard is for operators who let billing, CRM, deployment, support, or automation systems trigger autonomous workers. It verifies HMAC-SHA256 signatures, rejects stale events, records accepted event IDs in SQLite, and quarantines malformed, forged, expired, or replayed envelopes before downstream automation sees them.

Honest scope

The admission decision is deterministic and works offline. The optional local LLM CLI sees only verified metadata (source, event_id, event_type, and content_type) and may suggest a queue. It never sees the webhook body and cannot change an accept/reject verdict.

Capability Deterministic core Optional LLM
HMAC verification Yes No
Timestamp window Yes No
Replay protection Yes No
Quarantine and audit report Yes No
Conservative queue selection Yes No
Metadata-only routing suggestion Fallback Yes
HTTP server or reverse proxy No No
Provider-specific signature formats Customize No

This pack consumes local JSON envelope files. Your existing HTTP gateway must write those files after preserving the exact request body. See CUSTOMIZE.md.

Who it is for

Quick start

Install on Debian or Ubuntu:

sudo bash install.sh

Or run in place without root:

export WEBHOOK_GUARD_SECRET='replace-with-at-least-16-random-bytes'
python3 agent.py --help
python3 -m unittest -q test_agent

Create and sign a local example:

NOW="$(date +%s)"
export NOW
python3 -c 'import json,os; print(json.dumps({
  "source":"billing",
  "event_id":"evt-demo-001",
  "event_type":"payment.succeeded",
  "timestamp":int(os.environ["NOW"]),
  "body":"{\"amount\":1200,\"currency\":\"USD\"}"
}))' > /tmp/webhook.json
SIG="$(python3 agent.py sign --input /tmp/webhook.json)"
export SIG
python3 -c 'import json,os; p="/tmp/webhook.json"; d=json.load(open(p)); d["signature"]=os.environ["SIG"]; open(p,"w").write(json.dumps(d))'
python3 agent.py verify --input /tmp/webhook.json --no-record

For a durable replay ledger, omit --no-record. A second verification of the same (source, event_id) returns exit code 2 with verdict replay.

Event envelope

{
  "source": "billing",
  "event_id": "evt-123",
  "event_type": "payment.succeeded",
  "content_type": "application/json",
  "timestamp": 1784912400,
  "body": "{\"amount\":1200,\"currency\":\"USD\"}",
  "signature": "sha256=0123456789abcdef..."
}

The signed bytes are:

ASCII(timestamp) + "." + exact UTF-8 body bytes

Use body_base64 instead of body for binary data. Exactly one body field is required.

Architecture

provider webhook
       |
       v
existing HTTP gateway
       |
       | exact body + signature + timestamp + event ID
       v
local inbox/*.json
       |
       v
+-----------------------+
| Webhook Guard         |
| 1. bound input size   |
| 2. verify HMAC        |
| 3. check clock window |
| 4. reserve event ID   |
+----------+------------+
           |
      +----+----+
      |         |
 accepted/   quarantine/
      |         |
 safe route   audit only
 suggestion
      |
 downstream agent

Commands

python3 agent.py status
python3 agent.py sign --input envelope.json
python3 agent.py verify --input envelope.json --db webhook_guard.sqlite3
python3 agent.py run --once --inbox inbox --accepted accepted --quarantine quarantine
python3 agent.py run --llm-routing

verify exits 0 only for an accepted event, 2 for a rejected event, and 1 for local configuration or input errors.

Security boundaries

Start with CHECKLIST.md, then adapt the gateway and source mappings in CUSTOMIZE.md.