Files
telegtrum_bot/entrypoint.tor.sh
T
goyban b7a0a86be2 Security fixes, ready-to-deploy image, and rewritten docs
Audit fixes:

- Wallet names were used unvalidated as file paths, so a name like
  "../<other-id>/x" reached another user's wallet directory or overwrote
  bot_settings.json. Names are now validated and every path is resolved and
  confirmed to sit inside the caller's own directory, which also blocks a
  planted symlink from escaping.
- Tor mode leaked: the mempool.space fee check opened a direct clear-net
  connection, tying the server's IP to its Bitcoin activity. It now goes
  through Tor's SOCKS proxy to mempool's onion service, DNS included.
- The xpub message was left in the chat forever. It reveals the wallet's whole
  address and balance history, so it is now deleted like the password is.
- Inline buttons stay live on old messages, so a user removed from the
  allow-list could keep using them. Callbacks re-check authorisation, and
  auth_check now works for callback queries instead of raising on a null
  message.
- Wallet names echoed back in callback_data are confirmed against the user's
  real wallet list.
- Settings are written via temp file + atomic rename; a crash mid-write used
  to truncate the file and lose every user's wallet selection.
- Replies were sent against messages that had just been deleted; deletion is
  now best-effort and cannot abort the flow.

Deployment:

- Allow-list can come from ALLOWED_USERS instead of a bind-mounted file, so a
  deployment needs no files on disk. Both sources merge when both are present.
- A missing bind-mounted allowed_users.txt made Docker create a directory in
  its place and silently lock everyone out; the entrypoint now detects that
  and stops with an explanation.
- Standard mode honours ELECTRUM_SERVER, which previously only worked in Tor
  mode despite being documented.
- Added VERSION, push.sh, docker-compose.deploy.yml and .env.deploy.example
  for a two-file deploy off the published image.

Docs rewritten in English and Persian around the name Telegtrum, leading with
the security model and what it does not protect against.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 16:43:00 +00:00

50 lines
1.9 KiB
Bash

#!/usr/bin/env bash
set -e
mkdir -p /root/.electrum/wallets
# The allow-list may come from ALLOWED_USERS instead of a mounted file. Missing
# is fine; a *directory* here means Docker auto-created one for a bind mount
# that pointed at a non-existent path, which would silently lock everyone out.
ALLOWED_FILE="${ALLOWED_USERS_FILE:-/app/allowed_users.txt}"
if [ -d "$ALLOWED_FILE" ]; then
echo "ERROR: $ALLOWED_FILE is a directory."
echo "Create the file on the host before starting, or drop the bind mount"
echo "and set ALLOWED_USERS=<id>,<id> in your .env instead." >&2
exit 1
fi
if [ ! -f "$ALLOWED_FILE" ] && [ -z "${ALLOWED_USERS:-}" ]; then
echo "WARNING: no allow-list found — set ALLOWED_USERS or mount $ALLOWED_FILE" >&2
fi
echo "Starting Tor..."
tor --RunAsDaemon 1 --SocksPort 9050 --DataDirectory /var/lib/tor
echo "Waiting for Tor SOCKS proxy on 127.0.0.1:9050..."
until echo > /dev/tcp/127.0.0.1/9050 2>/dev/null; do
sleep 1
done
echo "Tor is ready."
echo "Starting Electrum daemon..."
rm -f /root/.electrum/daemon
PROXY="socks5:localhost:9050"
# Everything the bot itself fetches must go through Tor too. Without these the
# mempool.space fee check would open a direct clear-net connection and tie this
# server's IP to its Bitcoin activity, defeating the point of Tor mode.
export TOR_SOCKS="127.0.0.1:9050"
export MEMPOOL_API_URL="${MEMPOOL_API_URL:-http://mempoolhqx4isw62xs7abwphsq7ldayuidyx2v2oethdhhj6mlo2r6ad.onion/api/v1/fees/recommended}"
if [ -n "${ELECTRUM_SERVER:-}" ]; then
# Pin to a single user-specified server (own node)
electrum -1 -s "${ELECTRUM_SERVER}" -p "${PROXY}" daemon -d
else
# Route through Tor using a public .onion server
electrum -s "${ELECTRUM_ONION_SERVER:-electrums3lojbuj.onion:50001:t}" -p "${PROXY}" daemon -d
fi
echo "Electrum daemon started. Launching bot..."
exec /opt/electrum/bin/python3 /app/bot.py