Säkerhet
Vår säkerhetsmodell i en mening: det finns ingenting på en server att attackera. Allt nedan kan falsifieras från dina DevTools.
Arkitektur
Generatorn är en statisk single-page-applikation som serveras från Cloudflare Pages: inga användarkonton, ingen autentisering och ingen backend-kodväg någonstans i genereringsflödet. Alla QR-generings-, kodnings-, skannings- och renderingsoperationer körs helt i din webbläsare. En liten serverlös endpoint finns vid sidan om och listas här snarare än döljs: /api/contact (kontaktformuläret, som lagrar det du skickar in i Cloudflare D1 och mejlar det till oss). Den anropas inte medan du skapar en QR-kod; URL-säkerhetskontrollen är en separat produkt på check.qr.abundera.ai. Kontrollera om en QR-kod är säker
Hotmodell
Eftersom generatorn varken samlar in, lagrar eller överför användardata (de två endpointarna ovan hanterar bara det du uttryckligen skickar till dem) gäller inte de vanligaste webbapp-hoten — lösenordsstöld, databasintrång, sessionskapning, serverinjektion, för den. Den återstående attackytan är det statiska tillgångspaketet (HTML, CSS, JavaScript) som serveras från vår origin. Vi utformar med antagandet:
- Origin-kompromiss: en angripare ersätter en av våra paketerade tillgångar med en skadlig. CSP nedan begränsar skaderadien; cache-buster-tokens gör återgång till en känd fungerande version enkel.
- Användarinmatning: QR-nyttolaster, vCard-namn, WiFi-lösenord, batch-CSV-rader, skannat bildinnehåll. Varje inmatningsväg behandlas som ej betrodd när den renderas tillbaka till DOM.
- Användarbilder: vCard-foto-URL:er och logotypuppladdningar. Bilder renderas till en canvas och bäddas aldrig in i DOM som rå markup.
- Tredjeparts webbläsartillägg: utanför scope. Om ett tillägg i din webbläsare har behörighet att modifiera varje sida kan det modifiera vår. Våra garantier gäller när sidan laddas omodifierad.
Content Security Policy — per direktiv
Policyn nedan läses från den driftsatta _headers-filen när den här sidan byggs, så den kan inte glida isär från det kanten faktiskt skickar. Verifiera den i svarshuvudena för valfri begäran.
Content-Security-Policy:
default-src 'self';
script-src 'self' https://abundera.ai 'wasm-unsafe-eval' https://challenges.cloudflare.com;
worker-src 'self' blob:;
style-src 'self' 'unsafe-inline' https://abundera.ai;
font-src 'self';
img-src 'self' data: blob: https:;
connect-src 'self' https: https://challenges.cloudflare.com;
frame-src 'self' https://challenges.cloudflare.com;
frame-ancestors 'none';
base-uri 'self';
form-action 'self'Vad varje direktiv tillåter oss att göra och var det kompromissar:
default-src 'self'— det hårda golvet. Allt vi inte uttryckligen tillåter förblir same-origin.script-src 'self' https://abundera.ai 'wasm-unsafe-eval' https://challenges.cloudflare.com— inget inline<script>, ingeteval().abundera.aiär vår egen förälderdomän och serverar ett delat skript, språkväljaren.challenges.cloudflare.comär Turnstile-widgeten som bara används på /contact/.'wasm-unsafe-eval'krävs av vår QR-encoderbiblioteks WebAssembly-kompileringsväg; det tillåter INTE traditionellteval(). Vår pre-deploy-kontroll skannar varje HTML-sida för inline-skript och misslyckas bygget.style-src 'self' 'unsafe-inline'— en verklig eftergift. Vår QR-förhandsvisning beräknar pixelnivåfärger inline (style-attribut på enskilda moduler). En hash-baserad tillåtelselista skulle fungera men misslyckas vid stiluppdatering utan deploy. Avvägning: vi accepterar den något svagare stylingpolicyn; styling kan ändå inte exfiltrera data (CSS har ingenconnect-src-räckvidd).img-src 'self' data: blob: https:—data:för inline QR-renderingar,blob:för export-nedladdnings-URL:er,https:för användarangivna vCard-foto- och avatar-URL:er. Användarangivna URL:er exekveras aldrig, de renderas bara. Var medveten om att det här direktivet också är en utgående kanal: vilket skript som helst som körs på sidan skulle kunna begära en bild från vilken HTTPS-värd som helst och lägga data i URL:en. Vi accepterar det eftersom funktionen behöver det, och vi säger det här istället för att beskriva policyn som vattentät.connect-src 'self' https: https://challenges.cloudflare.com— den man ska läsa noga.https:är en schemakälla: den låterfetch(), XMLHttpRequest, WebSocket över TLS, EventSource ochsendBeacon()nå vilken HTTPS-origin som helst, inte bara sådana du skrev in. Den finns där så att vCard-fotofältet och URL-säkerhetskontrollen kan hämta en adress du klistrat in. Den förhindrar inte exfiltrering av ett skadligt skript; ingen CSP-direktiv gör det när skriptet redan körs som oss. Det som förhindrar exfiltrering är att vår levererade kod inte gör sådana anrop, vilket du kan se i Network-fliken.frame-src 'self' https://challenges.cloudflare.com— bara Turnstile-widgeten får ramas in.frame-ancestors 'none'— ingen annan webbplats kan bädda in oss. Förhindrar clickjacking.base-uri 'self'— en injicerad skadlig<base>-tagg kan inte omdirigera relativa URL:er till en angripares origin.form-action 'self'— ett injicerat formulär kan bara posta tillbaka till vår origin. Kontaktformuläret är det enda formuläret som skickar något någonstans.
Vad CSP inte kan göra
CSP begränsar varifrån webbläsaren laddar kod. Den granskar inte vad den laddade koden faktiskt gör. Om vår origin blev komprometterad, det första fallet i hotmodellen, skulle angriparens skript köras med samma behörigheter som vårt, inklusive tillåtelserna för connect-src och img-src ovan. Våra försvar mot det ligger uppströms om CSP: driftsättningar går ut via ett enda Cloudflare-konto med avgränsade tokens, tillgångsfilnamn är innehållshashade så att en utbytt fil ändrar varje URL som refererar till den, och service workern cachar bara same-origin GET-svar. Manifestet beskriver webbplatsen som den levereras. Det är inte ett påstående om att ingen webbsida någonsin skulle kunna skicka data någonstans, och vi vill hellre att du håller oss till det snävare, kontrollerbara påståendet.
Olika CSP-policyer gäller för /bio/* (avslappnad img-src för användarangivna avatarer) och /embed/* (avslappnad frame-ancestors för avsiktlig inbäddning). Båda dokumenteras i site/_headers.
Transport- och inramningshuvuden
- HSTS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload— 1 år, alla underdomäner, berättigade för HSTS-förladdningslistan. Nedgradering till HTTP nekas av kompatibla webbläsare. - X-Frame-Options: DENY — redundant med CSP
frame-ancestors, behålls för äldre webbläsartäckning. - X-Content-Type-Options: nosniff — förhindrar MIME-förvirringsattacker.
- Referrer-Policy: strict-origin-when-cross-origin — utgående länkklick avslöjar origin men inte sökvägen.
- Permissions-Policy:
camera=(self), microphone=(), geolocation=()— kamera tillåten endast för vår egen skanner; mikrofon och plats uttryckligen nekade även om inbäddade.
Service worker
Vår service worker (site/sw.js) cachar endast same-origin-tillgångar. Fetch-hanteraren avvisar uttryckligen cross-origin-begäranden och icke-GET-metoder — du kan läsa logiken i /sw.js (källan levereras tillräckligt ominifierad för att följa med). Cache-skrivningar är inlindade i event.waitUntil() så de kan inte tappas mitt under navigering.
Inmatningssanering
Varje renderingsväg som accepterar användarinmatning behandlar den som ej betrodd text:
- QR-nyttolastförhandsvisningar använder
textContent, inteinnerHTML. - Delningsmål (urklipp,
navigator.share()) skickar användartext som en sträng, aldrig som markup. - SVG-exporter genereras från vårt encoderbibliotek; användarinnehåll är base64-kodat till
<image>xlink:href, inte injicerat som SVG-element. - Utskriftsförhandsvisningar använder en blob-URL, inte
document.write(). - localStorage-parsning är inlindad i
try/catch— en korrupt post ger ett nytt tomt standardvärde, aldrig ett undantag som kan rullas upp till en aktiv kodväg. - Användarangivna URL:er som visas som "Öppna länk"-knappar är begränsade till
http(s)://—javascript:- ochdata:-scheman avvisas.
Cross-origin bildinhämtning
När en användare klistrar in en https:-URL som vCard-foto eller logotyp hämtar webbläsaren den med hänsyn till CORS och vår CSP:s img-src-tillåtelselista. Bilden renderas till en canvas. Den blir aldrig live DOM, körs aldrig som kod och når aldrig vår origin — hämtningen är webbläsare → fjärrbild, och resultatet målas klientsidan. En angripare som kontrollerar en fjärrbild-URL kan spåra att URL:en laddades (en loggpost på deras egen server) men kan inte exfiltrera något från vår sida.
Subresource Integrity (SRI)
All JavaScript och CSS vi levererar är same-origin. Vi laddar inte tredjepartsskript eller stilmallar, så SRI-hashar är inte tillämpliga. Om vi någonsin laddar en tredjepartstillgång levererar vi ett SRI integrity-attribut på den och dokumenterar hash-uppdateringsprocessen på den här sidan.
Rapportera en sårbarhet
Om du upptäcker ett säkerhetsproblem som påverkar Abundera QR — vare sig det gäller vår kod, vår deployment eller ett beroende vi levererar — vänligen rapportera det privat till security@abundera.ai. Vi strävar efter att triagera inom 72 timmar. Du kan också nå oss via kontaktuppgifterna i vår /.well-known/security.txt-fil.
Ingen bug bounty (ännu)
Vi erbjuder för närvarande inte betalda bounties, men varje bekräftad giltig rapport får erkännande i ändringsloggen och vårt offentliga tack.
Verifiera vad som helst ovan
Varje påstående på den här sidan kan falsifieras från din webbläsares DevTools utan att lita på oss:
- CSP: DevTools → Nätverk →
/→ Huvuden. LäsContent-Security-Policy-svarshuvudet. - HSTS + säkerhetshuvuden: samma plats — alla
Strict-Transport-Security,X-Frame-Optionsetc. är synliga. - Inga utgående anrop: DevTools → Nätverk → Fetch/XHR. Generera en QR. Se antalet förbli noll.
- Service worker-scope: DevTools → Applikation → Service Workers. Verifiera skriptkällan och listan över cachade tillgångar.
- Inga cookies: DevTools → Applikation → Cookies. Tom.
- Fullständig genomgång: manifests verifieringsavsnitt.
Kontakt
Säkerhetsupplysningar: security@abundera.ai