Sikkerhed
Vores sikkerhedsmodel i én sætning: der er intet på en server at angribe. Alt herunder kan falsificeres fra dine DevTools.
Arkitektur
Generatoren er en statisk single-page-applikation, der serveres fra Cloudflare Pages: ingen brugerkonti, ingen godkendelse, og ingen backend-kodesti nogen steder i genereringsflowet. Alle QR-genererings-, kodnings-, scannings- og renderingsoperationer kører udelukkende i din browser. Ét lille serverless-endpoint sidder ved siden af og er nævnt her i stedet for skjult: /api/contact (kontaktformularen, som gemmer det, du indsender, i Cloudflare D1 og mailer det til os). Det kaldes ikke, mens du laver en QR-kode; URL-sikkerhedstjekkeren er et separat produkt på check.qr.abundera.ai. Tjek om en QR-kode er sikker
Trusselsmodel
Fordi generatoren ikke indsamler, gemmer eller transmitterer brugerdata (de to endpoints ovenfor håndterer kun det, du eksplicit sender dem), gælder de mest almindelige webapptrusler — tyveri af legitimationsoplysninger, databasebrud, session-kapring, serverside-injektion — ikke for den. Den resterende angrebsflade er det statiske asset-bundt (HTML, CSS, JavaScript), der serveres fra vores oprindelse. Vi designer med antagelsen om:
- Kompromittering af oprindelsen: en angriber erstatter et af vores medfølgende assets med et ondsindet. CSP nedenfor begrænser skadeomfanget; cache-buster-tokens gør det nemt at rulle tilbage til en kendt god version.
- Brugerleveret input: QR-nyttelaster, vCard-navne, WiFi-adgangskoder, batch-CSV-rækker, scannede billedindhold. Alle inputstier behandles som upålidelige, når de gengives tilbage til DOM'en.
- Brugerleverede billeder: vCard-foto-URL'er og logo-uploads. Billeder gengives til et canvas, aldrig indlejret i DOM'en som rå markup.
- Tredjeparts browserudvidelser: uden for scope. Hvis en udvidelse i din browser har tilladelse til at ændre alle sider, kan den ændre vores. Vores garantier gælder, når siden indlæses uændret.
Content Security Policy — pr. direktiv
Politikken nedenfor læses fra den udrullede _headers-fil, når denne side bygges, så den ikke kan afvige fra det, edge'n sender. Verificer den i svarheaderne for enhver anmodning.
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'Hvad hvert direktiv lader os gøre, og hvor det kompromitterer:
default-src 'self'— det hårde gulv. Alt, vi ikke eksplicit lemper, forbliver same-origin.script-src 'self' https://abundera.ai 'wasm-unsafe-eval' https://challenges.cloudflare.com— ingen inline<script>, ingeneval().abundera.aier vores eget overordnede domæne og leverer ét delt script, sprogvælgeren.challenges.cloudflare.comer Turnstile-widgetten, der kun bruges på /contact/.'wasm-unsafe-eval'er nødvendig for vores QR-enkodningsbiblioteks WebAssembly-kompileringssti; det tillader IKKE traditioneleval(). Vores egen pre-deploy-kontrol scanner alle HTML-sider for inline-scripts og fejler bygningen.style-src 'self' 'unsafe-inline'— en reel indrømmelse. Vores QR-forhåndsvisning beregner farver på pixelniveau inline (style-attributter på individuelle moduler). En hash-baseret tilladelsesliste ville virke, men ville fejle ved enhver stilopdatering uden en deploy. Afvejning: vi accepterer den lidt svagere stilpolitik; styling kan alligevel ikke eksfiltrere data (CSS har ingenconnect-src-rækkevidde).img-src 'self' data: blob: https:—data:for inline QR-gengivelser,blob:for eksport-download-URL'er,https:for brugerleverede vCard-foto- og avatar-URL'er. Brugerleverede URL'er udføres aldrig, de gengives kun. Vær opmærksom på, at dette direktiv også er en udgående kanal: ethvert script, der kører på siden, kunne anmode om et billede fra en vilkårlig HTTPS-host og lægge data i URL'en. Vi accepterer det, fordi funktionen kræver det, og vi siger det her i stedet for at beskrive politikken som vandtæt.connect-src 'self' https: https://challenges.cloudflare.com— den, du bør læse omhyggeligt.https:er en skemakilde: den laderfetch(), XMLHttpRequest, WebSocket over TLS, EventSource ogsendBeacon()nå enhver HTTPS-oprindelse, ikke kun dem, du selv har indtastet. Den er der, så vCard-foto-feltet og URL-sikkerhedstjekket kan hente en adresse, du indsætter. Den forhindrer ikke eksfiltrering fra et ondsindet script, det gør ingen CSP-direktiv, når scriptet først kører som os. Det, der forhindrer eksfiltrering, er, at vores leverede kode ikke laver sådanne forespørgsler, hvilket du kan følge i Network-fanen.frame-src 'self' https://challenges.cloudflare.com— kun Turnstile-widgetten må indlejres.frame-ancestors 'none'— ingen anden side kan indlejre os. Forhindrer clickjacking.base-uri 'self'— et ondsindet injiceret<base>-tag kan ikke omdirigere relative URL'er til en angribers oprindelse.form-action 'self'— enhver injiceret formular kan kun sende tilbage til vores oprindelse. Kontaktformularen er den eneste formular, der overhovedet sender noget nogen steder.
Hvad CSP ikke kan gøre
CSP begrænser, hvorfra browseren vil indlæse kode. Den kontrollerer ikke, hvad indlæst kode gør. Hvis vores oprindelse blev kompromitteret, det første punkt i trusselsmodellen, ville angriberens script køre med de samme tilladelser som vores, inklusive connect-src- og img-src-tilladelserne ovenfor. Vores forsvar mod det ligger opstrøms for CSP: deploys går ud gennem én Cloudflare-konto med afgrænsede tokens, asset-filnavne er indholds-hashede, så en udskiftet fil ændrer hver URL, der refererer til den, og service workeren cacher kun same-origin GET-svar. Manifestet beskriver sitet, som det er leveret. Det er ikke en påstand om, at ingen webside nogensinde kunne sende data et sted hen, og vi vil hellere have, at du holder os til det snævrere, efterprøvelige udsagn.
Forskellige CSP-politikker gælder for /bio/* (lempet img-src for brugerleverede avatarer) og /embed/* (lempet frame-ancestors for intentionel indlejring). Begge er dokumenteret i site/_headers.
Transport + framing-headere
- HSTS:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload— 1 år, alle underdomæner, berettiget til HSTS-forudindlæsningslisten. Nedgraderinger til HTTP afvises af konformante browsere. - X-Frame-Options: DENY — redundant med CSP
frame-ancestors, bevaret for ældre browserunderstøttelse. - X-Content-Type-Options: nosniff — forhindrer MIME-forvirringsangreb.
- Referrer-Policy: strict-origin-when-cross-origin — udgående lænkeklik lækker oprindelsen, men ikke stien.
- Permissions-Policy:
camera=(self), microphone=(), geolocation=()— kamera tilladt kun for vores egen scanner; mikrofon og placering eksplicit afvist, selv hvis indlejret.
Service worker
Vores service worker (site/sw.js) cacher kun same-origin-assets. Fetch-handleren afviser eksplicit cross-origin-anmodninger og ikke-GET-metoder — du kan læse logikken i /sw.js (kildekoden leveres ikke-minificeret nok til at følge med). Cache-skrivninger er pakket ind i event.waitUntil(), så de ikke kan droppes midt i en navigation.
Input-sanitering
Alle renderingsstier, der accepterer brugerinput, behandler det som upålidelig tekst:
- QR-nyttelastforhåndsvisninger bruger
textContent, ikkeinnerHTML. - Delingsmål (udklipsholder,
navigator.share()) sender brugertekst som en streng, aldrig som markup. - SVG-eksporter genereres fra vores enkodningsbibliotek; brugerindhold er base64-kodet ind i
<image>xlink:href, ikke injiceret som SVG-elementer. - Udskriftsforhåndsvisninger bruger en blob-URL, ikke
document.write(). - localStorage-parsing er pakket ind i
try/catch— en korrupt post giver et frisk tomt standard, aldrig en undtagelse, der kunne rulle ind i en aktiv kodesti. - Brugerleverede URL'er, der vises som "Åbn link"-knapper, er begrænset til
http(s)://—javascript:- ogdata:-skemaer afvises.
Cross-origin billedhentning
Når en bruger indsætter en https:-URL som et vCard-foto eller logo, henter browseren det under CORS og vores CSPs img-src-tilladelsesliste. Billedet gengives til et canvas. Det bliver aldrig levende DOM, kører aldrig som kode og når aldrig vores oprindelse — hentningen er browser → eksternt billede, og resultatet males klientsiden. En angriber, der kontrollerer en ekstern billed-URL, kan spore, at URL'en blev indlæst (en logpost på deres egen server), men kan ikke eksfiltrere noget fra vores side.
Subresource Integrity (SRI)
Al JavaScript og CSS, vi leverer, er same-origin. Vi indlæser ikke tredjeparts-scripts eller -stylesheets, så SRI-hashes er ikke relevante. Hvis vi nogensinde indlæser et tredjeparts-asset, leverer vi en SRI integrity-attribut på det og dokumenterer hash-opdateringsprocessen på denne side.
Rapportering af en sårbarhed
Hvis du opdager et sikkerhedsproblem, der påvirker Abundera QR — hvad enten det er i vores kode, vores deployment eller i en afhængighed, vi leverer — bedes du rapportere det privat til security@abundera.ai. Vi sigter mod at triagere inden for 72 timer. Du kan også kontakte os via kontaktoplysningerne i vores /.well-known/security.txt-fil.
Ingen bug-bounty (endnu)
Vi tilbyder i øjeblikket ikke betalte bounties, men hver bekræftet gyldig rapport modtager kredit i ændringsloggen og vores offentlige tak.
Verificer alt ovenstående
Hvert udsagn på denne side kan falsificeres fra din browsers DevTools uden at stole på os:
- CSP: DevTools → Netværk →
/→ Headere. LæsContent-Security-Policy-svarheaderen. - HSTS + sikkerhedsheadere: samme sted — alle
Strict-Transport-Security,X-Frame-Optionsosv. er synlige. - Ingen udgående kald: DevTools → Netværk → Fetch/XHR. Generer en QR. Se antallet forblive nul.
- Service worker-scope: DevTools → Applikation → Service Workers. Verificer scriptkilden og den cachede asset-liste.
- Ingen cookies: DevTools → Applikation → Cookies. Tom.
- Fuld gennemgang: manifestets verifikationsafsnit.
Kontakt
Sikkerhedsoplysninger: security@abundera.ai