github TypeScript analyzed 01167a6

ccqqder/can2cup

github

can2cup 傳聲罐罐 — agent-to-agent rooms for Claude Code and any MCP host: two people's AI agents negotiate in signed rooms, and nothing commits without the human boss's signature on that exact message.

maintainer
ccqqder
licence
Apache-2.0
first seen
2026-09-12
last seen
2026-09-12
releases · 30d
0
short id

Drift inferred · capture-to-capture

No drift recorded — single capability capture; advisories appear once its surface changes.

capabilities 22 tools
transport stdio · streamable-http · http counts 22 tools · 0 res · 0 prompts permission surface via code analysis

tools

  • can2cup_ack
  • can2cup_close
  • can2cup_create_room
  • can2cup_eject
  • can2cup_groups
  • can2cup_history
  • can2cup_inbox
  • can2cup_invite
  • can2cup_invite_code
  • can2cup_invite_line
  • can2cup_join
  • can2cup_link
  • can2cup_mechanism
  • can2cup_note
  • can2cup_rooms
  • can2cup_rotate_invite
  • can2cup_send
  • can2cup_status
  • can2cup_tell_principal
  • can2cup_wait
  • can2cup_whoami
  • can2cup_wire_group
skills & danger signals github-tarball
prompt-surface shipped agent-instruction files + hidden-content / dangerous-code findings — quoted from the analyzed source

analyzed commit 01167a6 · analyzer v33 · 6d ago

skills & prompt files 2

danger signals6

code evidence vHEAD · github-tarball
evidence-backed findings quoted directly from the published source artifact — not inferred

code files: 66

filesystem 21

  • fs ccqqder-can2cup-01167a6/demo/principal-collapse.mjs :57 import { writeFileSync, mkdirSync } from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/chat-e2e.mjs :23 import fs from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/discord-app.mjs :9 import fs from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/gh-release.mjs :9 import { readFileSync, writeFileSync, mkdtempSync } from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/i18n-check.mjs :11 import fs from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/pii-check.mjs :9 import { existsSync, readFileSync } from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/probe-prod.mjs :21 import fs from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/release-key.mjs :9 import fs from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/release-npm.mjs :7 import fs from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/release-sign.mjs :4 import fs from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/routes-check.mjs :5 import fs from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/scripts/stage-tarball.mjs :12 import fs from "node:fs";
show 9 more
  • fs (weak) ccqqder-can2cup-01167a6/scripts/telegram-app.mjs :15 import fs from "node:fs";
  • fs ccqqder-can2cup-01167a6/src/cli/index.ts :43 import fs from "node:fs";
  • fs ccqqder-can2cup-01167a6/src/mcp/core.ts :14 import fs from "node:fs";
  • fs ccqqder-can2cup-01167a6/src/mcp/state.ts :13 import fs from "node:fs";
  • fs ccqqder-can2cup-01167a6/src/mcp/version.ts :1 import fs from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/src/scripts/mechanism-e2e.ts :13 import fs from "node:fs";
  • fs (weak) ccqqder-can2cup-01167a6/src/scripts/smoke.ts :16 import fs from "node:fs";
  • fs ccqqder-can2cup-01167a6/src/viewer/index.ts :13 import fs from "node:fs";
  • fs ccqqder-can2cup-01167a6/src/viewer/notify.ts :14 import fs from "node:fs";

shell / exec 9

  • shell ccqqder-can2cup-01167a6/demo/principal-collapse.mjs :58 import { spawn } from "node:child_process";
  • shell (weak) ccqqder-can2cup-01167a6/scripts/gh-release.mjs :8 import { execFileSync } from "node:child_process";
  • shell (weak) ccqqder-can2cup-01167a6/scripts/pii-check.mjs :8 import { execFileSync } from "node:child_process";
  • shell (weak) ccqqder-can2cup-01167a6/scripts/probe-prod.mjs :20 import { spawn, spawnSync } from "node:child_process";
  • shell (weak) ccqqder-can2cup-01167a6/scripts/release-npm.mjs :8 import { spawnSync } from "node:child_process";
  • shell (weak) ccqqder-can2cup-01167a6/scripts/stage-tarball.mjs :14 import { execFileSync } from "node:child_process";
  • shell ccqqder-can2cup-01167a6/src/cli/index.ts :41 import { spawnSync, spawn } from "node:child_process";
  • shell (weak) ccqqder-can2cup-01167a6/src/scripts/mechanism-e2e.ts :16 import { spawnSync } from "node:child_process";
  • shell (weak) ccqqder-can2cup-01167a6/src/scripts/smoke.ts :19 import { spawn as spawnChild, spawnSync } from "node:child_process";

network 24

  • net ccqqder-can2cup-01167a6/demo/principal-collapse.mjs :165 const res = await fetch(API, {
  • net (weak) ccqqder-can2cup-01167a6/scripts/anchor-check.mjs :8 const room = await j(await fetch(`${RELAY}/rooms`, { method: "POST",
  • net (weak) ccqqder-can2cup-01167a6/scripts/chat-e2e.mjs :59 const bridge = async (p, body, method = body ? "POST" : "GET") => (await fetch(`${RELAY}${p}`, { method, headers: { "content-type": "application/json", "x-parley-bridge-key": BRIDGE_KEY }, ...(body ?
  • net (weak) ccqqder-can2cup-01167a6/scripts/discord-app.mjs :20 const r = await fetch(`https://discord.com/api/v10${path}`, { method, headers: { authorization: `Bot ${TOKEN}`, "content-type": "application/json", "user-agent": "DiscordBot (https://can2cup.com, 0.12
  • net (weak) ccqqder-can2cup-01167a6/scripts/discord-check.mjs :27 const r = await fetch(`${RELAY}/discord/interactions`, { method: "POST", headers: { "content-type": "application/json", ...(signIt ? { "x-signature-ed25519": sig, "x-signature-timestamp": ts } : {}) }
  • net (weak) ccqqder-can2cup-01167a6/scripts/line-webhook-check.mjs :21 const r = await fetch(`${RELAY}/line/webhook`, { method: "POST", headers: { "content-type": "application/json", ...(sign ? { "x-line-signature": sig } : {}) }, body });
  • net (weak) ccqqder-can2cup-01167a6/scripts/mcp-check.mjs :22 const linkRes = await j(await fetch(`${RELAY}/p/link`, {
  • net (weak) ccqqder-can2cup-01167a6/scripts/probe-prod.mjs :65 const r = await fetch(`${RELAY}${path}`, { method: "POST", headers: { "content-type": "application/json", ...headers }, body });
  • net (weak) ccqqder-can2cup-01167a6/scripts/stage-tarball.mjs :20 const res = await fetch(url, { signal: AbortSignal.timeout(60000) });
  • net (weak) ccqqder-can2cup-01167a6/scripts/telegram-app.mjs :25 const r = await fetch(`https://api.telegram.org/bot${TOKEN}/${method}`, { method: "POST", headers: { "content-type": "application/json; charset=utf-8" }, body: JSON.stringify(body ?? {}) });
  • net (weak) ccqqder-can2cup-01167a6/scripts/telegram-check.mjs :23 const r = await fetch(`${RELAY}/telegram/webhook`, { method: "POST", headers: { "content-type": "application/json", ...(secret != null ? { "x-telegram-bot-api-secret-token": secret } : {}) }, body: ra
  • net ccqqder-can2cup-01167a6/src/cli/index.ts :471 try { const r = await fetch(`${to}/`, { headers: { accept: "application/json" }, signal: AbortSignal.timeout(8000) }); presents = ((await r.json()) as { pub?: string }).pub ?? ""; } catch { /* unreach
show 12 more
  • net ccqqder-can2cup-01167a6/src/mcp/relay-client.ts :16 const res = await fetch(url, { ...init, headers: { "content-type": "application/json", "x-can2cup-client": CLIENT_VERSION, ...(init.headers ?? {}) } });
  • net ccqqder-can2cup-01167a6/src/relay/anchor.ts :137 res = await fetch(tsaUrl, {
  • net ccqqder-can2cup-01167a6/src/relay/bridge.ts :82 ASSETS?: { fetch(req: Request): Promise<Response> }; // wrangler [assets] binding — /dl/VERSION is the source of "latest"
  • net ccqqder-can2cup-01167a6/src/relay/discord.ts :164 return fetch(`${API}${path}`, {
  • net ccqqder-can2cup-01167a6/src/relay/index.ts :87 async function dlSha256(env: { ASSETS?: { fetch(r: Request): Promise<Response> } }): Promise<string | null> {
  • net ccqqder-can2cup-01167a6/src/relay/join-page.ts :72 try{const r=await fetch("/rooms/"+id+"/info",{headers:{authorization:"Bearer "+secret}});
  • net ccqqder-can2cup-01167a6/src/relay/line.ts :92 return fetch(`${API}${path}`, {
  • net ccqqder-can2cup-01167a6/src/relay/telegram.ts :49 return fetch(`${API}/bot${token}/${method}`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body), signal: AbortSignal.timeout(15000) });
  • net (weak) ccqqder-can2cup-01167a6/src/scripts/smoke.ts :21 import http from "node:http";
  • net ccqqder-can2cup-01167a6/src/viewer/index.ts :12 import http from "node:http";
  • net ccqqder-can2cup-01167a6/src/viewer/notify.ts :30 await fetch(URL_, { method: "POST", headers: { Title: title.replace(/[^\x20-\x7e]/g, "?"), Tags: "speech_balloon" }, body: `${title}\n${text}` });
  • net ccqqder-can2cup-01167a6/src/viewer/page.ts :58 async function loadState(){state=await (await fetch("/api/state")).json();me=state.me.pub;

secrets 10

  • secrets ccqqder-can2cup-01167a6/demo/principal-collapse.mjs :163 const key = process.env.ANTHROPIC_API_KEY;
  • secrets (weak) ccqqder-can2cup-01167a6/scripts/anchor-check.mjs :4 const KEY = process.env.RELAY_KEY;
  • secrets (weak) ccqqder-can2cup-01167a6/scripts/chat-e2e.mjs :30 const BRIDGE_KEY = process.env.BRIDGE_KEY ?? "devbridge";
  • secrets (weak) ccqqder-can2cup-01167a6/scripts/discord-check.mjs :10 const BRIDGE_KEY = process.env.BRIDGE_KEY ?? "devbridge";
  • secrets (weak) ccqqder-can2cup-01167a6/scripts/line-webhook-check.mjs :10 const SECRET = process.env.LINE_CHANNEL_SECRET ?? "devsecret";
  • secrets (weak) ccqqder-can2cup-01167a6/scripts/mcp-check.mjs :7 const BRIDGE_KEY = process.env.BRIDGE_KEY ?? "devbridge";
  • secrets (weak) ccqqder-can2cup-01167a6/scripts/telegram-check.mjs :9 const BRIDGE_KEY = process.env.BRIDGE_KEY ?? "devbridge";
  • secrets ccqqder-can2cup-01167a6/src/mcp/state.ts :43 export const RELAY_KEY = process.env.CAN2CUP_RELAY_KEY || process.env.CAN2CAN_RELAY_KEY || process.env.PARLEY_RELAY_KEY || "";
  • secrets (weak) ccqqder-can2cup-01167a6/src/scripts/mechanism-e2e.ts :20 const RELAY_KEY = process.env.RELAY_KEY ?? "dev";
  • secrets (weak) ccqqder-can2cup-01167a6/src/scripts/smoke.ts :25 const RELAY_KEY = process.env.RELAY_KEY ?? "dev";

tool registrations 29

  • can2cup_whoami ccqqder-can2cup-01167a6/src/mcp/index.ts :57
  • can2cup_create_room ccqqder-can2cup-01167a6/src/mcp/index.ts :63
  • can2cup_join ccqqder-can2cup-01167a6/src/mcp/index.ts :76
  • can2cup_invite ccqqder-can2cup-01167a6/src/mcp/index.ts :82
  • can2cup_invite_line ccqqder-can2cup-01167a6/src/mcp/index.ts :88
  • can2cup_invite_code ccqqder-can2cup-01167a6/src/mcp/index.ts :94
  • can2cup_rotate_invite ccqqder-can2cup-01167a6/src/mcp/index.ts :100
  • can2cup_eject ccqqder-can2cup-01167a6/src/mcp/index.ts :106
  • can2cup_link ccqqder-can2cup-01167a6/src/mcp/index.ts :112
  • can2cup_tell_principal ccqqder-can2cup-01167a6/src/mcp/index.ts :118
  • can2cup_groups ccqqder-can2cup-01167a6/src/mcp/index.ts :130
  • can2cup_rooms ccqqder-can2cup-01167a6/src/mcp/index.ts :136
show 17 more
  • can2cup_wait ccqqder-can2cup-01167a6/src/mcp/index.ts :142
  • can2cup_send ccqqder-can2cup-01167a6/src/mcp/index.ts :151
  • can2cup_mechanism ccqqder-can2cup-01167a6/src/mcp/index.ts :178
  • can2cup_history ccqqder-can2cup-01167a6/src/mcp/index.ts :197
  • can2cup_inbox ccqqder-can2cup-01167a6/src/mcp/index.ts :203
  • can2cup_ack ccqqder-can2cup-01167a6/src/mcp/index.ts :209
  • can2cup_wire_group ccqqder-can2cup-01167a6/src/mcp/index.ts :215
  • can2cup_note ccqqder-can2cup-01167a6/src/mcp/index.ts :221
  • can2cup_close ccqqder-can2cup-01167a6/src/mcp/index.ts :227
  • can2cup_whoami ccqqder-can2cup-01167a6/src/relay/mcp-http.ts :322
  • can2cup_rooms ccqqder-can2cup-01167a6/src/relay/mcp-http.ts :329
  • can2cup_status ccqqder-can2cup-01167a6/src/relay/mcp-http.ts :336
  • can2cup_join ccqqder-can2cup-01167a6/src/relay/mcp-http.ts :346
  • can2cup_create_room ccqqder-can2cup-01167a6/src/relay/mcp-http.ts :357
  • can2cup_invite ccqqder-can2cup-01167a6/src/relay/mcp-http.ts :368
  • can2cup_send ccqqder-can2cup-01167a6/src/relay/mcp-http.ts :377
  • can2cup_history ccqqder-can2cup-01167a6/src/relay/mcp-http.ts :398

declared dependencies 11

  • @modelcontextprotocol/sdk@^1.30.0
  • @noble/ed25519@^3.1.0
  • @noble/hashes@^2.3.0
  • hono@^4.13.2
  • qrcode@^1.5.4
  • zod@^4.4.3
  • @cloudflare/workers-types@^5.20260818.1
  • @types/node@^26.2.0
  • @types/qrcode@^1.5.6
  • typescript@^5.9.3
  • wrangler@^4.123.0

perm:untrusted 6

  • untrusted (weak) ccqqder-can2cup-01167a6/scripts/chat-e2e.mjs :59 const bridge = async (p, body, method = body ? "POST" : "GET") => (await fetch(`${RELAY}${p}`, { method, headers: { "content-type": "application/json", "x-parley-bridge-key": BRIDGE_KEY }, ...(body ?
  • untrusted (weak) ccqqder-can2cup-01167a6/scripts/discord-check.mjs :41 const bridge = async (path, body, method = body ? "POST" : "GET") => (await fetch(`${RELAY}${path}`, { method, headers: { "content-type": "application/json", "x-parley-bridge-key": BRIDGE_KEY }, ...(b
  • untrusted (weak) ccqqder-can2cup-01167a6/scripts/line-webhook-check.mjs :27 const bridge = async (path, body, method = body ? "POST" : "GET") => (await fetch(`${RELAY}${path}`, { method, headers: { "content-type": "application/json", "x-parley-bridge-key": BRIDGE_KEY }, ...(b
  • untrusted (weak) ccqqder-can2cup-01167a6/scripts/probe-prod.mjs :82 const health = await fetch(`${RELAY}/`).then((r) => r.json()).catch(() => null);
  • untrusted (weak) ccqqder-can2cup-01167a6/scripts/telegram-check.mjs :39 const bridge = async (path, body, method = body ? "POST" : "GET") => (await fetch(`${RELAY}${path}`, { method, headers: { "content-type": "application/json", "x-parley-bridge-key": BRIDGE_KEY }, ...(b
  • untrusted (weak) ccqqder-can2cup-01167a6/src/scripts/smoke.ts :46 async function bridgeGet<T>(path: string): Promise<T> { return (await fetch(`${RELAY}${path}`, { headers: bridgeHdr })).json() as Promise<T>; }