cybersecurity · intermediate · ~25 min

Extract the host from a URL safely

Strict URL host extraction with explicit reject rules.

Challenge

Extract just the host from a URL with a strict, conservative parser — URL parsing is a notorious CVE source, and writing one teaches what vetted libraries reject and why.

Task

Implement int extract_host(const char *url, char *out_host, size_t cap) that copies the host into out_host, NUL-terminated and capped to cap-1 bytes.

Input

  • url: a NUL-terminated URL of the form scheme://host[:port][/path][?query][#fragment]. The grader passes fixed strings.
  • out_host, cap: the output buffer and its capacity.

Output

Returns int: 1 on success (writing the host), or 0 on any failure.

Example

extract_host("http://example.com/foo")          ->   1, out_host = "example.com"
extract_host("https://api.example.com:8443/v1") ->   1, out_host = "api.example.com"
extract_host("http://127.0.0.1")                ->   1, out_host = "127.0.0.1"
extract_host("file:///etc/hosts")               ->   0   (empty host)
extract_host("not-a-url")                        ->   0   (no ://)
extract_host("http://user:pw@evil/foo")          ->   0   (userinfo refused)

Edge cases

  • Missing scheme or missing :// returns 0.
  • An empty host returns 0.
  • A host that does not fit in out_host returns 0.

Rules

  • The host starts after :// and ends at the first /, :, ?, #, or end of string.
  • Refuse (return 0) any URL containing userinfo (user:pass@host) — a known XSS/SSRF vector — rather than parsing it.
  • No external parsers; pure C scanning with a cap-aware copy.

Why this matters

URL parsing is a notorious source of security bugs (CVEs in nginx, curl, browsers). Real production code uses a vetted library. But understanding the structure — and writing a strict, conservative parser — teaches you what those libraries are doing and why they reject so many edge cases.

Input format

A NUL-terminated url, an output buffer out_host, and its capacity cap.

Output format

An int: 1 with the host in out_host, or 0 on any failure.

Constraints

Refuse no-scheme, empty-host, userinfo, and over-capacity hosts. Pure C; cap-aware copy.

Starter code

#include <stddef.h>
int extract_host(const char *url, char *out_host, size_t cap) { /* TODO */ return 0; }

Common mistakes

Accepting userinfo and using it as the host. Forgetting to handle the optional :port. Not capping the copy at cap-1.

Edge cases to handle

Empty URL; URL with no path; IPv4 literal; userinfo (must reject).

Complexity

O(strlen(url)).

Background lessons

Up next

Solve this exercise in the browser editor — compile and run against the test harness, no setup required.