URL-osoite tuntuu yksityiseltä, koska sen pitäisi olla vain niillä, joille sen lähetät. Käytännössä URL-osoite on yksi verkon eniten kirjatuista tiedoista: sen tallentavat, kopioivat ja välittävät eteenpäin järjestelmät, jotka eivät koskaan kysyneet lupaa ja joita et voi tarkastaa. Tässä kerrotaan tarkasti, mihin se vuotaa ja miten linkit suunnitellaan niin, että vuoto ei haittaa. Samasta syystä kertakäyttöisten salaisten linkkien luontityökalu pitää purkuavaimen linkin #-merkin jälkeisessä osassa: se osa ei koskaan päädy palvelimen lokiin.
Mihin URL-osoite vuotaa
- Selaimen historia. Jokainen käyttäjän avaama URL-osoite tallentuu laitteelle, ja se voi synkronoitua muille laitteille sekä selaimen valmistajan synkronointipalveluun.
- HTTP-palvelimen käyttölokit. Useimmat palvelimet kirjaavat oletuksena koko pyynnön polun ja kyselymerkkijonon. Kenellä tahansa, jolla on pääsy lokeihin, on URL-osoite.
- Käänteiset välityspalvelimet ja CDN-palvelut. Cloudflare, Fastly ja oma kuormantasaajasi kirjaavat kaikki URL-osoitteen, kukin omalla säilytysajallaan.
- Lokien keräysjärjestelmät. Käyttölokit pysyvät harvoin yhdellä koneella. Ne lähetetään keskitettyihin loki- ja valvontapalveluihin, ja URL-osoitetta säilyttävien järjestelmien määrä moninkertaistuu.
- Referer-otsakkeet. Kun sivu viittaa kolmannen osapuolen
resurssiin, selain voi lähettää lähdesivun URL-osoitteen
Referer-otsakkeessa. Analytiikkaskriptit, upotetut videot ja mainospikselit saavat sen kaikki. - Selainlaajennukset. Laajennukset, joilla on selaushistorian lukuoikeus, näkevät jokaisen URL-osoitteen, myös #-merkin jälkeisen osan.
- Kirjanmerkkien synkronointi. Kirjanmerkkeihin tallennetut URL-osoitteet synkronoituvat käyttäjän laitteille ja selaimen valmistajan palvelimille.
- Linkkien esikatselutoiminnot. Slack, Teams, iMessage, LinkedIn ja sähköpostiohjelmat hakevat URL-osoitteen esikatselua varten huomaamatta heti, kun viesti lähetetään.
- Yritysten välityspalvelimet ja sähköpostiyhdyskäytävät. Monet organisaatiot tarkastavat, kirjoittavat uudelleen ja kirjaavat jokaisen URL-osoitteen, joka kulkee niiden rajan yli.
Pitääkö HTTPS URL-osoitteen yksityisenä?
Ei. HTTPS salaa URL-osoitteen siirron ajaksi eikä mitään muuta. Molemmat päät tallentavat sen silti. Tämä kannattaa sanoa tarkasti, koska ”yhteys on salattu” luetaan helposti tarkoittavan, että ”URL-osoite on yksityinen”.
TLS salaa polun ja kyselymerkkijonon siirron aikana: selaimen ja palvelimen välissä
verkkoa tarkkaileva ei pysty lukemaan osaa
/reset?token=.... TLS ei kuitenkaan piilota kohdepalvelimen
nimeä (se näkyy DNS-kyselyssä ja useimmissa nykyisissä yhteyksissä TLS:n SNI-kentässä)
eikä mitään yhteyden päissä. Selain tallentaa
koko URL-osoitteen historiaan, ja palvelin kirjoittaa sen
käyttölokiinsa. Siirron aikainen salaus suojaa yhteyden, ei
sen kahta päätä, ja juuri päissä URL-osoitteet vuotavat.
Esimerkki käytännössä: yhden URL-osoitteen elinkaari
Seurataan yhtä arkaluonteista URL-osoitetta, vaikkapa salasanan palautuslinkkiä
https://example.com/reset?token=8f3a91..., lähettämisestä napsautukseen:
- Sähköpostipalvelu säilyttää viestin (URL-osoite mukaan lukien) toistaiseksi, ja sen tietoturvaskanneri voi hakea URL-osoitteen viestin saapuessa.
- Vastaanottajan sähköpostiyhdyskäytävä kirjoittaa URL-osoitteen uudelleen ja kirjaa sen, ja hakee sen uudelleen napsautushetkellä.
- DNS selvittää nimen
example.com. Palvelimen nimi (ei polku) on nyt nimipalvelimen lokeissa. - Verkkopalvelin kirjoittaa koko pyyntörivin käyttölokiinsa. Nginxin tai Apachen oletusarvoinen ”combined”-muotoinen merkintä näyttää tältä:
203.0.113.7 - - [14/Jul/2026:09:12:45 +0000]
"GET /reset?token=8f3a91... HTTP/1.1" 200 5123 "-" "Mozilla/5.0 ..."
- Palvelimen edessä oleva CDN kirjaa saman URL-osoitteen ja säilyttää sitä oman säilytysaikansa.
- Sivun analytiikkaskripti tallentaa sivun URL-osoitteen kyselymerkkijonoineen kolmannen osapuolen järjestelmään, ellei sitä ole erikseen määritetty poistamaan sitä.
- Selain tallentaa URL-osoitteen historiaan ja synkronoi sen.
Yksi lähetys, seitsemän kopiota, vähintään viiden organisaation hallussa. Mikään tästä ei vaatinut hyökkääjää. Verkko toimii juuri niin kuin se on suunniteltu.
Referer-otsake käytännössä
Jos salaisuuden avaussivulla on viittaus mihin tahansa ulkoiseen resurssiin (CDN:n
fonttiin, analytiikkaskriptiin, upotettuun kuvaan), selain voi lähettää
sivun URL-osoitteen kyseiselle palvelulle Referer-otsakkeessa.
Nykyisten selainten oletus on strict-origin-when-cross-origin
(MDN: Referrer-Policy),
joka lyhentää toiselle sivustolle lähtevän viittaustiedon pelkäksi alkuperäksi
(https://example.com/ koko polun sijaan). Se on todellinen
parannus, mutta siihen ei pidä luottaa: saman sivuston sisäisissä pyynnöissä
kulkee yhä koko URL-osoite, sivukohtainen käytäntö voi löysentää oletusta, ja
vanhemmat asiakasohjelmat ja upotetut verkkonäkymät toimivat eri tavoin.
Kaksi käytännön suojakeinoa:
<!-- Strip the referer for outbound requests on the page -->
<meta name="referrer" content="no-referrer" />
Referrer-Policy: no-referrer
Otsake koskee koko sivustoa, meta-tagi vain kyseistä sivua. Käytä molempia kerroksellisen suojauksen vuoksi. Vielä parempi on tarjota arkaluonteiset sivut kokonaan ilman kolmannen osapuolen resursseja, jolloin viittaustietoa ei ole kenellekään lähetettävänä.
Onko tunniste turvallisempi polussa, kyselymerkkijonossa vai #-merkin jälkeisessä osassa?
Vain #-merkin jälkeinen osa jää pyynnön ulkopuolelle, joten vain se jää pois palvelimen lokeista. Polku ja kyselymerkkijono ovat tässä samanarvoiset. Se, mihin kohtaan URL-osoitetta tunniste sijoitetaan, ratkaisee, kuka sen näkee:
| Sijainti | Lähetetäänkö palvelimelle? | Palvelimen lokeissa? | Referer-otsakkeessa? | Selaimen historiassa? |
|---|---|---|---|---|
Polku (/s/abc123) | Kyllä | Kyllä | Riippuu käytännöstä | Kyllä |
Kyselymerkkijono (?token=abc123) | Kyllä | Kyllä | Riippuu käytännöstä | Kyllä |
#-merkin jälkeinen osa (#abc123) | Ei | Ei | Ei | Kyllä |
#-merkin jälkeinen osa todella eroaa muista: RFC 3986:n kohdan 3.5 mukaan se käsitellään selaimessa eikä sitä koskaan liitetä HTTP-pyyntöön. Siksi päästä päähän -salausta käyttävät tekstinjakopalvelut sijoittavat purkuavaimen juuri siihen: palvelin ei kirjaimellisesti koskaan saa sitä. Näkymätön se ei silti ole: selaimen historia, laajennukset ja mikä tahansa sivulla ajettava JavaScript voivat lukea sen. Polun ja kyselymerkkijonon ero taas ei vaikuta yksityisyyteen lainkaan, sillä molemmat päätyvät samoihin lokeihin.
Salasanan palautustunnisteiden ongelma
Arkaluonteiset tunnisteet URL-osoitteissa ovat tunnettu haavoittuvuusluokka. MITREn CWE-598 (”Use of GET Request Method With Sensitive Query Strings”) kuvaa juuri tämän: kyselymerkkijonojen arkaluonteiset tiedot päätyvät lokeihin, historiaan ja viittaustietoihin siirron salauksesta riippumatta. Siksi hyvin rakennetut salasanan palautusprosessit eivät koskaan luota pelkästään URL-osoitteen salassa pysymiseen. Niissä tunniste on kertakäyttöinen, lyhytikäinen ja sidottu seuraavaan toimenpiteeseen (uuden salasanan asettamiseen), joten lokista kolme viikkoa myöhemmin löytynyt tunniste on arvoton.
Tästä seuraa yleinen opetus: URL-osoitetta ei yleensä voi pitää poissa lokeista, mutta lokiin kirjatun URL-osoitteen voi tehdä arvottomaksi ennen kuin kukaan lukee sen.
Miten suunnitellaan URL-osoitteita, joiden vuotaminen ei haittaa
Oleta, että jokainen luomasi URL-osoite päätyy lopulta jonnekin, minne sen ei pitänyt päätyä, ja suunnittele niin, ettei sillä ole merkitystä:
- Kertakäyttöisyys. Salaisuus tuhoutuu ensimmäisen onnistuneen avauksen jälkeen, joten vuotanut URL-osoite ei enää toimi, kun se ilmestyy jonkun historiaan.
- Lyhyt voimassaoloaika. Rajaa vuotoikkunaa. URL-osoite, joka toimi viisi minuuttia, on paljon vähemmän arvokas kuin viikon toiminut.
- Erillistä kanavaa pitkin välitetty salalause. Vaadi salaisuus, joka ei koskaan ollut URL-osoitteessa. Silloin pelkkä URL-osoite, joka on ainoa lokeissa oleva tieto, ei riitä.
- Erota haku ja näyttäminen. Palauta
GET-pyyntöön vain metatiedot ja luovuta sisältö vasta erilliselläPOST-pyynnöllä, jotta esikatselurobotit ja skannerit eivät voi kuluttaa salaisuutta. - Ei kolmannen osapuolen resursseja arkaluonteisilla sivuilla, ja lisäksi
Referrer-Policy: no-referrerja<meta name="robots" content="noindex">. - Peitä salaisuuksien reitit omissa lokeissasi. Nginxissä pyynnön URI
muunnetaan ennen kirjaamista (katso
log_format-direktiivi ngx_http_log_module -moduulin ohjeista):
map $request_uri $loggable_uri {
~^/s/ "/s/[redacted]";
default $request_uri;
}
log_format redacted '$remote_addr - $remote_user [$time_local] '
'"$request_method $loggable_uri" $status';
access_log /var/log/nginx/access.log redacted;
Hallitset vain omia lokejasi. CDN:n, välityspalvelimen ja selaimen kopiot jäävät, ja juuri siksi tämän luettelon kolme ensimmäistä kohtaa kantavat suurimman osan painosta.
Miten tämä näkyy salaisissa linkeissä
Tämän uhkamallin takia LinkPilotin salaiset linkit toimivat niin kuin
toimivat: URL-osoitteen oletetaan väistämättä vuotavan, joten pelkkä URL-osoite ei
koskaan riitä. GET-pyyntö palauttaa vain metatiedot. Sisällön saa vain
erillisellä POST-pyynnöllä, jonka voi lisäksi suojata salalauseella, josta
selain laskee SHA-256-tiivisteen. Tuhoutuneet, vanhentuneet ja mitätöidyt salaisuudet
palauttavat HTTP-tilakoodin 410, ja niiden sisältö on ylikirjoitettu peruuttamattomasti. Näyttämisvastauksissa
on Cache-Control: no-store, ja avaustapahtumiin kirjataan IP-osoitteesta
tiiviste, jonka suola vaihtuu päivittäin, eikä itse osoitetta.
Yksi rajoitus kerrotaan suoraan
tietoturva-arkkitehtuuria käsittelevällä sivulla: purkuavain
kulkee linkin #-merkin jälkeisessä osassa, joten koko linkkiä on kohdeltava
salaisuutena. Juuri tästä vaarasta tämä artikkeli kertoo. Lyhyt
voimassaoloaika, tuhoutuminen lukemisen jälkeen ja erillistä kanavaa pitkin välitetty salalause rajoittavat
vahinkoa, kun linkki vuotaa.
Päivitys 29. syyskuuta 2026: tässä kappaleessa sanottiin alun perin, ettei LinkPilot tarjoa päästä päähän -salausta. Nykyään tekstisisältö salataan selaimessa, liitteet mukaan lukien.
Kokeile ilmaiseksi, ei rekisteröitymistä
Itsetuhoutuva viesti
Lähetä muistiinpano, joka katoaa, kun se on luettu kerran.
Rajoitukset
URL-osoitteen suunnittelu ei korjaa kaikkea. Se ei vaikuta siihen, mitä vastaanottaja tekee luvallisen avauksen jälkeen, se ei poista kopioita, jotka kolmansilla osapuolilla jo on, eikä se pelasta URL-osoitetta, jossa henkilötiedot ovat näkyvillä. Jos käyttäjän sähköpostiosoite on kyselymerkkijonossa, mikään voimassaoloaika ei poista sitä lokeista. Pysyvä sääntö: älä koskaan laita URL-osoitteeseen tietoa, joka pitäisi myöhemmin poistaa, koska URL-osoitetta on käytännössä mahdotonta poistaa kaikkialta, minne se on kopioitu. Suunnittele sen sijaan URL-osoitteita, jotka ovat vuotaessaan arvottomia.
Lisälukemista
- Miten kertakäyttöiset salaiset linkit toimivat
- Linkkiskannerit ja kertakäyttöiset salaisuudet
- Salasanojen turvallinen jakaminen: 5 tapaa vertailussa
