Security and AI agent controls

The controls that keep agents from posting without you, and how your credentials are stored.

Updated 2026-09-28

How SocialHandoff keeps agents in check

SocialHandoff exists to put a person between AI agents and your social accounts. This page describes the controls that do that, how your credentials are stored, and how to report a problem. Everything here describes the open-source core, so you can read the code that enforces it.

The short version

  • Nothing an agent drafts is published until a person approves it, unless you have promoted that agent.
  • An agent can never approve its own draft. Approval needs an owner key.
  • Social account tokens are encrypted at rest with AES-256-GCM.
  • Agent API keys are stored only as SHA-256 hashes.
  • Every action lands in an append-only, hash-chained audit log you can verify.
  • One kill switch pauses every agent and holds the queue.

Approval is enforced on the server

The approval rule is not a setting in the agent's prompt. It is enforced by the API. When an agent calls draft_post or schedule_post, the post enters the approval inbox. The approve_post tool is only accepted from an owner key, so an agent that tries to approve its own work gets an error, whatever its instructions say. That matters because prompt injection is a real risk: a malicious web page or email can tell an agent to post something. With SocialHandoff, the worst a hijacked agent can do is add a draft you then reject.

Publish-now posts also have a 60-second undo window, and a dry-run preview shows exactly what each network will receive before anything is sent. See approving posts.

One key per agent, least privilege by default

Every agent gets its own API key. Each key is scoped two ways:

ScopeWhat it limits
NetworksWhich connected accounts the agent may target
Permissionsdraft, schedule, and analytics, each granted separately

If a key leaks, you revoke that one key without touching your other agents. Keys are shown once when you create them and then stored only as SHA-256 hashes, so a copy of the database does not contain usable keys. Read more in agent keys and permissions.

The trust ladder

A new agent starts draft-only. After a run of clean approvals, an owner can promote it to auto-publish on specific networks, either by hand or by policy with autoPromote. Promotion is narrow: an agent trusted on Bluesky is still draft-only on LinkedIn. If any guardrail fails, the agent is demoted immediately and goes back to draft-only.

The policy lives in .socialhandoff/policy.json in your own repository, so a change to what agents may do goes through the same code review as any other change. See the trust ladder guide.

Guardrails on every draft

Guardrails check every draft before it can publish:

  • Banned topics from your brand memory
  • Per-network length limits
  • Missing alt text on images
  • Per-account daily post limits
  • Blocked link shorteners, which hide where a link goes

Details are in the guardrails guide.

The kill switch

If something looks wrong, one action pauses every agent and holds every queued post. Nothing publishes while the switch is on. When you resume, held posts are released. See the kill switch guide.

Credentials and data at rest

  • Social account tokens are encrypted with AES-256-GCM before they are written to the database. The key comes from SOCIALHANDOFF_ENCRYPTION_KEY and is never stored alongside the data.
  • Agent API keys are stored as SHA-256 hashes only.
  • Model keys for brand-voice rewrites are your own, and you can remove them at any time.

A verifiable audit log

Drafts, approvals, rejections, publishes, and other key actions are appended to the audit log. Each entry includes a hash of the entry before it, forming a chain. Calling GET /v1/audit/verify recomputes the chain and reports whether any entry was changed or removed. Entries also carry citations, such as the GitHub release a draft was created from, so you can trace a post back to its source. See the audit log guide.

Hardening of the service

  • Owner sign-in protects the dashboard and approval inbox.
  • A one-time setup token is required to claim a new install, so a freshly deployed server cannot be taken over by whoever finds it first.
  • Private-network URLs are refused, which blocks server-side request forgery against your internal network.
  • The container runs as a non-root user.
  • Duplicate protection and idempotency keys stop retries from posting the same thing twice.

Self-hosting and the hosted service

If you self-host, your tokens, drafts, and logs never leave your server, and you control the encryption key. If you use the hosted service, SocialHandoff runs the same open-source core for you. Our privacy policy explains what we store and why. The open-source page explains what is and is not in the AGPL core.

Reporting a vulnerability

Email support@socialhandoff.com with the details and steps to reproduce. Please give us a reasonable time to fix the issue before you disclose it publicly. We will confirm receipt, keep you updated, and credit you if you would like.

Let your agents post. Keep the final say.

Connect your first agent in minutes. Every draft waits in your inbox until you approve it.

14 days free. No card required.

The hosted version is opening soon

Leave your email and we will send one message when hosted accounts open, with your 14-day trial ready. Want it today? Self-host it free from the repo.

Start free trial