Skip to content

Security

What is actually implemented

A URL shortener is attractive to attackers precisely because it hides a destination behind a domain people trust. This page lists the controls that exist in the code today — and stops there.

Controls

Ten things this platform does

Each one is a mechanism, not an intention.

Encryption in transit

Every request is served over TLS, including customer domains.

HSTS is sent on every response with a two-year max-age, includeSubDomains and preload, so a browser that has seen the site once refuses to talk to it over plain HTTP again. Custom domains are served over TLS too; certificate issuance and renewal are handled by the hosting platform the operator deploys to.

Password storage

bcrypt at cost 12, for account passwords and link passwords alike.

Plaintext passwords are never written anywhere — not to the database, not to logs. Verification against a missing hash still burns the same amount of time as a real comparison, so response latency does not reveal whether an account exists.

API keys

Stored as a SHA-256 digest. The key itself is shown exactly once.

We cannot show you a key again because we do not have it — only its hash, which is what an incoming request is matched against. Keys carry explicit scopes and an optional expiry date, and can be revoked immediately.

SSRF protection

Every server-side fetch resolves DNS and checks the address before connecting.

A hostname check alone is not enough: an attacker controls their own DNS and can point a public name at a cloud metadata address. Each A and AAAA record is resolved and rejected if it lands in a private, loopback, link-local or CGNAT range, and the check runs again on every redirect hop.

Destination validation

Short links cannot be pointed at internal infrastructure.

Destinations are rejected when they use a non-HTTP protocol, embed credentials, target a private or loopback address — including decimal, octal, hexadecimal and IPv4-mapped IPv6 encodings — or use a port that is not a plausible public web service.

Destination screening

Blocklist, structural heuristics and optional Safe Browsing.

Destinations are checked against an operator blocklist, then against heuristics that look for brand names in unrelated paths and subdomains, credential-harvest vocabulary, punycode homographs and chained shorteners. Where an operator configures a key, Google Safe Browsing runs as a third layer. Heuristics mostly produce a warning interstitial; only the blocklist and Safe Browsing hard-block.

Rate limiting

Sliding-window limits on every sensitive endpoint.

Sign-in, registration, password reset, link-password entry, abuse reports, the contact form and the public API each have their own bucket, so pressure on one never consumes another’s allowance. Responses carry standard rate-limit headers, and the limiter fails open rather than locking customers out if the cache blips.

Audit logging

Every state change a customer could later ask about is recorded.

The log stores the actor, the action, the target and what changed. It is what answers “who changed this destination and when” — including for team accounts, where more than one person can edit the same link.

Role-based access control

Admin, Editor and Viewer roles, re-checked on every request.

Ownership is part of the database query rather than a comparison made after fetching a row, so a guessed id returns nothing rather than someone else’s data. Administrative role is refreshed from the database periodically instead of being trusted from a long-lived token.

No raw IP retention

The analytics table has no column for an IP address.

An address is used in memory to derive a daily-rotating visitor hash and to apply rate limits, then discarded. Nothing that is stored can be turned back into it.

Headers

Sent on every response

These are the values configured for the application, not a generic list.

Security headers and the reason each one is set
HeaderValueWhy
Strict-Transport-Securitymax-age=63072000; includeSubDomains; preloadRemoves the plain-HTTP downgrade path for two years after a single visit.
X-Content-Type-OptionsnosniffStops a browser from re-interpreting a response as a type we did not send.
X-Frame-OptionsSAMEORIGINPrevents the dashboard being framed by another site for clickjacking.
Referrer-Policystrict-origin-when-cross-originKeeps paths and query strings from leaking to third parties in the Referer header.
Permissions-Policycamera=(), microphone=(), geolocation=(), interest-cohort=()Denies powerful browser APIs the product does not use, and opts out of cohort tracking.

A Content-Security-Policy is not listed because the framework injects inline bootstrap scripts, which would force 'unsafe-inline' on script-src and make the directive weaker than it looks. XSS defence rests on React's escaping and on server-side sanitisation of the one surface that accepts customer HTML.

Design constraint

The owned-content proxy cannot be turned into a phishing tool

The feature that serves another origin under a branded URL is gated structurally rather than by a checkbox.

  1. 1The branded domain must be verified and owned by the account.
  2. 2The proxy target must sit on the same registrable domain as the branded host. go.acme.com may proxy store.acme.com; it may not proxy anything under a different one.
  3. 3The domain-level proxy switch must be on, which requires the Business plan.
  4. 4The target passes the SSRF check on every hop, and every proxied request is audited.

Because rule 2 compares registrable domains, “proxy a bank's login page” is not one misconfiguration away — it cannot be expressed. Any destination outside your own registrable domain uses an ordinary HTTP redirect, which shows the visitor where they are going.

Honesty

What we do not claim

Trust pages usually end with a row of badges. This one does not, because the badges would not be real.

Responsible disclosure

Reporting a vulnerability

Good-faith security research is welcome. Here is exactly how to report, what is in scope, and what we commit to in return.

How to report

Email [email protected] with a description of the issue, the steps to reproduce it, and the impact you believe it has. A short proof of concept helps more than a scanner export.

  • Use test accounts you control. If you need a second account to demonstrate an issue, create one — do not use somebody else's.
  • Stop at proof. Do not read, modify, export or delete data that is not yours, and do not degrade service for other people.
  • Give us a reasonable window to fix the issue before publishing. We will tell you when the fix ships and are happy to coordinate a date.

Safe harbour

Research conducted in good faith and within this policy is authorised. We will not initiate or support legal action against you for it, we will not report you to law enforcement for it, and we will not terminate your account for accessing your own test data in the course of it.

If a third party brings action against you for research that followed this policy, we will make it known that your activity was authorised. This is not legal advice and does not override the law where you are — if you are unsure whether something is permitted, ask first.

What we commit to

  • Acknowledge your report within three business days.
  • Give you an assessment and a rough timeline within ten business days.
  • Tell you when the issue is fixed, and confirm the fix with you if you want to check it.
  • Credit you publicly when the fix ships, if you want the credit and are happy to be named.

There is no paid bounty programme. We would rather say so plainly than imply one and disappoint you after you have done the work.

In scope

6
  • The marketing site, dashboard and admin interface.
  • The redirect engine and link interstitials.
  • The public API and webhook delivery.
  • Bio Page rendering, including custom HTML sanitisation.
  • Authentication, session handling and account recovery.
  • Custom domain verification and the owned-content proxy.

Out of scope

7
  • Volumetric denial of service, load testing and traffic amplification.
  • Social engineering of staff, customers or support channels.
  • Physical attacks and attacks on third-party infrastructure we do not operate.
  • Reports produced solely by an automated scanner with no demonstrated impact.
  • Missing headers or best practices with no working exploit path.
  • Self-XSS, and issues that require a compromised device or browser extension.
  • Content posted by customers — use the abuse report form for that.