Is Wayground AI safe?

Medium risk

Wayground AI is medium risk. Starting bulk Classroom feedback with integrity checks on exports each student's Doc as text and sends it to Wayground's integrity API with an AI-detection/plagiarism flag. DA recorded no live body; grading wasn't triggered in that session.…

Wayground (formerly Quizizz)v4.5.5Chrome Web Store
49Risk
Who publishes it

Wayground (formerly Quizizz) - no other listings under this identity, 10 shared hostnames

What this publisher told the store about itself, and the other listings that told it the same thing.

Publisher
Wayground (formerly Quizizz)

Shared hosts - 10 hostnames

Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.

cf.quizizz.com
Also called by 1 other listing: Quizonator
readworks.org
Also called by 1 other listing: InsertLearning
commonlit.org
Also called by 2 other listings, including TeacherTab
ed.ted.com
Also called by 2 other listings
history.com
Also called by 2 other listings, including Revision History
pangram.com
Also called by 2 other listings, including Pangram AI Detection
kids.nationalgeographic.com
Also called by 3 other listings, including Signspaces - Sign Language Learning
smithsonianmag.com
Also called by 3 other listings, including Signspaces - Sign Language Learning
phet.colorado.edu
Also called by 4 other listings
wayground.com
Also called by 6 other listings, including Quizonator

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

Student text sent for integrity checks

Starting bulk Classroom feedback with integrity checks on exports each student's Doc as text and sends it to Wayground's integrity API with an AI-detection/plagiarism flag.

DA recorded no live body; grading wasn't triggered in that session.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-359
Source
Dynamic sandbox
What actually happens
You did this

A teacher starts bulk document feedback with integrity checks turned on.

The classroom grading message passes an integrity-enabled flag into the feedback workflow.

The extension did this

The extension exports each student document as text and prepares integrity checks for that text.

The code calls the integrity helper only when that option is enabled or when prior integrity results are absent.

Fields prepared for the integrity request
  • Student submission text
    A student essay paragraph about photosynthesis (illustrative)

    This is the body of a student's submitted Google Doc. It can include academic work and personal classroom context.

  • Integrity check type
    ["ai"] or ["plagiarism"]

    This tells the server whether the text should be evaluated for AI generation, plagiarism, or both across separate calls.

  • Wayground session token
    Authorization: Bearer <redacted>

    This authenticates the request as the signed-in Wayground user rather than as an anonymous browser request.

Captured request
POSThttps://wayground.com/_growthsvc/main/public/v1/integrity/check

The shipped request parser expects JSON and returns the response data object.

Headers
Content-Type
application/json
Authorization
Bearer <redacted>
The code that does this

The integrity request and authorization helper in the shipped service worker

Readable version

Authorization wrapper

background.js
async function Xo(e, t = {}) {  const n = await async function() {    const {      token: e,      expiry: t    } = await Wo();    return e && t > Date.now() + 12e4 ? e : await Jo()  }(), r = {    ...t.headers,    Authorization: `Bearer ${n}`  };  let o = await fetch(e, {    ...t,    headers: r  });  if (401 === o.status) try {    const n = await Jo();    r.Authorization = `Bearer ${n}`, o = await fetch(e, {      ...t,      headers: r    })  } catch (e) {    if ("SESSION_EXPIRED" === e.message) return o;    throw e  }  return o}

Integrity API client

background.js
class fs {  async _call(e, t) {    const n = `${d()}/_growthsvc/main/public/v1/integrity/check`,      r = await Xo(n, {        method: "POST",        headers: {          "Content-Type": "application/json"        },        body: JSON.stringify({          text: e,          checks: t        })      });    if (!r.ok) {      const e = await r.json().catch(() => ({}));      throw new Error(e?.error?.message || `HTTP ${r.status}`)    }    const o = await r.json();    return o?.data ?? o  }  async checkAI(e) {    const t = await this._call(e, ["ai"]);    if (t.aiDetection?.error) throw new Error(t.aiDetection.error);    return t.aiDetection  }  async checkPlagiarism(e) {    const t = await this._call(e, ["plagiarism"]);    if (t.plagiarism?.error) throw new Error(t.plagiarism.error);    return t.plagiarism  }}

AI and plagiarism checks are dispatched

background.js
async function ws(e, t) {  if (!e) return {    aiDetection: null,    plagiarism: null  };  if ((t || "").trim().split(/\s+/).filter(Boolean).length < 50) return {    aiDetection: {      skipped: !0,      reason: "too_short"    },    plagiarism: {      skipped: !0,      reason: "too_short"    }  };  async function n(e) {    try {      return await e()    } catch {      return await new Promise(e => setTimeout(e, 1e3)), e()    }  }  const [r, o] = await Promise.allSettled([n(() => e.checkAI(t)), n(() => e.checkPlagiarism(t))]);  return {    aiDetection: "fulfilled" === r.status ? r.value : {      error: r.reason?.message || "Unknown error"    },    plagiarism: "fulfilled" === o.status ? o.value : {      error: o.reason?.message || "Unknown error"    }  }}
Services involved in this document flow
    • www.googleapis.com

    Google Drive export endpoint used to read the student's document text.

    • wayground.com

    Wayground integrity API that receives the text and selected check type.

Student PDFs uploaded to Quizizz media

Asking Wayground AI for Doc feedback downloads it as PDF, uploads via Quizizz media first: gets an upload URL from media.quizizz.com, PUTs the PDF, passes that URL into the request.

No live upload captured; the Doc action wasn't run.

Severity
Medium unwanted
Type
Unexpected
CWE
CWE-829
Source
Dynamic sandbox
What actually happens
You did this

A teacher asks Wayground AI to comment on a Google Doc.

The generate-document-feedback message includes the document file ID and starts the background workflow.

The extension did this

The extension downloads the document as a PDF and uploads it through Quizizz media hosting.

The hosted file URL is then attached to the AI feedback request as the student document.

Fields and objects in the media upload flow
  • Student document PDF
    application/pdf blob from a student essay (illustrative)

    This is the student's Google Doc converted into a PDF before feedback generation.

  • Upload metadata
    destination=quizzes; Content-Type=application/pdf

    This tells the media service that the uploaded object is a PDF and should be handled as quiz media.

  • Hosted file URL
    https://media.quizizz.com/uploads/student-document.pdf (illustrative)

    This URL points to the uploaded PDF and is passed into the AI feedback request as the document reference.

  • Google Drive token
    Authorization: Bearer <redacted>

    This lets the extension retrieve the source Google Doc from the teacher's Drive access.

Captured request
POSThttps://media.quizizz.com/_mdserver/main/getUploadURL?destination=quizzes&metadata=%7B%22Content-Type%22%3A%22application%2Fpdf%22%7D&enableAcceleration=true

The shipped code requires a JSON response containing data.signedUrl and data.finalUrl before it uploads the PDF.

Headers
Accept
application/json, text/plain, */*
The code that does this

The Quizizz media upload function in the shipped service worker

Readable version

Media upload URL request and signed PUT

background.js
async function Ys(e, t = "application/pdf") {  const n = Math.random().toString(36).substring(7),    r = await fetch(`https://media.quizizz.com/_mdserver/main/getUploadURL?destination=quizzes&metadata=${encodeURIComponent(JSON.stringify({"Content-Type":t}))}&_=${n}&enableAcceleration=true`, {      method: "POST",      headers: {        Accept: "application/json, text/plain, */*"      }    });  if (!r.ok) throw new Error(`Media server error: ${r.status}`);  const o = await r.json();  if (!o.success || !o.data?.signedUrl || !o.data?.finalUrl) throw new Error("Invalid response from media server");  const {    signedUrl: s,    finalUrl: i  } = o.data, a = await fetch(s, {    method: "PUT",    headers: {      "Content-Type": t    },    body: e  });  if (!a.ok) throw new Error(`S3 upload failed: ${a.status}`);  return i}
Services involved in this upload flow
    • www.googleapis.com

    Google Drive API used to download or export the source document.

    • media.quizizz.com

    Quizizz media service that returns signed upload and hosted file URLs.

    • amazonaws.com

    Signed object-storage URL returned by the media service for the PDF PUT upload.

    • wayground.com

    Wayground AI backend receives the hosted file URL as the document reference.

Updated 30 September 2026jnegnfbcjklhkmoihoakeijbealomipg