Back to skill

Security audit

gogcli-mcp-gmail

Security checks for vulnerabilities and agentic risk

Overview

This is a real Gmail MCP server, but it exposes broad Gmail, auth, and local server-file capabilities that need careful review before installation.

Install only if you trust this publisher and are comfortable giving an agent broad Gmail authority. Prefer a pinned package version, set GOG_READONLY when you only need reads, avoid broad OAuth services or extraScopes, and run the MCP server under a dedicated OS account with limited filesystem access if using local server-side attachment paths.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:21
Finding
Unpinned npm Package Is Downloaded and Executed Automatically<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:21-25` **Vulnerability Type**: Supply-chain exposure through unpinned package execution **Risk Level**: Medium ### Vulnerable Code ```json { "mcpServers": { "gogcli-gmail": { "command": "npx", "args": ["-y", "gogcli-mcp-gmail"], "env": { "GOG_ACCOUNT": "you@gmail.com" } } } } ``` ### Technical Analysis The recommended configuration invokes `npx -y gogcli-mcp-gmail` without specifying an exact package version or integrity digest. Consequently, startup can download and execute whichever package version the npm registry currently resolves. The `-y` option suppresses the installation confirmation that could otherwise alert the user that code is being downloaded. Although no malicious dependency was identified in the reviewed artifact, this configuration creates a mutable execution channel: the code executed in a future session may differ from the code covered by this audit. This is an insecure dependency-loading practice rather than evidence that the current package is malicious. ### Attack Path 1. An attacker compromises the npm publisher account, registry entry, or release pipeline for `gogcli-mcp-gmail`. 2. The attacker publishes a malicious version under the same package name. 3. A user starts the MCP server using the documented `npx -y` configuration. 4. `npx` resolves and downloads the newly published version without interactive confirmation. 5. The malicious package executes with the privileges and environment of the MCP server process. ### Impact Assessment A compromised package could execute arbitrary Node.js code with the MCP process's operating-system privileges. Depending on the deployment, this could expose: - Gmail data accessible through stored `gog` credentials. - OAuth-related configuration and account metadata. - Files readable or writable by the MCP process. - Tool requests and responses handled by the server. - Network access a ...[truncated 144 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin the reviewed package to an exact version: ```json { "command": "npx", "args": ["gogcli-mcp-gmail@2.30.0"] } ``` 2. Prefer installing the package through a lockfile-controlled deployment rather than downloading it at every startup. 3. Remove `-y` where interactive installation confirmation is operationally acceptable. 4. Verify package integrity using npm lockfile integrity metadata or a separately published checksum. 5. Pin and verify the `gogcli` binary release as well as the Node.js package. 6. Require a new security review before updating either the npm package or bundled CLI. 7. Consider installing from a verified release artifact and running the already-installed local executable. ]]>

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/tools/gmail-extra.ts:2402
Finding
Unrestricted Server-Side Paths Permit Filesystem Reads and Writes<![CDATA[ ## Vulnerability Details **File Location**: `src/tools/gmail-extra.ts:2402-2518`, `src/tools/gmail-extra.ts:2744-2752`, `src/tools/gmail-extra.ts:2785-2791`, and `src/tools/gmail-extra.ts:3093-3141` **Vulnerability Type**: Excessive local filesystem authority exposed through MCP tool parameters **Risk Level**: High ### Vulnerable Code The attachment tool accepts an unrestricted server-side output path: ```ts out: z.string().optional().describe('Server-side path where gog writes the file. NOTE: this resolves on the CONNECTOR/gog server\'s filesystem, not your machine — on the remote connector it is ignored (you can\'t read it; you get a Drive link instead), and deliver="url" ignores it too (the server has to read the file back to upload it, and only does that from its own download directory). Locally, with any other delivery mode, it is honored. Omit it to use an ephemeral temp path.'), ``` The supplied value is honored in local mode and passed directly to `gog`: ```ts const notes: string[] = []; let outPath = out; if (out && remote) { notes.push("`out` was ignored: it resolves on the connector's server filesystem, which you can't read."); outPath = undefined; } else if (out && deliver === 'url') { notes.push( '`out` was ignored: deliver="url" has the server read the file back to upload it, and it will only ' + 'read from its own download directory.', ); outPath = undefined; } if (!outPath) { outPath = deliver === 'url' ? blobOutPath(messageId, attachmentRef, filename ?? 'attachment') : messageOutPath(messageId, filename ?? 'attachment'); } ``` The resulting path is used as a CLI argument: ```ts args.push(`--out=${outPath}`, `--name=${filename ?? 'attachment'}`); ``` Thread tools similarly accept unrestricted output directories: ```ts outDir: z.string().optional().describe('Directory to write attachments to (default: current directory)'), ``` ```ts }, async ({ threadId, download, full, sanitizeContent, latestN, sn ...[truncated 5258 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove server-side path parameters from the default tool schemas where inline content is sufficient. 2. Require an explicit administrator configuration option before enabling local file input or custom output paths. 3. Define separate canonical roots for readable input files and writable attachment output. 4. Resolve every supplied path with `realpath` and verify that it remains beneath the applicable configured root. 5. Reject: - Absolute paths when only relative paths are expected. - `..` traversal. - Symlink escapes. - FIFOs, sockets, devices, and other non-regular files. - Paths under credential, configuration, home, or application source directories. 6. Open input files with protections against symlink races and verify the file type after opening. 7. Create output files with restrictive permissions and exclusive creation semantics where possible. 8. Generate output filenames internally rather than allowing callers to select complete paths. 9. Replace `bodyHtmlFile` with the existing `bodyHtml` parameter, which already supports large content through controlled temporary files. 10. Prefer `attachInline` over unrestricted server-side attachment paths. 11. Run the MCP server under a dedicated operating-system account with: - No access to unrelated user files. - A minimal writable temporary directory. - Read-only application files. - Credentials isolated from attachment storage. 12. Add tests covering absolute paths, traversal, symlink escapes, special files, and attempts to access the persisted credential directory. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
Findings (65)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill handles in-depth Gmail operations. However, the code shown contains Ajv internals and helper libraries (e.g., codegen, schema validation, refs resolution, json-schema traversal, deep equality), with no Gmail API calls, auth flow, message/thread/label handling, draft/send/forward logic, or mailbox operations. Its primary purpose is schema validation infrastructure, not Gmail interaction. This is a clear material mismatch between declared purpose and actual behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill should handle in-depth Gmail operations only. However, the supplied code chunk contains generic infrastructure libraries (`fast-uri` and `ajv`) for URI processing and JSON schema validation. There is no evidence of Gmail API calls, authentication flows for Gmail, message/thread/label handling, draft/send/forward/autoreply behavior, or any mailbox operations. This is a materially different primary purpose and capability set from the declared Gmail functionality, so it should be flagged as a mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill is specifically for advanced Gmail actions such as managing threads, labels, drafts, attachments, forwarding, and bulk mailbox operations. The supplied code chunk contains no Gmail API calls, no auth flow, no email/thread/label handling, and no mailbox operations. Instead, it is generic validation infrastructure from Ajv and Zod for schema vocabularies, data parsing, and format/error handling. This is a materially different primary purpose and an unrelated capability set, so the description does not accurately represent the code.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
This is a clear description-behavior mismatch. The declared purpose says the skill should perform advanced Gmail operations, but the code shown contains only generic Zod validation framework internals. There are no calls to Gmail services, no network or auth logic, no message/thread manipulation, and no email-specific behaviors. The code’s primary purpose is schema definition, parsing, validation, error formatting, and regex/string-format checks, which is materially different from the declared Gmail functionality.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The code shown does not interact with Gmail, authentication flows for Gmail, threads, labels, drafts, forwarding, attachments, or any email resources. Instead, it implements generic data validation and parsing infrastructure from Zod, including format checks and locale-specific error messages. This is a materially different primary purpose from the declared Gmail skill description, so the description does not accurately represent the code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill should handle advanced Gmail workflows. However, the provided code only contains multilingual validation error-formatting logic from Zod locales (e.g., messages for invalid_type, invalid_format, too_big, too_small). There is no code for reading/sending/organizing Gmail, no thread/label/draft/attachment handling, and no authentication or Gmail API integration. This is a material purpose mismatch rather than a supporting implementation detail.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared purpose says this skill handles advanced Gmail operations. However, the supplied code is unrelated to Gmail, authentication, email threads, labels, drafts, attachments, forwarding, or any mail actions. It defines localized formatter functions for validation errors in multiple languages, consistent with a validation library like Zod. This is a materially different primary purpose, so the description does not accurately represent the code.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill should handle advanced Gmail workflows and use Gmail/auth tools. However, the code shown contains Zod locale strings and validator compilation logic (e.g., error message generators, schema registry, compile functions, type/string/number/object checks). There is no evidence of Gmail API calls, authentication flows, email/thread/label handling, drafts, attachments, forwarding, or any mailbox operations. This is a clear purpose/behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill should handle in-depth Gmail operations. However, the supplied code chunk contains generic library code from Zod for generating validation checks and converting schemas to JSON Schema. It manipulates schema definitions, types, patterns, transforms, records, maps, sets, files, and serialization metadata. There is no evidence of Gmail API usage, mail/thread/label/draft handling, forwarding, autoreply, attachment processing, or authentication flows. This is a clear purpose mismatch, not merely an implementation detail.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This code chunk does not implement or expose the declared Gmail operational functionality itself. Instead, it is test code verifying one specific behavior of a Gmail drafts diff tool. While it is Gmail-related, its primary purpose is automated testing of internal arithmetic/output correctness, not reading/organizing/drafting/forwarding messages or performing Gmail actions for a user. That is a materially different purpose from the declared skill description.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
This code chunk does not perform Gmail operations or expose Gmail workflow behavior. It is a unit test for helper functions (`authoredBodyLines`, `measureBodyAgreement`) that analyze email text, remove signature blocks, and compare authored content between drafts. While email-related, this is materially different from the declared purpose of an in-depth Gmail operations skill. The actual behavior is internal content-analysis logic, not auth plus Gmail tools for managing messages, threads, labels, drafts, attachments, or bulk actions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description presents a general-purpose Gmail operations skill for acting on mailboxes: reading, organizing, drafting, forwarding, autoreplying, attachments, labels, and bulk mailbox actions. The supplied code chunk does not implement those operations. Instead, it is a test file validating low-level analysis utilities around Gmail drafts: identifying API vs non-API draft origins, parsing headers, extracting and decoding MIME bodies, measuring body similarity, detecting possible Apple Mail draft forks, and warning about content loss when rewriting drafts. Although the domain is Gmail, the actual behavior is materially different from the declared purpose: it is internal draft-analysis/testing logic rather than Gmail action tooling. That is a meaningful description-behavior mismatch.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill should perform advanced Gmail-related operations, but the provided code does not interact with Gmail, email, authentication, threads, labels, drafts, attachments, or mailbox actions at all. It is purely a testing configuration file for Vitest that defines code coverage behavior. This is a materially different primary purpose and unrelated to the declared skill behavior, so it is a clear mismatch.

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
function validateAsync3() {
        const ruleErrs = gen.let("ruleErrs", null);
        gen.try(() => assignValid((0, codegen_1._)`await `), (e) => gen.assign(valid, false).if((0, codegen_1._)`${e} instanceof ${it.ValidationError}`, () => gen.assign(ruleErrs, (0, codegen_1._)`${e}.errors`), () => gen.throw(e)));
        return ruleErrs;
      }
      function validateSync() {
        const validateErrs = (0, codegen_1._)`${validateRef}.errors`;
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
schema, schemaId, root, baseId });
      if (env.schema !== env.root.schema)
        return env;
      return void 0;
    }
  }
});

// ../../node_modules/ajv/dist/refs/data.json
var require_data = __commonJS({
  "../../node_modules/ajv/dist/refs/data.json"(exports, module) {
    module.exports = {
      $id: "https://raw.githubusercontent.com/ajv-validator/ajv/master/lib/refs/data.json#",
      description: "Meta-schema for $data reference (JSON AnySchema extension proposal)",
      type: "object",
      required: ["$data"],
      properties: {
        $data: {
          type: "string",
          anyOf: [{ format: "relative-json-pointer" }, { format: "json-pointer" }]
        }
      },
      additionalProperties: false
    };
  }
});

// ../../node_modules/fast-uri/lib/utils.js
var require_utils = __commonJS({
  "../../node_modules/fast-uri/lib/utils.js"(exports, module) {
    "use strict";
    var isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\d
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

YARA rule 'exploit_framework': Exploit framework components and payloads [hacktools]

High
Category
YARA Match
Content
return clone(this, _def, params);
  },
  brand() {
    return this;
  },
  register(reg, meta3) {
    reg.add(this, meta3);
    return this;
  },
  apply(fn, ...args) {
    return args.length === 0 ? fn(this) : fn(this, ...args);
  }
});
var ZodMiniObject = /* @__PURE__ */ $constructor("ZodMiniObject", (inst, def) => {
  $ZodObject.init(inst, def);
  ZodMiniType.init(inst, def);
  installLazyProp(inst, "shape", (self) => self._zod.def.shape, false);
});
// @__NO_SIDE_EFFECTS__
function object(shape, params) {
  const def = {
    type: "object",
    shape: shape ?? {},
    ...normalizeParams(params)
  };
  return new ZodMiniObject(def);
}

// ../../node_modules/zod/v4/core/visit.js
var RESOLVING = /* @__PURE__ */ Symbol("z.visit/resolving");
function visit(schema, fnOrHandlers) {
  const fn = typeof fnOrHandlers === "function" ? fnOrHandlers : (node2, rewritten) => {
    const h = fnOrHandlers[node2._zod.def.type];
    return h ? h(node2, rewritten) : node2;
  };
  const cache2 = /*
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Direct Prompt Extraction

High
Category
System Prompt Leakage
Content
return walk(value, keep, drop);
}
function normalizeRules(rules) {
  return rules.map((rule) => typeof rule === "string" ? rule.toLowerCase() : new RegExp(rule.source, rule.flags));
}
function matchesRule(key, rules) {
  const lower = key.toLowerCase();
Confidence
85% confidence
Finding
Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Credential Access

High
Category
Privilege Escalation
Content
var TOKEN_LEFT_BOUNDARY = "(?<![A-Za-z0-9+/])";
var GOOGLE_TOKEN_PATTERNS = [
  new RegExp(`${TOKEN_LEFT_BOUNDARY}ya29\\.[A-Za-z0-9._\\-]+`, "g"),
  // OAuth2 access tokens
  new RegExp(`${TOKEN_LEFT_BOUNDARY}1//[A-Za-z0-9._\\-]+`, "g")
  // OAuth2 refresh tokens
];
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Description-Behavior Mismatch

High
Confidence
99% confidence
Finding
The skill declares Gmail-focused behavior, but the bundled code exposes broader account-management and cross-service capabilities such as generic auth management, token health checks, and non-Gmail delivery paths. This widens the effective privilege surface beyond the advertised scope and can mislead a caller or orchestrator into granting or invoking capabilities they did not intend to expose.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The auth tools allow multi-service authorization and arbitrary extra OAuth scopes, including raw scope URIs. In a Gmail skill, this creates a privilege-escalation path where an agent can obtain broader Google access than the user or platform expects, enabling access to unrelated services under the same account.

Credential Access

High
Category
Privilege Escalation
Content
}
  });
  server.registerTool("gog_auth_status", {
    description: "Show gogcli auth CONFIGURATION: keyring backend, credential files, and auth setup. Despite the name this is not a health check \u2014 it reads local setup and does not contact Google, so it says nothing about whether an account can still authenticate. Use gog_auth_health for that.",
    annotations: { readOnlyHint: true },
    inputSchema: {}
  }, async () => {
Confidence
83% confidence
Finding
The skill exposes auth-status functionality that reveals credential storage and keyring configuration details. In a hosted agent environment, such environment and credential-management metadata can help an attacker understand where secrets live and how to target them, even if raw secret values are not returned.

Credential Access

High
Category
Privilege Escalation
Content
}
  });
  server.registerTool("gog_auth_health", {
    description: 'Check the LIVE health of each stored Google account. Unlike gog_auth_status (which only reports keyring/config setup), this performs a real token refresh against Google, so it detects expired or revoked (invalid_grant) refresh tokens \u2014 the account-wide sign-out that blocks every service. Reports per account: whether the token is currently valid, the mapped cause when it is not, how long ago it was authorized, and a warning as it approaches the 7-day refresh-token limit that applies to OAuth apps whose consent screen is still in "Testing" mode. Run it proactively to re-authorize on your own schedule instead of mid-task. On the hosted connector this is the ONLY check that measures Google: a connector showing "connected" or "refreshed" has verified the connector key that reaches the gog machine, and nothing else \u2014 the Google credential lives on that machine and can be dead while the connection looks perfectly healthy.',
    annotations: { readOnlyHint: true },
    inputSchema: {}
  }, async () => {
Confidence
86% confidence
Finding
The auth-health tool performs live token refresh checks and reports account-level credential validity. While operationally useful, that exposes credential state and can be abused for account enumeration, token-state probing, or determining which identities are usable for subsequent malicious actions.

Missing User Warnings

High
Confidence
98% confidence
Finding
Reply-all is especially risky because a single mistaken execution can broadcast sensitive content to multiple participants. The absence of a wrapper-enforced confirmation step materially increases the blast radius of prompt mistakes, ambiguous user intent, or malicious instruction injection.

Credential Access

High
Category
Privilege Escalation
Content
const missing = [!clientId && "GOG_CLIENT_ID", !clientSecret && "GOG_CLIENT_SECRET"].filter(Boolean).join(" and ");
    return async () => {
      throw new Error(
        `GOG_REFRESH_TOKEN is set but ${missing} is not, so no access token can be minted. Set the OAuth client alongside the refresh token, or unset GOG_REFRESH_TOKEN to use the backend\u2019s own identity.`
      );
    };
  }
Confidence
88% confidence
Finding
The code supports minting Google access tokens from refresh tokens supplied via environment variables. That is a legitimate implementation detail, but in the context of a Gmail-only skill it confirms the skill can exercise long-lived OAuth credentials directly, increasing the consequence of any misuse or overbroad registration of auth-related tools.

Credential Access

High
Category
Privilege Escalation
Content
cache.delete(k);
    logAuthTransition("token.evicted", {
      credential: credentialTag(k),
      reason: "Google rejected this access token; the next read will mint a new one"
    });
    return true;
  };
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.dynamic_code_execution, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
dist/index.js:36856

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
dist/index.js:2946

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
dist/index.js:36665