Skip to content

Security model

LinkBrain is single-user. Two independent gates in the Worker’s fetch() entry ensure only you can store or read links.

Gate 1 — webhook secret (blocks the open internet)

Section titled “Gate 1 — webhook secret (blocks the open internet)”

Every POST must carry an X-Telegram-Bot-Api-Secret-Token header equal to your WEBHOOK_SECRET (a 128-bit random value). A request with a wrong or missing secret is rejected with 403 before anything else runs. Only Telegram sends that header, because you registered it via setWebhook. Forging a request means guessing a 16-byte random secret — infeasible.

Gate 2 — chat-id allowlist (blocks other Telegram users)

Section titled “Gate 2 — chat-id allowlist (blocks other Telegram users)”

Even a request that has the correct secret is ignored unless the message’s chat.id matches your ALLOWED_CHAT_ID. Anything else is silently dropped — no reply, nothing stored. So only your chat can actually use the bot.

  • ✅ A stranger cannot POST directly to the Worker (Gate 1).
  • ✅ Another Telegram user cannot save or read links, and gets no response at all (Gate 2) — the bot appears dead to them.
  • ⚠️ The bot is still messageable. Anyone who knows its @username can send it a message, and Telegram forwards it to the Worker; Gate 2 just makes it a no-op. You can’t make a Telegram bot un-messageable — the defense is to ignore outsiders, which is exactly what happens. Keeping the username private is the practical extra step.
  • WEBHOOK_SECRET lives only as a Cloudflare secret and was passed once to setWebhook — it is not in the repository. Don’t share it.
  • If it ever leaks, rotate: wrangler secret put WEBHOOK_SECRET with a new value, then call setWebhook again with the matching secret_token.
  • The Worker also serves these public docs on GET requests at every path except /webhook. That’s intentional and contains no secrets. The webhook itself — POST /webhook — stays behind both gates; run_worker_first routes that path to the Worker so a static asset can never shadow it.