Is Google Drive Mini safe?

Medium risk

Google Drive Mini is medium risk. Google Drive Mini requests full Drive OAuth plus offline access. Tokens are stored in chrome.storage.local; the popup uses them to list, rename, delete, and download Drive files. DA did not finish login: no traffic captured.…

Bart Verav3.9.9Chrome Web Store
45Risk

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

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Full Google Drive OAuth Access With Offline Tokens

Google Drive Mini requests full Drive OAuth plus offline access.

Tokens are stored in chrome.storage.local; the popup uses them to list, rename, delete, and download Drive files.

DA did not finish login: no traffic captured.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You sign in to Google from the extension's popup.

The service worker builds a Google OAuth request for Drive and offline access.

The extension did this

The extension stores Google access credentials and uses them for Drive file operations.

The code paths cover file listing, starring, renaming, deleting, and downloading links returned by Drive.

02EvidenceFIELD TABLE
OAuth permissions and local token fields shown by the shipped code
FieldValueWhy it matters
Full Google Drive permission
https://www.googleapis.com/auth/driveThis lets the extension reach files across your Google Drive rather than only files it created itself.
Offline access permission
https://www.googleapis.com/auth/offlineThis lets access continue after the initial sign-in by using a refresh token.
Stored refresh token
chrome.storage.local service.refresh_tokenThis local stored value can be exchanged for a fresh Google access token after sign-in.
Stored access token
chrome.storage.local service.tokenThis local stored value is sent as the bearer token for Drive file requests.
Drive file endpoint
https://www.googleapis.com/drive/v3/files?pageSize=50&fields=*This endpoint is where file listing and file actions are sent after sign-in.
03EvidenceNETWORK CAPTURE
Captured request
GEThttps://www.googleapis.com/drive/v3/files?pageSize=50&fields=*
No Drive API response was captured because the Google OAuth login flow was not completed during dynamic analysis.
Headers
Acceptapplication/json
AuthorizationBearer ${e.token}
04EvidenceSTORAGE DUMP
What's stored on your device

After sign-in, the extension keeps the Google access token and refresh token in local extension storage for later Drive requests.

Locationchrome.storage.local key 'service'
Contents (JSON)
{
  "token": "u.access_token",
  "refresh_token": "u.refresh_token"
}
05EvidenceCODE COMPARE
The code that does this

The service worker requests offline Drive access and stores returned tokens

What it actually does
Readable service-worker OAuth flowsrc/js/serviceWorker.js
oauth2: {
  client_id: "530311117568-qkkvrkfum8cnhmb87iddli004ns5aj0a.apps.googleusercontent.com",
  scopes: ["https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/offline"]
},
S = async e => {
  var o;
  const n = (o = d.oauth2) == null ? void 0 : o.client_id,
    c = "<redacted>",
    s = "https://oauth2.googleapis.com/token",
    a = {
      refresh_token: e,
      client_id: n,
      client_secret: c,
      grant_type: "refresh_token"
    };
  return fetch(s, {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    },
    body: new URLSearchParams(a)
  }).then(t => t.json()).then(t => t).catch(t => console.error("Error refreshing access token:", t))
}, I = "<redacted>";
var _;
const m = (_ = d.oauth2) == null ? void 0 : _.client_id,
  g = chrome.identity.getRedirectURL(),
  T = async () => {
    var o, t;
    const {
      token: e,
      refresh_token: n
    } = await r.service.get(), c = !e;
    let s = "https://accounts.google.com/o/oauth2/auth?";
    const a = {
      client_id: m,
      redirect_uri: g,
      scope: (t = (o = d.oauth2) == null ? void 0 : o.scopes) == null ? void 0 : t.join(" ")
    };
    if (e) chrome.identity.removeCachedAuthToken({
      token: e
    }, async function() {
      if (n) {
        const i = await S(n);
        await r.service.set({
          refresh_token: i.refresh_token,
          token: i.access_token
        })
      } else await r.service.set({
        token: void 0
      })
    });
    else {
      const i = {
          ...a,
          response_type: "code",
          access_type: "offline",
          login_hint: ""
        },
        p = new URLSearchParams(Object.entries(i));
      p.toString(), s += p, chrome.identity.launchWebAuthFlow({
        url: s,
        interactive: c
      }, async function(k) {
        const y = new URL(k).searchParams.get("code"),
          u = await (await fetch("https://oauth2.googleapis.com/token", {
            method: "POST",
            headers: {
              "Content-Type": "application/x-www-form-urlencoded"
            },
            body: new URLSearchParams({
              code: y,
              client_id: m,
              client_secret: I,
              redirect_uri: g,
              grant_type: "authorization_code"
            })
          })).json();
        await r.service.set({
          refresh_token: u.refresh_token,
          token: u.access_token
        })
      })
    }
  };
06EvidenceCODE COMPARE
The code that does this

The popup uses the bearer token for Drive file listing and file changes

What it actually does
List Drive filessrc/js/popup.js
const wO = 50,
  CO = "https://www.googleapis.com/drive/v3/files?",
  Of = async e => {
    const t = `${e.nextPageToken?`pageToken=${e.nextPageToken}&`:""}${e.orderBy?`orderBy=${e.orderBy}${e.desc?"%20desc":""}&`:""}${e.isStarred||e.search?"q=":""}${e.isStarred?"starred":""}${e.isStarred&&e.search?"%20and%20":""}${e.search?`name%20contains%20'${e.search}'`:""}${e.isStarred||e.search?"&":""}pageSize=${wO}&fields=*`;
    return fetch(`${CO}${t}`, {
      headers: new Headers({
        Authorization: `Bearer ${e.token}`,
        Accept: "application/json"
      })
    }).then(r => r.json()).then(r => r)
  }
Star or unstar a Drive filesrc/js/popup.js
Ql = async (e, t, r) => fetch(`https://www.googleapis.com/drive/v3/files/${e}?key=${{}.REACT_APP_API_KEY}`, {
  headers: new Headers({
    Authorization: `Bearer ${r}`,
    Accept: "application/json",
    "Content-Type": "application/json"
  }),
  method: "PATCH",
  body: JSON.stringify({
    starred: t
  })
}).then(n => n)
Move a Drive file to trashsrc/js/popup.js
nP = (e, t) => fetch(`https://www.googleapis.com/drive/v3/files/${e}`, {
  headers: new Headers({
    Authorization: `Bearer ${t}`,
    Accept: "application/json",
    "Content-Type": "application/json"
  }),
  method: "DELETE"
}).then(r => r)
Rename a Drive filesrc/js/popup.js
iP = (e, t, r) => fetch(`https://www.googleapis.com/drive/v3/files/${e}`, {
  headers: new Headers({
    Authorization: `Bearer ${r}`,
    Accept: "application/json",
    "Content-Type": "application/json"
  }),
  method: "PATCH",
  body: JSON.stringify({
    name: `${t}`
  })
}).then(n => n)
07EvidenceTHIRD PARTY LIST
External services contacted by the OAuth and Drive code paths
  • accounts.google.com

    Receives the browser OAuth authorization request for the Drive and offline scopes.

  • oauth2.googleapis.com

    Receives the authorization-code and refresh-token exchanges for Google access tokens.

  • www.googleapis.com

    Receives Google Drive files API calls for listing files and applying file changes.

SeverityLOW
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Content script polls every page's links every second on all sites

The extension injects a content script into every website, including banking and email sites.

It runs before the page loads, then polls every anchor once per second via setInterval, scanning every page's full link inventory each tick.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You navigate to any website.

The manifest declares matches: ['<all_urls>'], run_at: 'document_start', all_frames: true.

The extension did this

The extension content script begins running in the page before it finishes loading, then polls all anchor elements on the page every second.

This occurs on every site, not just Google Drive or related domains.

02EvidenceCODE COMPARE
The code that does this

Content script: full source (contentScript.js)

What it actually does
(function() {
  "use strict";
  // Runs after DOM is ready, on EVERY page
  document.addEventListener("DOMContentLoaded", () => {
    // Poll every 1 second for the lifetime of the tab
    setInterval(() => {
      scanLinks();
    }, 1000);
  });

  const scanLinks = () => {
    // Queries ALL anchor elements on the page, every tick
    const links = document.querySelectorAll("a:not(.docs-creator)");
    for (let i = 0; i < links.length; i++) {
      links[i].classList.add("docs-creator"); // marks as visited
      const href = links[i].getAttribute("href");
      if (href && href.indexOf("drive.google") !== -1) {
        // Only acts on drive.google links — but scans all links to find them
        links[i].addEventListener("click", (event) => {
          event.preventDefault();
          const w = window.screen.width;
          const h = window.screen.height;
          window.open(
            event.currentTarget.href,
            "_blank",
            `menubar=no,scrollbars=yes,resizable=yes,width=${w*60/100}px,height=${h*60/100}px,left=${w*20/100}px,top=${h*20/100}px`
          );
        });
      }
    }
  };
})();
03EvidenceTEMPORAL PATTERN
When this fires
Every 1 second

Scans all anchor elements on the page every 1 second via setInterval, for as long as the tab remains open.

04EvidencePLAIN NOTE
Scope mismatch: functionality vs. permissions

The extension's function — intercepting clicks on Google Drive links to open them in a sized popup window — requires DOM access only on pages that contain such links. The declared scope of `<all_urls>` with `all_frames: true` and `document_start` injection is broader than required for this behavior. The polling loop runs indefinitely on pages with no Drive links, including pages where DOM queries against unrelated anchor elements carry higher sensitivity (internal web apps, banking portals, email clients).

What it can do

Permissions this extension asks for, as declared in version 3.9.9. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.

  • Read and change your data on every site you visit

    <all_urls>

  • Store data in your browser

    storage

  • Start, monitor and manage your downloads

    downloads

  • Sign you in with your Google account

    identity

  • See the email address of your Google account

    identity.email

Updated 30 September 2026dehdfphabgkllffpepfmahleiphflgbm