Steven
Steven5 min lukuaika

Mac-sovelluksesi myöntää mikrofonin käytön — ja unohtaa sen joka käynnistyksellä

GeekBye pyysi mikrofonin käyttöoikeutta, myönsit sen, ja se toimi. Seuraava käynnistys: poissa. Eikä sovellus näkynyt lainkaan kohdassa Järjestelmäasetukset → Mikrofoni. Syyllinen oli macOS:n turvaominaisuus, joka ajoi sovellusta hiljaa polusta, joka katoaa — tässä on diagnoosi ja yhden kehotteen korjaus.

macOS
Käyttöoikeudet
Ohjelmistokehitys
GeekBye-julkaisut
Mac-sovelluksesi myöntää mikrofonin käytön — ja unohtaa sen joka käynnistyksellä

Tässä on virhe, joka saa sinut epäilemään omia silmiäsi. Asennat GeekByen, se pyytää mikrofonin käyttöä, klikkaat Allow, ja litterointi toimii. Hienoa. Suljet sovelluksen, avaat sen uudelleen seuraavana aamuna — ja se pyytää mikrofonin käyttöä uudelleen. Menet tarkistamaan asetukset kohdasta Järjestelmäasetukset → Tietosuoja ja turvallisuus → Mikrofoni korjataksesi sen käsin, ja GeekBye ei ole edes listalla. Ei estetty. Ei sallittu. Vain poissa, ikään kuin se ei olisi koskaan pyytänyt.

Jokainen yksittäinen palanen näytti oikealta. Kehote oli aito. Käyttöoikeus toimi sillä hetkellä. Sovellus oli asianmukaisesti allekirjoitettu ja notarisoitu oikeilla käyttökuvauksilla. Ja silti myönnetty oikeus haihtui joka käynnistyksellä. GeekBye v2.0.6 korjasi sen — ja perimmäinen syy on yksi ovelimmista asioista, joita macOS tekee suojellakseen sinua.

Ominaisuus, joka piilotti sovelluksen itseltään

Syyllinen on macOS App Translocation, Gatekeeperin turvaominaisuus. Kun lataat sovelluksen ja ajat sen suoraan DMG:stä tai ~/Downloads-kansiostasi — missä tahansa, missä se on vielä "karanteenissa" — macOS ei todellisuudessa aja sitä siitä, missä sen näet. Se kopioi sen läpinäkyvästi satunnaiseen, vain luku -tilassa olevaan polkuun syvälle kansion /private/var/folders/.../AppTranslocation/… alle ja ajaa tuota kopiota. Se on hyvä puolustus: se estää haitallista latausta peukaloimasta viereisiä tiedostoja.

Mutta tässä on törmäys. macOS:n käyttöoikeusjärjestelmä (TCC — se osa, joka seuraa, kuka saa käyttää mikrofoniasi, kameraasi ja näyttöäsi) tunnistaa sovelluksen sen polun ja koodi-identiteetin perusteella. Kun sovellus on siirtynyt (translocated), tuo polku on satunnainen ja tilapäinen. Joten kun myönnät mikrofonin käytön, macOS tallentaa myönnetyn oikeuden tunnollisesti — polkuun, jota ei ole olemassa seuraavalla käynnistyksellä. Avaat sovelluksen uudelleen, macOS siirtää sen eri satunnaiseen polkuun, näkee sovelluksen, josta sillä ei ole mitään tietoa, ja kysyy uudelleen. Ja koska tuo haamupolku ei ole koskaan vakaa sijainti, sovellus ei koskaan ansaitse pysyvää riviä kohdassa Järjestelmäasetukset → Mikrofoni.

Sovellus myönsi käyttöoikeutta haamulle.

Tämä on myös syy siihen, miksi vain osa ihmisistä törmäsi tähän. Jos kopiosi GeekByesta asui jo kansiossa /Applications — koska raahasit sen sinne tai koska se päätyi sinne automaattipäivityksen kautta — ei ole karanteenia, ei siirtymää, polku on vakaa ja kaikki säilyy täydellisesti. Virhe oli näkymätön meille ja kenelle tahansa, joka oli ensimmäisen asennuksensa ohittanut, mikä on juuri sellainen virhe, joka selviää pisimpään.

Korjaus: anna sovellukselle oikea koti

Koska koko ongelma on epävakaa polku, korjaus on saada sovellus vakaalle polulle. v2.0.6 havaitsee, kun GeekBye ajetaan siirtyneenä (tai vain kansion /Applications ulkopuolelta) ja tarjoaa yhden napsautuksen "Move to Applications" (siirrä Ohjelmat-kansioon) — käyttäen macOS:n siirtokutsua, joka kopioi paketin kansioon /Applications ja käynnistää sen sieltä uudelleen. Siitä hetkestä lähtien sovelluksella on kiinteä identiteetti: mikrofonioikeus pysyy, näytön tallennus pysyy, ja GeekBye ilmestyy vihdoin Järjestelmäasetuksiin, missä sen odottaisitkin näkyvän.

Kehote on siitä kohtelias. Se tarjoaa Move to Applications, Not Now (ei nyt) ja Don't Ask Again (älä kysy uudelleen) — ja se muistaa viimeisimmän valinnan, joten sovellus ei koskaan jankuta jollekulle, jolla on tietoinen syy ajaa sitä muualta. Päätös siitä, näytetäänkö kehotetta lainkaan, on eristetty pieniin, puhtaisiin funktioihin (onko tämä koontiversio siirtynyt? onko se kansion /Applications ulkopuolella? vaimensiko käyttäjä sen?) niin, että logiikka on yksikkötestattavissa ilman, että tarvitsee käynnistää oikeaa notarisoitua koontiversiota oikealla karanteeniin joutuneella asemalla.

Sama julkaisu myös yksinkertaisti itse käyttöoikeuskokemusta. GeekBye avasi ennen mukautetun, räätälöidyn sovelluksen sisäisen käyttöoikeusikkunan — muutama sata riviä käyttöliittymää, joka yritti toisintaa jotain, minkä käyttöjärjestelmä jo tekee hyvin. v2.0.6 poisti sen ja nojasi natiiviin macOS-käyttöoikeuskehotteeseen, jota tukee hiljainen, ei-estävä palkki, joka ilmestyy vain silloin, kun vaadittu käyttöoikeus todella puuttuu. Vähemmän koodia, ja käyttäytymistä, jonka käyttäjät jo tunnistavat, koska jokainen muukin Mac-sovellus toimii samalla tavalla.

Osa, josta olen ylpein: todistimme sen ennen kuin uskoimme siihen

Olisi ollut helppoa arvata siirtymä ja julkaista korjaus. Sen sijaan julkaisu toimitti ensin käynnistysdiagnostiikan: käynnistyksen yhteydessä GeekBye raportoi nyt oman suoritettavan tiedostonsa polun ja sen, onko se siirtynyt, onko se kansion /Applications sisällä sekä nykyisen mikrofonin ja näytön käyttöoikeustilan. Tuo telemetria muutti uskottavan teorian vahvistetuksi — tuotantodata osoitti, että altistuneet istunnot ajoivat tosiaan siirtyneistä poluista kansion /Applications ulkopuolella, aivan kuten ennustettiin.

Tuolla järjestyksellä on väliä. "Kehote ilmestyy, mutta käyttöoikeus ei pysy" -tilanteelle on useita mahdollisia selityksiä — allekirjoitusongelma, puuttuva käyttökuvaus, valtuutusongelma, TCC-tietokannan omituisuus. Suljimme API-tason syyt pois (pyyntöpolku oli todistettavasti oikea), ja annoimme sitten oikean maailman datan osoittaa identiteetti-/polkukerrokseen sen sijaan, että olisimme julkaisseet toiveikkaan korjauksen ja toivoneet tukipyyntöjen loppuvan.

Kolme asiaa, jotka tämä virhe opettaa

  1. Käyttöoikeus, joka kysyy mutta ei pysy, on identiteetti-ongelma, ei API-ongelma. Jos pyyntökoodi on oikein ja myönnetty oikeus silti katoaa, lopeta pyynnön uudelleenkirjoittaminen. Kysy, mihin polkuun ja koodi-identiteettiin käyttöjärjestelmä sitoo myönnetyn oikeuden — ja onko tuo identiteetti vakaa käynnistysten välillä.
  2. Julkaise diagnostiikka korjauksen kanssa (tai ennen sitä). Muutama kenttä — mistä ajan, mikä on käyttöoikeustilani — muutti valistuneen arvauksen vahvistetuksi perimmäiseksi syyksi ja kertoi meille tarkalleen, ketkä käyttäjät olivat altistuneet. Instrumentoi epäilemäsi rajapinta ennen kuin paikkaat sen.
  3. Virheet, jotka piiloutuvat kehittäjiltä, ovat niitä, jotka ajavat "väärässä" ympäristössä. Meidän virheemme asui kansiossa /Applications jokaisella kehityskoneella, joten virhe oli meille rakenteellisesti näkymätön samalla kun se osui ensikertalaisiin. Kun raportti ei toistu, ensimmäinen kysymys on mikä on erilaista siinä, missä se ajetaan, ei erehtyykö käyttäjä.

GeekBye v2.0.6 toimitti siirtokehotteen ja diagnostiikan yhdessä. Laajempaa luotettavuuskaarta varten, johon tämä liittyy, katso mitä version 2 todella vaatii (v2.0.0) ja miksi näytön tallennus kaappaa väärän näytön (v2.0.10) — toinen virhe, joka nousi pintaan vain tietyssä ympäristössä. Viereisen pienten yksityiskohtien julkaisun osalta, rauhallinen ohjelmisto: välkyntäkorjaus ja vastaustila-siru (v2.0.3 + v2.0.5).

Aiheeseen liittyvät artikkelit

Ohjelmiston toimittaminen täydellisyyteen asti – anatomia: miten koodikatselmointi löysi sen, mitä testit eivät löytäneet
Steven
Steven5 min lukuaika

Ohjelmiston toimittaminen täydellisyyteen asti – anatomia: miten koodikatselmointi löysi sen, mitä testit eivät löytäneet

Koko GeekBye v2 -sarjassa toistuu sama asia: korjaus läpäisee jokaisen testin kehittäjän koneella, ja sitten koodikatselmointi todistaa, että lähes kaikilla muilla se olisi epäonnistunut. Tämä on yhdeksän julkaisun taustalla oleva työnkulku – katselmointiportti, korjaus-ensin-löydöt ja testaa-ennen-toimitusta-kuri, joka muuttaa lauseen "minulla se toimii" lauseeksi "se toimii".

Ohjelmistokehitys
Prosessi
Koodikatselmointi
Yksi CSS-muuttuja, viisi katselmuskierrosta ja Swift-työkaluketju joka valehteli
Steven
Steven5 min lukuaika

Yksi CSS-muuttuja, viisi katselmuskierrosta ja Swift-työkaluketju joka valehteli

GeekBye v2.0.7 teki koko overlaystä säädettävän läpikuultavan — mikä kuulostaa yhden rivin CSS-muutokselta ja ei todellakaan ollut sitä. Todellinen tarina on siinä, mitä koodikatselmus nappasi: kaksi pintaa jotka kieltäytyivät haalistumasta, tallennuspalkki joka näytti väärältä samalla peittävyydellä, ja käännetty binääri joka heilahti 672 tavua koska omat dokumenttimme kertoivat katselmoijalle väärän Swift-version.

Ohjelmistokehitys
Suunnittelu
Build
Reaaliaikainen transkriptio, kun palomuuri estää WebSocketit
Steven
Steven4 min lukuaika

Reaaliaikainen transkriptio, kun palomuuri estää WebSocketit

Yritysverkot rakastavat sallia HTTPS:n ja tappaa hiljaa WebSocket-päivityksen. Se rikkoo huomaamatta reaaliaikaisen transkription. GeekBye v2.0.8 vaihtaa automaattisesti puhtaaseen HTTPS-siirtoon — ja sen julkaisu paljasti bugin, joka olisi tehnyt koko ominaisuudesta hyödyttömän.

Transkriptio
Verkot
Ohjelmistokehitys