← All solutions

The Passenger Who Doesn't Exist - Solution

SkyStack passengers checked in successfully, held valid boarding passes, and still failed at the gate with PASSENGER NOT FOUND. The pass was real. The gate reader and check-in service computed different pax_key values from the same documented name.

1. Reproduce The Failure

Start with the Boarding Pass Tester.

Simple names pass, but accented names can fail:

ANA                  -> passes
ANA MULLER-SCHMIDT  -> passes
ANÄ MULLER-SCHMIDT -> fails

The failure is not that the boarding pass signature is invalid. The reader accepts the pass, computes a lookup key, and then cannot find that key in the manifest.

2. Compare The Logged Keys

Both services log a pax_key:

For affected passengers, those two 12-character hex strings differ. Nothing crashes and nothing logs an error because each service is internally consistent.

3. Identify The Three Derivation Differences

The key is derived from the passenger name field plus the global salt:

sha256(f"{salt}:{field}")[:12]

The salt is:

gate-7f3a91

The two services disagree in three ways.

Check-in derives the manifest key like this:

NFC -> truncate to 20 characters -> hash without case folding

The gate reader derives the lookup key like this:

NFD -> truncate to 20 bytes -> uppercase -> hash

All three differences matter:

4. Ignore The Visible Off-By-One Decoy

For the reference passenger, the displayed fields look like a simple truncation bug:

check-in field: Lévi/Shay Sofia SR R
gate field:     LÉVI/SHAY SOFIA SR

That is only the visible part. Fixing truncation alone still produces the wrong key because the normalization and case-folding steps also affect the hash input.

5. Reconstruct The Gate Algorithm

Use the vendor strings, crash-core excerpt, and logs to reconstruct the reader side:

import hashlib
import unicodedata

SALT = "gate-7f3a91"

def gate_pax_key(documented_name: str) -> str:
    nfd_name = unicodedata.normalize("NFD", documented_name)
    field_bytes = nfd_name.encode("utf-8")[:20]
    field = field_bytes.decode("utf-8", errors="ignore").upper()
    return hashlib.sha256(f"{SALT}:{field}".encode("utf-8")).hexdigest()[:12]

The exact order is important: normalize first, truncate bytes second, uppercase third, hash last.

6. Calibrate With The Oracle Passenger

Before submitting your own key, validate the implementation against the one passenger whose raw documented name and reader pax_key are both visible:

pax_4417
documented_name = İlgaz/Zeynep Meriç
gate field = İLGAZ/ZEYNEP MERIC
expected gate pax_key = 25d340322140

If your implementation does not produce:

25d340322140

do not submit yet. You are missing one of the three levers or applying them in the wrong order.

7. Compute Your Passenger Key

Run the verified algorithm on your own documented name from the affected-passenger manifest.

For the worked reference name:

Documented name: Lévi/Shay Sofia SR Renee
Gate field:     LÉVI/SHAY SOFIA SR
pax_key:        d38a63a53199

The submitted flag shape is:

SKY{d38a63a53199}

Your own flag uses your own computed 12-hex key.

8. Root Cause

The root cause was not a bad pass, bad signature, scanner outage, or missing passenger record. It was a lookup-key derivation split between two systems:

For names with diacritics inside the first 20 bytes, those inputs diverged. The reader computed a valid but absent key and reported PASSENGER NOT FOUND.

The challenge has no deploy step. The proof is reproducing the reader's key and submitting it as SKY{<12 hex>}.