Heads up alla som använder olika appar i blindo:
Säkerhetsgranskning: tesla-order-status
Repository: chrisi51/tesla-order-status
Granskad version: p1.2.5
Datum: 2026-03-11
Utfört och (dåligt) översatt av Claude Opus 4.6
Jag har gått igenom hela kodbasen och sammanställt de säkerhetsproblem jag hittade. Totalt 16 fynd, sorterade efter allvarlighetsgrad.
Kritiskt — Leveranskedjan / fjärrkörning av kod
1. Osignerad auto-uppdaterare som kör godtycklig kod
Filer: app/update_check.py:128–154, hotfix.py:36–70
Både auto-uppdateraren och hotfix-skriptet laddar ner en ZIP från GitHub, packar upp den över hela installationskatalogen och — i auto-uppdaterarens fall — kör omedelbart om processen via os.execv().
Det finns ingen signaturverifiering, ingen checksumma-validering, ingen hash-pinning. Om en angripare kan utföra en MITM-attack (t.ex. på publikt Wi-Fi eller via DNS-förgiftning), kompromettera GitHub-kontot, eller få in skadlig kod via en pull request, får de full kodexekvering på varje användares maskin som kör uppdateraren.
perform_update() avslutas med:
Kod: Markera allt
os.execv(sys.executable, [sys.executable] + sys.argv)
Skriptet startas alltså om med den nyss överskrivna koden utan att verifiera att innehållet är säkert. Inställningen "automatically" gör detta helt tyst.
Allvarlighetsgrad: Kritisk
Rekommendation: Pinna SHA-256-hashar per release eller verifiera GPG-signaturer. Använd helst ett signerat manifest. Kör aldrig os.execv() direkt efter uppackning av opålitlig kod.
2. Zip Slip — path traversal vid uppackning
Filer: hotfix.py:62, update_check.py:140
Båda filerna använder extractall() eller shutil.unpack_archive() utan att kontrollera att de uppackade filnamnen håller sig inom målkatalogen. Ett manipulerat arkiv kan innehålla sökvägar som ../../../.bashrc och skriva över godtyckliga filer.
Allvarlighetsgrad: Kritisk (i kombination med den osignerade uppdateraren)
Rekommendation: Validera varje sökväg innan uppackning:
Kod: Markera allt
for member in zf.namelist():
resolved = (Path(tmpdir) / member).resolve()
if not str(resolved).startswith(str(Path(tmpdir).resolve())):
raise ValueError(f"Path traversal detected: {member}")
3. Godtycklig kodexekvering via migrationshanteraren
Fil: app/utils/migration.py:39–44
Migrationshanteraren laddar och kör dynamiskt alla .py-filer i app/migrations/ via importlib. Eftersom auto-uppdateraren tyst kan leverera nya migrationsfiler (se fynd #1), är detta en andra exekveringsväg för injicerad kod.
Allvarlighetsgrad: Hög (beroende av #1)
Rekommendation: Migrationer bör vara deklarativa datatransformeringar, inte godtycklig Python. Om kodexekvering krävs, signera migrationsfilerna individuellt.
Högt — Token- och autentiseringssäkerhet
4. Tokens sparas som klartext-JSON utan filrättighetsbegränsningar
Fil: app/utils/auth.py:84–86
Teslas OAuth-tokens (inklusive den långlivade refresh-tokenen) skrivs till data/private/tesla_tokens.json som ren JSON. Inga filrättigheter sätts, så på fleranvändarsystem innebär standardvärdet för umask (typiskt 0022) att andra användare kan läsa filen. En stulen refresh-token ger bestående åtkomst till offrets Tesla-konto.
Allvarlighetsgrad: Hög
Rekommendation: Sätt restriktiva rättigheter direkt efter skapandet (os.chmod(path, 0o600)). Överväg att kryptera tokens i vila eller använda OS-nyckelringen (t.ex. via keyring-biblioteket).
5. JWT-validering kontrollerar bara utgångstid — ingen signaturverifiering
Fil: app/utils/auth.py:96–98
Kod: Markera allt
def _is_token_valid(access_token):
jwt_decoded = json.loads(base64.b64decode(access_token.split('.')[1] + '==').decode('utf-8'))
return jwt_decoded['exp'] > time.time()
JWT-payloaden avkodas för att kontrollera exp-fältet, men den kryptografiska signaturen verifieras aldrig. Om tokenfilen manipuleras (t.ex. av skadlig programvara) accepterar skriptet en förfalskad token med framtida utgångstid. Padding-hacket + '==' kan dessutom ge felaktig avkodning för vissa payloads.
Allvarlighetsgrad: Medel–Hög
Rekommendation: Använd base64.urlsafe_b64decode med korrekt padding-beräkning. Överväg att verifiera JWT-signaturen mot Teslas publika nycklar, eller åtminstone behandla ett misslyckat API-anrop som signal att autentisera om.
6. OAuth state-parametern valideras aldrig
Fil: app/utils/auth.py:23, 64–70
OAuth state-parametern genereras och skickas i auktoriserings-URL:en, men efter att användaren klistrar in omdirigerings-URL:en kontrolleras aldrig det returnerade värdet. Det här motverkar CSRF-skyddet som state-parametern är avsedd att ge.
Allvarlighetsgrad: Medel
Rekommendation: Extrahera och jämför state-parametern från omdirigerings-URL:en med det genererade värdet innan autentiseringen fortsätter.
Medel — Dataexfiltrering och integritet
7. Beständigt fingeravtryck i telemetri
Filer: app/utils/telemetry.py:74–134, app/config.py:14
När telemetri är aktiverat skickas en JSON-payload till tesla-order-status-tracker.de/push/telemetry.php med ett beständigt installationsfingeravtryck, pseudonymiserade order-ID:n, Tesla-modell, locale, CLI-flaggor och skriptversion. Fingeravtrycket genereras en gång och återanvänds för alltid, vilket möjliggör långsiktig spårning av individuella installationer.
Allvarlighetsgrad: Medel
Rekommendation: Rotera fingeravtrycket periodiskt. Dokumentera tydligare vilken data som skickas.
8. Påträngande omsamtycke för telemetri
Fil: app/utils/telemetry.py:35–47
Om användaren tackar nej till telemetri frågar skriptet igen var tionde körning. Meddelandet ("Naww, I've counted on you! =(") använder känslomässig press. Det här är ett mörkt mönster som undergräver användarens tillit.
Allvarlighetsgrad: Låg–Medel
Rekommendation: Respektera användarens val. Fråga en gång; erbjud en CLI-flagga eller konfigurationsalternativ för de som ändrar sig.
9. Optionskoder skickas till extern server
Filer: app/utils/option_codes.py:14, app/utils/telemetry.py:124–134
Optionskoder hämtas från och laddas upp till tesla-order-status-tracker.de. Även om enskilda koder inte är känsliga identifierar kombinationen unikt en fordonskonfiguration, och skickas tillsammans med det beständiga fingeravtrycket.
Allvarlighetsgrad: Låg–Medel
Rekommendation: Gör optionskodsrapportering till ett separat opt-in (skilt från generell telemetri).
Medel — Indatavalidering och felhantering
10. Ren except: fångar SystemExit och KeyboardInterrupt
Fil: app/config.py:39
Fångar allt, inklusive SystemExit, KeyboardInterrupt och MemoryError. Det kan dölja kritiska fel och förhindra ordentlig nedstängning.
Allvarlighetsgrad: Låg–Medel
Rekommendation: Använd except Exception: som minimum.
11. Ingen explicit TLS-certifikatsverifiering
Fil: app/utils/connection.py
request_with_retry använder requests.get/post utan att explicit ange verify=True. Även om requests har det som standard skyddar kodbasen inte mot att miljövariabler manipuleras. Värt att tänka på eftersom tokens skickas i Authorization-headers.
Allvarlighetsgrad: Låg–Medel
Rekommendation: Ange verify=True explicit i alla anrop.
12. XML-parsning utan skydd mot entitetsexpansion
Fil: app/update_check.py:72
Atom-feeden parsas med xml.etree.ElementTree som är sårbar för "billion laughs"-attacker (exponentiell entitetsexpansion). Även om GitHub knappast serverar ett skadligt feed kan en MITM-angripare göra det.
Allvarlighetsgrad: Låg–Medel
Rekommendation: Använd defusedxml.ElementTree eller sätt en parser med expansionsbegränsningar.
13. Regex-baserad JSON-reparation i konfigurationsladdaren
Fil: app/config.py:56
Kod: Markera allt
text = re.sub(r",\s*([\]\}])", r"\1", text)
Regexet tar bort avslutande kommatecken för att tolerera felformaterad JSON, men det kan även matcha inuti strängvärden och korrumpera data (t.ex. "tags": "a, }" skulle förvanskas).
Allvarlighetsgrad: Låg
Rekommendation: Använd en JSON-parser som hanterar avslutande komman (t.ex. json5) eller ta bort workarounden.
Lågt — Övrigt
14. Clipboard-injektion med reklam
Fil: app/utils/orders.py:399–403
I share-läge kopieras data tyst till urklipp med en bifogad reklamtext. Även i normalt läge anropas generate_share_output som kopierar till urklipp som bieffekt. Användare kan omedvetet klistra in reklam.
Allvarlighetsgrad: Låg
Rekommendation: Kopiera till urklipp bara när användaren explicit använder --share. Ta bort reklaminjektionen.
15. Okodade värden i URL
Fil: app/utils/orders.py:237–240
order_id, LANGUAGE och COUNTRY interpoleras rakt in i en URL utan URL-kodning. Om något av värdena innehåller specialtecken bryts URL-strukturen.
Allvarlighetsgrad: Låg
Rekommendation: Använd urllib.parse.urlencode eller requests params-dict.
16. Överdriven backoff-fördröjning
Fil: app/utils/connection.py:68
Vid 5xx-fel är retry-fördröjningen 5 ** attempt sekunder (1, 5, 25). 25 sekunders väntan vid tredje försöket är onödigt lång och det saknas ett övre tak samt jitter.
Allvarlighetsgrad: Låg
Rekommendation: Använd exponentiell backoff med jitter och ett rimligt tak.
Sammanfattning
- #1–2 (Kritisk): Osignerad uppdaterare + Zip Slip — leveranskedjeattack som ger fjärrkörning av kod.
- #3 (Hög): Migrationshanteraren kör godtyckliga .py-filer som kan levereras via uppdateraren.
- #4 (Hög): Tokens i klartext utan filrättighetsbegränsningar — ger tillgång till Tesla-kontot.
- #5 (Medel–Hög): JWT-expiry kontrolleras utan signaturverifiering.
- #6 (Medel): OAuth state-parameter valideras aldrig — CSRF-risk.
- #7–9 (Medel): Beständig fingeravtrycksspårning och optionskodsdelning via telemetri.
- #10–12 (Låg–Medel): Bred felhantering, implicit TLS, osäker XML-parsning.
- #13–16 (Låg): Regex-korruption, reklam i urklipp, okodade URL-värden, överdriven backoff.
Tre viktigaste åtgärderna
- Signera eller hasha releaser och verifiera innan uppdateringar tillämpas. Ta bort os.execv() efter blind uppackning.
- Begränsa filrättigheter på tesla_tokens.json till enbart ägaren (0o600) och överväg OS-nyckelringsintegration.
- Validera OAuth state-parametern vid omdirigering för att stänga CSRF-luckan.