De helft van de pagina wordt weergegeven, één stylesheet staat grijs in het Netwerk-paneel, en de VPN-client meldt nog steeds een gezonde tunnel. Alle drie de waarnemingen kloppen tegelijk, want de browser heeft een verzoek van de pagina beoordeeld en de tunnel had bij dat oordeel geen stem. Wat de zaak sluit is een beslissing en geen instelling: repareer de verwijzing, escaleer hem naar wie de host bezit, of laat de afhankelijkheid vallen. Elk van die opties heeft een goedkope test, en de verkeerde kiezen kost een supportronde.

Waarom de tunnel een subresource niet kan dekken

Gemengde inhoud begint met een HTTPS-document dat een subresource via gewoon HTTP opvraagt. Elke URL wordt op zijn eigen schema beoordeeld, dus de bescherming van het bovenliggende document strekt zich nooit uit tot een kindverzoek. Versleuteling die onder de browser wordt toegevoegd verandert wat er over de lijn gaat, niet het http:// dat de markup vroeg.

Huidige browsers sorteren deze verzoeken in twee groepen en behandelen ze verschillend. Scripts, stylesheets, iframes en aanroepen via fetch, XMLHttpRequest of WebSocket worden ronduit geweigerd, zonder eerst een upgrade-poging. Afbeeldingen, audio en video worden herschreven naar https:// en opnieuw opgevraagd, en het laden wordt afgebroken wanneer die veilige fetch faalt. Een subresource-URL waarvan de host een kaal IP-adres is, is vrijgesteld van upgraden, dus een HTTP-afbeelding op een IP-host blijft geblokkeerd in plaats van stilletjes gerepareerd. De splitsing, inclusief die uitzondering aan de upgradebare kant, staat in Mozilla's gids voor gemengde inhoud. Chrome past een vergelijkbare weigering toe op onveilige downloads die vanaf een veilige pagina starten, waardoor een PDF-link kan sterven terwijl de omringende pagina intact lijkt.

De grijze rij is dus het bewijs dat de controle werkt, niet het bewijs dat de tunnel platte tekst heeft gelekt. Behandel de rij als een bevinding die naar één verwijzing wijst en niet naar de hele pagina.

Bepaal wie de onveilige verwijzing bezit

Sorteer de aanstootgevende URL op waar hij wordt gemaakt voordat je iets bewerkt. Dat antwoord bepaalt of je vandaag een oplossing kunt uitrollen, of een leverancier er een moet uitbrengen, of de afhankelijkheid de pagina moet verlaten. Lees het uit de kolom Initiator in het Netwerk-paneel, want de markup op het scherm wordt vaak tijdens runtime samengesteld.

Waar de URL vandaan komtWie hem kan oplossenEerste stap
Hardgecodeerd in een template of partial die je uitroltJijVervang hem door de https://-vorm en leeg daarna de cache
Geïnjecteerd door een tagmanager of een leveranciersbundelDe leverancier, met jouw ticketStuur de exacte URL, het verzoektype en de console-regel
Alleen op poort 80 geserveerd zonder TLS-listenerDe eigenaar van de hostVraag om TLS, zet er iets van jezelf voor, of laat hem vallen

Wanneer de host al op 443 antwoordt en alleen de verwijzing http zegt, is de reparatie lokaal: wijzig de verwijzing, leeg de paginacache en bevestig dat de rij https wordt. Een host die alleen op poort 80 luistert, kun je niet door bewerken compliant maken, dus de resource verhuist, krijgt iets van jou ervoor, of verdwijnt. Een URL die door een tagmanager is geïnjecteerd blijft verschijnen, ook al is je eigen template schoon, en dat geval hoort in een ticket met de exacte URL en de console-regel erbij. Medewerkers vertellen dat ze onveilige inhoud moeten toestaan is geen van deze opties, want dat schakelt de controle uit voor elke site die dat browserprofiel bezoekt.

Repareer de verwijzing in plaats van de browserinstelling

Herlaad de falende flow met het netwerklogboek bewaard en filter het paneel op de host die je verdenkt. De console noemt de URL en de directive, wat beslist of een verzoek is geweigerd of geüpgraded voordat je een template aanraakt.

curl -sSI https://cdn.example.org/vendor.js | head -n 1
curl -sS -o /dev/null -w '%{http_code} %{url_effective}\n' -L https://cdn.example.org/vendor.js

Twee ondersteunende controles zijn de moeite waard, en geen ervan vervangt de reparatie. Een Content-Security-Policy-header met upgrade-insecure-requests laat de browser http-subresource-URL's herschrijven voordat ze de pagina verlaten, wat oude verwijzingen vangt die je nog niet hebt gevonden. Het herschreven verzoek faalt nog steeds wanneer de doelserver geen HTTPS levert, dus de header verandert alleen welke URL de browser probeert. HSTS werkt per host, wat betekent dat een beleid op je eigen domein niets doet voor een CDN van een derde partij dat de header nooit heeft gestuurd. Na een templatewijziging leeg je de paginacache en zoek je in de gerenderde HTML naar de oude hostnaam, want dezelfde URL kan ook via een partial, een vertaalstring of een databaseveld binnenkomen.

Volg ook redirects, want een keten die bij https:// begint kan op een http://-locatie landen en de browser beoordeelt de laatste hop. De -L vorm van het tweede commando hierboven print die effectieve URL voor je. Als de laatste hop gewoon http is, is de verwijzing nog steeds fout, ook al zag de link die je hebt bewerkt er prima uit.

Bevestig de pagina met de console en het netwerkpaneel

Herlaad met de cache uitgeschakeld en doorloop de flow opnieuw, inclusief de knoppen die inhoud op aanvraag laden. Een eerste paginalaad verbergt lazy widgets, kaarttegels en playerscripts die pas na een klik verschijnen. De console hoort geen mixed-content-items te bevatten en elke rij die je hebt aangeraakt hoort https te tonen. Leg de console en de verzoekrij vast voordat je het ticket sluit, want die toestand is na de volgende deploy moeilijk te reconstrueren.

Wanneer de resource van iemand anders is, stuur je vier dingen: de exacte URL, het verzoektype, de console-tekst en de pagina waar hij verschijnt. Verwijder sessie-identifiers uit alles wat je in een ticket plakt. Een melding die alleen zegt dat afbeeldingen kapot zijn, geeft de eigenaar niets om op te zoeken.

De tunnel doet ondertussen zijn eigen werk, terwijl de oplossing zit in de verwijzing die het verzoek heeft gemaakt. Zoek na de deploy nog eens in het template en de leveranciersbundel naar de hostnaam, en sluit de zaak pas als er geen geblokkeerd mixed-content-item meer in de console staat.

Gerelateerde artikelen