Self-hosted, edge-native email inbox on Cloudflare — receive and reply from your own domains. Runs on Workers, Durable Objects, R2, D1 & Queues, with an optional MCP layer for AI agents.
Drift inferred · capture-to-capture
No drift recorded — single capability capture; advisories appear once its surface changes.
transport — counts 5 tools · 0 res
· 0 prompts
permission surface via code analysis
tools
-
draft_reply
-
list_mailboxes
-
list_threads
-
read_message
-
search_messages
prompt-surface
shipped agent-instruction files + hidden-content / dangerous-code findings —
quoted from the analyzed source
analyzed commit bfaecd6 · analyzer v33 · 2d ago
skills & prompt files 2
- agent-rules santigamo-reccado-bfaecd6/AGENTS.md
- skill santigamo-reccado-bfaecd6/SKILL.md
danger signals7
- suspicious endpoint api.telegram.org santigamo-reccado-bfaecd6/src/telegram/api.ts :12
const TELEGRAM_API_BASE = "https://api.telegram.org"; - suspicious endpoint api.telegram.org santigamo-reccado-bfaecd6/tests/integration/telegram-card-reconcile.test.ts :120
if (!url.startsWith("https://api.telegram.org/")) { - suspicious endpoint api.telegram.org santigamo-reccado-bfaecd6/tests/integration/telegram-experience.test.ts :204
if (!url.startsWith("https://api.telegram.org/")) { - suspicious endpoint api.telegram.org santigamo-reccado-bfaecd6/tests/integration/telegram-webhook.test.ts :58
if (!url.startsWith("https://api.telegram.org/")) { - suspicious endpoint api.telegram.org santigamo-reccado-bfaecd6/tests/unit/telegram-cards.test.ts :102
if (!url.startsWith("https://api.telegram.org/")) { - suspicious endpoint api.telegram.org santigamo-reccado-bfaecd6/tests/unit/telegram-noise.test.ts :87
if (!url.startsWith("https://api.telegram.org/")) { - suspicious endpoint api.telegram.org santigamo-reccado-bfaecd6/tests/unit/telegram-notify.test.ts :83
if (!url.startsWith("https://api.telegram.org/")) {
evidence-backed
findings quoted directly from the published source artifact — not inferred
code files: 181
filesystem 18
- fs (weak) santigamo-reccado-bfaecd6/scripts/create-reccado.mjs :14
import { existsSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/doctor.ts :19
import { existsSync, readdirSync, readFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/ensure-dev-vars.ts :17
import { existsSync, writeFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/generate-large-mime.ts :2
import { createWriteStream, mkdirSync, statSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/reingest-mailbox.ts :68
import { mkdtempSync, readFileSync, rmSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/seed-dev-d1.ts :3
import { mkdtempSync, writeFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/setup-auth.ts :40
import { readFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/setup-cloud.ts :35
import { mkdirSync, writeFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/setup-domain.ts :15
import { existsSync, readFileSync, writeFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/setup-mailbox.ts :25
import { existsSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/setup-mcp-claim.ts :19
import { existsSync, mkdtempSync, readFileSync, writeFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/setup-routing.ts :19
import { readFileSync } from "node:fs";
show 6 more
- fs (weak) santigamo-reccado-bfaecd6/scripts/setup-sending.ts :72
import { existsSync, readFileSync, writeFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/smoke-email-local.ts :1
import { existsSync, readFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/smoke-large-email-local.ts :1
import { readFileSync, statSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/smoke-routing.ts :13
import { readFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/verify-cloudflare-bindings.ts :2
import { readFileSync } from "node:fs"; - fs (weak) santigamo-reccado-bfaecd6/scripts/verify-mailbox-rebuild.ts :51
import { readFileSync } from "node:fs";
shell / exec 18
- shell (weak) santigamo-reccado-bfaecd6/scripts/create-reccado.mjs :13
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/doctor.ts :18
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/reingest-mailbox.ts :67
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/seed-dev-d1.ts :2
import { execSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/setup-auth.ts :38
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/setup-cloud.ts :34
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/setup-domain.ts :14
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/setup-mailbox.ts :24
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/setup-mcp-claim.ts :18
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/setup-routing.ts :18
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/setup-sending.ts :65
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/smoke-routing.ts :12
import { execFileSync } from "node:child_process";
show 6 more
- shell (weak) santigamo-reccado-bfaecd6/scripts/verify-cloudflare-bindings.ts :1
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/scripts/verify-mailbox-rebuild.ts :50
import { execFileSync } from "node:child_process"; - shell (weak) santigamo-reccado-bfaecd6/tests/helpers/migrations.ts :81
* migrations/d1/*.sql -- and D1Database#exec() only accepts one statement per - shell (weak) santigamo-reccado-bfaecd6/tests/integration/api-control-plane.test.ts :25
// D1Database#exec() only takes one statement per line, so the multi-line CREATE TABLEs are split. - shell (weak) santigamo-reccado-bfaecd6/tests/integration/api-security.test.ts :25
// migrations/d1/*.sql. D1Database#exec() only accepts one statement per line, so - shell (weak) santigamo-reccado-bfaecd6/tests/integration/transactional-api-keys.test.ts :23
* D1Database#exec() only accepts one statement per line, so multi-line CREATE TABLE
network 44
- net (weak) santigamo-reccado-bfaecd6/scripts/doctor.ts :906
fetch(healthUrl, { redirect: "manual", signal: controller.signal }), - net (weak) santigamo-reccado-bfaecd6/scripts/reingest-mailbox.ts :260
const response = await fetch(`https://api.cloudflare.com/client/v4${path}`, { - net (weak) santigamo-reccado-bfaecd6/scripts/setup-auth.ts :86
const response = await fetch(`https://api.cloudflare.com/client/v4${path}`, { - net (weak) santigamo-reccado-bfaecd6/scripts/setup-domain.ts :93
const response = await fetch(`https://api.cloudflare.com/client/v4${path}`, { - net (weak) santigamo-reccado-bfaecd6/scripts/setup-routing.ts :135
const response = await fetch(`https://api.cloudflare.com/client/v4${path}`, { - net (weak) santigamo-reccado-bfaecd6/scripts/setup-sending.ts :240
// OAuth session, while the script's own fetch() DNS calls keep using the token. - net (weak) santigamo-reccado-bfaecd6/scripts/smoke-email-local.ts :52
const response = await fetch(emailUrl, { - net (weak) santigamo-reccado-bfaecd6/scripts/smoke-large-email-local.ts :21
const response = await fetch(emailUrl, { - net (weak) santigamo-reccado-bfaecd6/scripts/verify-mailbox-rebuild.ts :199
const response = await fetch(url, { - net santigamo-reccado-bfaecd6/src/api/hono.ts :185
// from a Durable Object (or any fetch()) have immutable headers, so rebuild the response - net santigamo-reccado-bfaecd6/src/api/mailbox-routes.ts :98
return stub.fetch(url.toString()); - net santigamo-reccado-bfaecd6/src/cloudflare/email-events-consumer.ts :155
const response = await stub.fetch("https://mailbox-do/transactional/delivery-event", {
show 28 more
- net santigamo-reccado-bfaecd6/src/cloudflare/queue-consumer.ts :43
const response = await stub.fetch("https://mailbox-do/ingest", { - net santigamo-reccado-bfaecd6/src/cloudflare/scheduled.ts :60
const exportResponse = await stub.fetch("https://mailbox-do/export-index"); - net santigamo-reccado-bfaecd6/src/components/domains/domains.ts :152
const data = await json<{ domains?: Domain[] }>(await fetch("/api/domains")); - net santigamo-reccado-bfaecd6/src/components/keys/api-keys.ts :263
const data = await json<{ keys?: RawApiKey[] }>(await fetch(base(mailboxId))); - net santigamo-reccado-bfaecd6/src/components/mail/Sidebar.tsx :28
await fetch("/api/auth/sign-out", { - net santigamo-reccado-bfaecd6/src/do/mailbox-do.ts :997
async fetch(request: Request): Promise<Response> { - net santigamo-reccado-bfaecd6/src/lib/mail.ts :149
const data = await json<{ mailboxes: Mailbox[] }>(await fetch("/api/mailboxes")); - net santigamo-reccado-bfaecd6/src/lib/outbound-send.ts :140
response = await stub.fetch(`https://mailbox-do/drafts/${draftId}/confirm-send`, { - net santigamo-reccado-bfaecd6/src/lib/runtime-config.ts :73
return await fetch(input, { - net santigamo-reccado-bfaecd6/src/mcp/mailbox-facade.ts :89
const response = await stub.fetch(url.toString()); - net santigamo-reccado-bfaecd6/src/routes/consent.tsx :21
const response = await fetch( - net santigamo-reccado-bfaecd6/src/routes/login.tsx :17
return fetch(url, { - net santigamo-reccado-bfaecd6/src/routes/security.tsx :14
return fetch(url, { - net santigamo-reccado-bfaecd6/src/server.ts :47
return stub.fetch("https://mailbox-do/debug/schema"); - net santigamo-reccado-bfaecd6/src/telegram/commands.ts :156
const response = await stub.fetch(url.toString()); - net santigamo-reccado-bfaecd6/src/telegram/drafts.ts :196
const response = await stub.fetch(`https://mailbox-do/drafts/${row.draft_id}`); - net santigamo-reccado-bfaecd6/src/telegram/messages.ts :45
const response = await stub.fetch(`https://mailbox-do/messages/${messageLocalId}`); - net santigamo-reccado-bfaecd6/src/telegram/webhook.ts :477
const draftResponse = await stub.fetch("https://mailbox-do/drafts", { - net (weak) santigamo-reccado-bfaecd6/tests/health.test.ts :32
const response = await worker.fetch(request, env, ctx); - net (weak) santigamo-reccado-bfaecd6/tests/integration/api-control-plane.test.ts :43
const response = await worker.fetch(new Request(`http://localhost${path}`, init), env, ctx); - net (weak) santigamo-reccado-bfaecd6/tests/integration/api-security.test.ts :43
const response = await worker.fetch(request, workerEnv, ctx); - net (weak) santigamo-reccado-bfaecd6/tests/integration/better-auth.test.ts :48
const response = await worker.fetch(request, env, ctx); - net (weak) santigamo-reccado-bfaecd6/tests/integration/mcp-oauth.test.ts :69
const response = await worker.fetch(request, authEnv(), ctx); - net (weak) santigamo-reccado-bfaecd6/tests/integration/outbound-threading.test.ts :273
const response = await stub.fetch(`https://mailbox-do/drafts/${draftId}/request-send`, { - net (weak) santigamo-reccado-bfaecd6/tests/integration/telegram-card-reconcile.test.ts :98
const response = await worker.fetch( - net (weak) santigamo-reccado-bfaecd6/tests/integration/telegram-experience.test.ts :245
const response = await worker.fetch(request, telegramEnv(), ctx); - net (weak) santigamo-reccado-bfaecd6/tests/integration/telegram-webhook.test.ts :138
const response = await worker.fetch(request, options.env ?? telegramEnv(), ctx); - net (weak) santigamo-reccado-bfaecd6/tests/integration/thread-merge.test.ts :91
const response = await testEnv.MAILBOX_DO.getByName(mailboxId).fetch(
4 more not shown — this panel samples each group; the count above is the real total.
secrets 7
- secrets (weak) santigamo-reccado-bfaecd6/scripts/reingest-mailbox.ts :620
const pushToken = (args["push-token"] ?? process.env.RECCADO_PUSH_TOKEN)?.trim(); - secrets (weak) santigamo-reccado-bfaecd6/scripts/setup-auth.ts :230
process.env.CLOUDFLARE_API_TOKEN?.trim(), - secrets (weak) santigamo-reccado-bfaecd6/scripts/setup-domain.ts :135
const token = process.env.CLOUDFLARE_API_TOKEN?.trim(); - secrets (weak) santigamo-reccado-bfaecd6/scripts/setup-routing.ts :179
const token = process.env.CLOUDFLARE_API_TOKEN?.trim(); - secrets (weak) santigamo-reccado-bfaecd6/scripts/setup-sending.ts :605
const token = process.env.CLOUDFLARE_API_TOKEN?.trim(); - secrets (weak) santigamo-reccado-bfaecd6/scripts/smoke-email-local.ts :19
if (process.env.PHASE0_DEBUG_TOKEN) { - secrets (weak) santigamo-reccado-bfaecd6/scripts/verify-mailbox-rebuild.ts :146
const debugToken = (args["debug-token"] ?? process.env.PHASE0_DEBUG_TOKEN)?.trim();
tool registrations 5
- list_mailboxes santigamo-reccado-bfaecd6/src/mcp/tools.ts :66
- list_threads santigamo-reccado-bfaecd6/src/mcp/tools.ts :104
- search_messages santigamo-reccado-bfaecd6/src/mcp/tools.ts :150
- read_message santigamo-reccado-bfaecd6/src/mcp/tools.ts :190
- draft_reply santigamo-reccado-bfaecd6/src/mcp/tools.ts :229
declared dependencies 41
- @modelcontextprotocol/sdk@^1.29.0
- @better-auth/mcp@1.7.2
- @tailwindcss/vite@^4.3.2
- @tanstack/react-devtools@^0.10.8
- @tanstack/react-router@^1.170.16
- @tanstack/react-router-devtools@^1.167.0
- @tanstack/react-router-ssr-query@^1.167.1
- @tanstack/react-start@^1.168.26
- @tanstack/router-plugin@^1.132.0
- agents@^0.17.3
- better-auth@1.7.2
- clsx@^2.1.1
show 28 more
- hono@^4.9.6
- lucide-react@^1.22.0
- mimetext@^3.0.28
- postal-mime@^2.7.5
- react@^19.2.0
- react-dom@^19.2.0
- tailwind-merge@^3.6.0
- tailwindcss@^4.3.2
- uqr@^0.1.3
- zod@^4.4.3
- @biomejs/biome@^2.5.2
- @cloudflare/vite-plugin@^1.54.3
- @cloudflare/vitest-pool-workers@^0.17.0
- @tailwindcss/typography@^0.5.16
- @tanstack/devtools-vite@^0.8.1
- @tanstack/router-cli@^1.132.0
- @testing-library/dom@^10.4.1
- @testing-library/react@^16.3.0
- @types/node@^26.1.0
- @types/react@^19.2.0
- @types/react-dom@^19.2.0
- @vitejs/plugin-react@^6.0.1
- @vitest/coverage-istanbul@^4.1.9
- jsdom@^29.1.1
- tsx@^4.20.3
- typescript@^6.0.2
- vite@^8.1.2
- vitest@^4.1.5
1 more not shown — this panel samples each group; the count above is the real total.
perm:untrusted 2
- untrusted (weak) santigamo-reccado-bfaecd6/scripts/smoke-email-local.ts :107
const r2Head = (await (await fetch(r2HeadUrl, { headers: debugHeaders })).json()) as { - untrusted (weak) santigamo-reccado-bfaecd6/scripts/smoke-large-email-local.ts :65
const r2Head = (await (await fetch(r2HeadUrl)).json()) as { exists?: boolean; size?: number };