What is this?

An end-to-end system for QR codes and short links. From generation in the browser to secure redirection on a self-hosted server. Instead of relying on external services like Bitly, I built the entire chain myself: a QR code generator as a static page, a redirect microservice at go.mathis-adler.dev with a preview page and domain allowlist, and a CLI tool for link management.

The motivation: public URL shorteners track clicks, can be shut down, and are a security risk. I explain exactly why in my blog.

How It Fits Together

  • QR generator: (mathis-adler.dev/qr-generator) Enter a URL, generate a QR code, download as SVG or PNG. Runs entirely in the browser — no data leaves the machine.
  • Redirect service: (go.mathis-adler.dev) Node.js microservice in Docker. Every short link first shows a preview page with a countdown before the actual 302 redirect occurs. Users always see where they will be redirected.
  • CLI tool: Links are created exclusively via the command line with an API key. No public interface, no potential for abuse.

Security Decisions

  • Domain allowlist instead of open redirect — only redirects to predefined domains, with exact match (no endsWith that would let evilgithub.com through)
  • 12-character Base62 tokens (~71 bits of entropy ) — too long to guess, but short enough for QR codes
  • No tracking, no IP addresses, no user agent, no cookies.
  • Two-tier rate limiting (Nginx + Express) — stricter for 404 responses as protection against token enumeration
  • API only accessible via VPN: Nginx restricts /api/ routes to the internal network

What I Learned

  • The decision not to build a public shortener radically simplified the architecture and reduced the attack surface to nearly zero
  • Preview pages before redirects are minimal effort with significant security benefit

Glossary

Open Redirect
A security vulnerability where a server forwards incoming requests to arbitrary external URLs without restriction. Attackers use this to hide phishing links behind trusted domains.
Domain Allowlist
An explicit list of allowed target domains for redirects. Prevents open redirects by only allowing short links to predefined, trusted domains.
Base62
An encoding scheme that represents numbers using 62 characters (a–z, A–Z, 0–9). Commonly used for URL tokens as it produces compact, URL-safe strings.
Entropy (Bits)
A measure of a token's randomness. 71 bits of entropy means 271 possible combinations — roughly 2.4 sextillion. The higher the entropy, the harder a token is to guess.
Rate Limiting
A protection mechanism that limits the number of requests per time period. Prevents brute-force attacks and token enumeration through automated queries.
Token Enumeration
An attack that systematically tries all possible token combinations to find valid short links. Short tokens and missing rate limiting make this attack practical.
302 Found
An HTTP status code for temporary redirects. Unlike 301 (permanent), the target URL is not cached by the browser, so changes to the redirect target take effect immediately.