confirm-gate
v1.2.0
Published
Destructive action confirmation gate for AI agents — generates one-time NATO-phonetic codes before irreversible operations.
Maintainers
Readme
confirm-gate
A lightweight confirmation gate for AI agents before performing destructive actions.
| Warning Screen | Confirmation Code |
|:-:|:-:|
|
|
|
The Problem
AI agents that can delete containers, repos, volumes, and files are powerful — but a misunderstood instruction or a hallucinated confirmation can cause real damage. Chat-based confirmations are too easy to skim past.
The Solution
Before any destructive action, the agent:
- POSTs a request to this service describing exactly what will be deleted
- Gets back a URL and sends it to the user
- The user opens the URL, reads a full-screen warning, and clicks a button
- A one-time code appears (e.g.
YANKEE-2387-HOTEL) - The user pastes the code back to the agent
- The agent verifies the code — only then does it proceed
No code = no action. Codes expire in 5 minutes and are single-use.
Features
- 💀 Scary red full-screen warning — hard to skim past
- ⏱️ Live countdown timer so you know how long you have
- 📋 Copy-to-clipboard button on the confirmation code
- 🔒 Optional PIN protection — a leaked URL is useless without it
- 🛡️ Rate limiting on verify endpoint
- 🗂️ File-based token store — no database needed
- 🐳 Docker-ready, single container
Quick Start
Option A — npx (Node.js, no Docker needed):
npx confirm-gate
# or install globally:
npm install -g confirm-gate && confirm-gateOption B — Docker:
docker run -d \
--name confirm-gate \
--restart unless-stopped \
-v confirm-data:/data \
-p 127.0.0.1:3051:3051 \
-e BASE_URL=https://confirm.yourdomain.com \
ghcr.io/dadmin88/confirm-gate:latestThen visit http://localhost:3051/setup to set your PIN.
CLI Options
confirm-gate [options]
--port <n> Port to listen on (default: 3051)
--base-url <url> Base URL for confirm links (default: http://localhost:3051)
--data <path> Directory for token store (default: ~/.confirm-gate)
--pin <code> Require PIN to confirm (default: none)
--version Print version
--help Show helpWith PIN Protection
# npx
npx confirm-gate --pin mysecretpin
# Docker
docker run -d \
--name confirm-gate \
--restart unless-stopped \
-v confirm-data:/data \
-p 127.0.0.1:3051:3051 \
-e BASE_URL=https://confirm.yourdomain.com \
-e CONFIRM_PIN=yourpin \
ghcr.io/dadmin88/confirm-gate:latestWhen a PIN is set, the confirmation page requires it before generating a code. A leaked URL is useless without it.
API
# 1. Agent creates a confirmation request
curl -X POST http://localhost:3051/api/request \
-H 'Content-Type: application/json' \
-d '{"action":"Delete container foo","details":"This will permanently remove the foo container and all its data."}'
# Returns: {"token":"...","url":"https://confirm.yourdomain.com/confirm/<token>","expires_in":300}
# 2. Agent sends the URL to the user, waits for them to paste back a code
# 3. Agent verifies the code
curl -X POST http://localhost:3051/api/verify \
-H 'Content-Type: application/json' \
-d '{"code":"YANKEE-2387-HOTEL"}'
# Returns: {"valid":true,"action":"...","details":"..."}Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| PORT | 3051 | Port to listen on |
| DATA_FILE | /data/tokens.json | Token persistence path |
| BASE_URL | http://confirm.mesh | Base URL for confirmation links |
| CONFIRM_PIN | (unset) | Optional PIN required to confirm |
Caddy Example
https://confirm.yourdomain.com {
reverse_proxy localhost:3051
}Stack
- Node.js ≥ 18 + Express
- File-based token store (no database needed)
- Zero native dependencies — works on any platform
Contributing
PRs welcome. Issues at github.com/Dadmin88/confirm-gate.
