cybersecurity · beginner · ~15 min · safe pentest lab

Flag Sensitive API Endpoints

Match a fixed allowlist of sensitive route prefixes safely using bounded string comparison, distinguishing a true leading-prefix match from a substring or case look-alike, while denying NULL/empty by default.

Challenge

Attack surface: which routes are high-risk?

When you map a web application's attack surface, some routes are far more dangerous than others. Paths under /admin, /internal, /debug, and /actuator typically expose privileged management, diagnostics, or framework internals. If they are reachable without authentication, they hand an attacker configuration, secrets, or direct control. A defensive gateway wants to flag every request whose path starts with one of these sensitive prefixes so it can require stronger auth or log the hit.

The insecure assumption people make is that a substring check is "good enough". It is not: /api/admin contains admin but is a different, possibly benign route, and /Admin is a different case. The prefix must be matched at the start of the path, byte for byte, and shorter look-alikes like /adm must not match.

Your task

Implement int is_sensitive_endpoint(const char *path). Return 1 if path begins with any prefix in the fixed allowlist /admin, /internal, /debug, /actuator; otherwise return 0. This operates only on a fixed set of path strings baked into the test harness — never a live target. Deny by default: NULL and the empty string are not sensitive and must return 0.

Edge cases to handle

  • NULL path and empty string -> 0.
  • Exact match (path equals a prefix, e.g. /admin) -> 1.
  • Prefix followed by a subpath or query (e.g. /admin/users/1, /debug?x=1) -> 1.
  • Path shorter than the prefix (e.g. /adm) -> 0.
  • Prefix appearing but not at the start (e.g. /api/admin) -> 0.
  • Different case (e.g. /Admin) -> 0.

Input format

A single C string path (the request path), which may be NULL, empty, or arbitrary length.

Output format

An int: 1 if the path starts with a sensitive prefix, else 0.

Constraints

Use only the fixed allowlist {/admin, /internal, /debug, /actuator}. Match prefixes at the start of the string only, exact bytes, case-sensitive. Do not read past the string's terminating NUL. NULL and empty input return 0. No dynamic allocation and no I/O needed.

Starter code

int is_sensitive_endpoint(const char *path)
{
    /* TODO: return 1 if `path` begins with any prefix in the allowlist
       {"/admin", "/internal", "/debug", "/actuator"}, else 0.
       Handle NULL and empty as 0. Match at the START of the string only,
       comparing exactly strlen(prefix) bytes (use strncmp).
       This insecure stub flags everything and must be replaced. */
    (void)path;
    return -1;
}

Common mistakes

Using strstr and matching a prefix anywhere in the path, so /api/admin is wrongly flagged. Using strcmp for exact equality, so legitimate subpaths like /admin/users are missed. Comparing strlen(path) bytes instead of strlen(prefix), so /adm falsely matches /admin or reads past short inputs. Forgetting the NULL check and dereferencing a null pointer. Doing a case-insensitive compare when the requirement is case-sensitive.

Edge cases to handle

NULL -> 0; empty string -> 0; exact prefix (/admin) -> 1; prefix + subpath or query (/admin/users, /debug?x=1) -> 1; path shorter than prefix (/adm) -> 0; prefix not at start (/api/admin) -> 0; different case (/Admin) -> 0.

Background lessons

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