Back to skill

Security audit

GA4 Analytics

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Google analytics purpose, but it exposes under-scoped de-indexing and broad local result-file access/storage behavior that should be reviewed before installation.

Review before installing. Use a least-privilege Google service account limited to the intended GA4 property and Search Console site, avoid invoking removeFromIndex unless you explicitly want a URL removed from Google indexing, keep the results directory private, and update/audit the npm dependencies before using this with sensitive analytics data.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/src/core/storage.ts:58
Finding

Path Traversal and Arbitrary JSON File Access in Exported Storage Utilities

Content
View full analysis
( data: T, category: string, operation: string, extraInfo?: string ): string { const settings = getSettings(); const categoryDir = join(settings.resultsDir, category); // Ensure category directory exists if (!existsSync(categoryDir)) { mkdirSync(categoryDir, { recursive: true }); } ``` ```typescript export function loadResult(filepath: string): SavedResult | null { if (!existsSync(filepath)) { return null; } try { const content = readFileSync(filepath, 'utf-8'); return JSON.parse(content) as SavedResult; } catch { return null; } } ``` ```typescript export function listResults(category: string, limit?: number): string[] { const settings = getSettings(); const categoryDir = join(settings.resultsDir, category); if (!existsSync(categoryDir)) { return []; } const files = readdirSync(categoryDir) .filter(f => f.endsWith('.json')) .map(f => join(categoryDir, f)) ``` The affected functions are made part of the public Skill interface: ```typescript export { saveResult, loadResult, listResults, getLatestResult } from './core/storage.js'; ``` ### Technical Analysis The `category` argument is joined directly to the configured results directory without an allowlist, canonicalization, or containment check. A value containing traversal components, such as `../../target`, can resolve outside the intended `results/` directory. Although generated filenames sanitize `operation` and `extraInfo`, this does not protect the directory component. Consequently, `saveResult` can create directories and write a generated JSON file in another filesystem location writable by the process. `listRe ...[truncated 1994 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/src/core/storage.ts:58
Finding

Sensitive Analytics Results Persisted in Plaintext Without Restrictive Permissions

Content
View full analysis
( data: T, category: string, operation: string, extraInfo?: string ): string { const settings = getSettings(); const categoryDir = join(settings.resultsDir, category); // Ensure category directory exists if (!existsSync(categoryDir)) { mkdirSync(categoryDir, { recursive: true }); } // Build filename const timestamp = getTimestamp(); const sanitizedOperation = sanitizeFilename(operation); const sanitizedExtra = extraInfo ? `__${sanitizeFilename(extraInfo)}` : ''; const filename = `${timestamp}__${sanitizedOperation}${sanitizedExtra}.json`; const filepath = join(categoryDir, filename); // Build wrapped result const result: SavedResult = { metadata: { savedAt: new Date().toISOString(), category, operation, propertyId: settings.propertyId, ...(extraInfo && { extraInfo }), }, data, }; // Write to file writeFileSync(filepath, JSON.stringify(result, null, 2), 'utf-8'); return filepath; } ``` ### Technical Analysis The Skill automatically persists API responses as unencrypted JSON. Depending on the invoked function, these files may contain: - Search queries and page performance. - Current page and event activity. - Geographic and device information. - Conversion and revenue metrics. - Transaction identifiers. - The GA4 property identifier included in result metadata. No explicit mode is supplied to `mkdirSync` or `writeFileSync`. Effective permissions therefore depend on the host process’s umask and deployment environment. In environments with permissive defaults, result directories or files may be readable by other local users or processes. Persistence is enabled by default across the API modules, includin ...[truncated 1663 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (33)

Known Vulnerable Dependency: protobufjs==7.5.4 — 12 advisory(ies): CVE-2026-44294 (protobuf.js: Denial of service from crafted field names in generated code); CVE-2026-44293 (protobuf.js: Code injection through bytes field defaults in generated toObject c); CVE-2026-44289 (protobuf.js: Denial of service through unbounded protobuf recursion) +9 more

Critical
Category
Supply Chain
Confidence
96% confidence
Finding

protobufjs 7.5.4 has numerous advisories including denial of service and potential code-generation/injection issues. Because this dependency sits in the Google client stack and processes structured protocol data, its presence materially increases risk, especially if any untrusted protobuf content or code-generation paths are reachable.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The description claims a full-featured Google Analytics/Search Console/Indexing API toolkit, but the supplied code only installs npm dependencies. There is no implementation here for querying GA4, accessing Search Console, using the Indexing API, analyzing traffic, or handling service account credentials. While setup scripts can be a supporting detail, this chunk by itself does not match the declared operational purpose and instead serves a different, preparatory function.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The description presents a comprehensive GA4 + Search Console analytics toolkit, but this code chunk is narrowly focused on indexing-related functions. It does not implement any Google Analytics reporting capabilities such as traffic, demographics, conversions, revenue, or date comparisons. It also does not provide Search Console query/performance analytics; only URL inspection is implemented. Additionally, the code includes an undeclared capability to request URL removal from Google's index (URL_DELETED). While URL re-indexing and index inspection are accurately represented, the overall declared description materially overstates the actual behavior of this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The supplied code is narrowly focused on Search Console search analytics. It queries search performance dimensions like query, page, device, country, and search appearance over a date range. There is no evidence in this chunk of GA4 metrics, real-time analytics, demographics, conversions, revenue, bounce rate analysis, or Indexing API features such as requesting re-indexing or inspecting index status. While the declared description includes Search Console query and SEO analysis, it materially overstates the implemented capabilities of this code chunk, so the description does not accurately represent the actual behavior shown here.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: @grpc/grpc-js==1.14.3 — 2 advisory(ies): CVE-2026-48068 (@grpc/grpc-js: A malformed request can cause a server crash); CVE-2026-48069 (@grpc/grpc-js: An incoming malformed compressed message can cause a client or se)

High
Category
Supply Chain
Confidence
94% confidence
Finding

The lockfile pins @grpc/grpc-js 1.14.3, and the cited advisories describe malformed-message crash conditions. Even though this skill is primarily a client-side analytics toolkit, google-gax and related libraries bring in gRPC code paths, so a vulnerable version in the shipped dependency graph is a real supply-chain risk if any reachable parsing/server behavior is exposed during use.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: brace-expansion==2.0.2 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
92% confidence
Finding

brace-expansion 2.0.2 is flagged for multiple expansion-based DoS conditions. In this toolkit it is a transitive dependency of glob/minimatch tooling, so the danger is mainly during any pattern processing in local execution rather than remote compromise, but attacker-controlled glob patterns could still cause excessive CPU or memory consumption.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: form-data==2.5.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
86% confidence
Finding

form-data 2.5.5 is flagged for CRLF injection through unescaped multipart field names/filenames. This analytics skill interacts with Google APIs and may construct outbound HTTP requests, so if any user-controlled multipart metadata is ever forwarded, header/request smuggling or malformed request generation becomes possible.

Content

No source excerpt is available for this finding.

Possible Typosquatting: 'gaxios' resembles popular package 'axios'

High
Category
Supply Chain
Confidence
70% confidence
Finding

Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Content

No source excerpt is available for this finding.

Possible Typosquatting: 'gaxios' resembles popular package 'axios'

High
Category
Supply Chain
Confidence
70% confidence
Finding

Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: minimatch==9.0.5 — 3 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu); CVE-2026-26996 (minimatch has a ReDoS via repeated wildcards with non-matching literal in patter); CVE-2026-27903 (minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja)

High
Category
Supply Chain
Confidence
91% confidence
Finding

minimatch 9.0.5 has multiple ReDoS-style advisories involving crafted glob patterns. In this repository it appears as a tooling dependency rather than core runtime analytics logic, which reduces exposure, but any use on attacker-controlled patterns could still hang or significantly slow the process.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/src/config/settings.ts (reported line 8)May include surrounding context.

ts
import { config } from 'dotenv';
import { join } from 'path';

// Load .env file from current working directory
config();

/**

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill declares capabilities that require environment variable access and outbound network access, but it does not explicitly scope or declare those permissions. This creates a trust and review gap: operators may approve or run the skill without realizing it can access secrets and contact external services, which is especially relevant because it handles service-account credentials and writes results locally.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
81% confidence
Finding

Using npx tsx without a pinned version allows execution to depend on whatever package version is resolved at runtime, which weakens supply-chain integrity and reproducibility. If a malicious or compromised package version is served, running the documented command could execute attacker-controlled code in the environment where analytics credentials are present.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill automatically persists analytics results and generated summaries to local files, but the documentation does not prominently warn about the privacy and data-retention implications. Because GA4/Search Console outputs can include sensitive business intelligence, user behavior metrics, and indexed URL data, silent local storage can lead to unintended disclosure, over-retention, or collection into other tools and backups.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The API reference documents a destructive capability, removeFromIndex(url), but does not warn that it can de-index content from Google search results and negatively affect discoverability, traffic, and business operations if used incorrectly. In an agent skill context, exposing such an action without explicit confirmation or caution increases the risk that an automated workflow or user may invoke it unintentionally.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

This function persists GA4 report data to disk by default via save = true and saveResult(...) without requiring explicit opt-in at the call site. Analytics reports can contain sensitive business intelligence and user-behavior data, so silent local persistence increases the risk of unintended disclosure through shared workspaces, backups, logs, or later file access.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill exposes a removeFromIndex capability that submits URL_DELETED notifications to Google's Indexing API, which is more destructive than the manifest description focused on re-indexing and inspection. In an agent context, this expands the action surface from read/refresh operations to content suppression, so a user or prompt-injected workflow could request de-indexing of legitimate pages and harm site visibility or SEO.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code persists full GA4 report responses to storage by default whenever runReport is called, without any indication here of consent, minimization, retention controls, or redaction. Because GA4 data can include sensitive business analytics and, depending on configuration, identifiers or queryable behavior data, silent persistence increases the risk of unintended data retention, broader internal exposure, and secondary leakage if storage is accessed by other components or users.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

This code persists Search Console query results by default whenever callers do not explicitly set save=false. Search Console data can include sensitive business intelligence and potentially sensitive query/page performance data, so automatic retention without explicit user consent or clear disclosure increases the risk of unintended data storage, over-retention, and secondary exposure through logs or local result files.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The module automatically persists analytics results and metadata to local JSON files, which expands the skill's behavior from transient analytics queries to durable local storage. Because GA4/Search Console data can include sensitive business metrics and identifiers, saving it by default creates confidentiality and data-retention risk if the host environment is shared, backed up, or later accessed by other tools or users.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Results are written to disk silently, with metadata such as timestamps, category, operation, property ID, and optional extra info included, but there is no user-facing disclosure or consent mechanism. In an analytics skill, this is especially risky because users may expect query results to be ephemeral, while persisted files can expose sensitive traffic, SEO, or business-performance information later.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: @protobufjs/utf8==1.1.0 — 1 advisory(ies): CVE-2026-44288 (protobufjs has overlong UTF-8 decoding)

Low
Category
Supply Chain
Confidence
83% confidence
Finding

@protobufjs/utf8 1.1.0 is present and the advisory indicates overlong UTF-8 decoding weaknesses. In this skill the package is only a deep transitive dependency, so exploitability is likely limited, but accepting malformed serialized input could still produce incorrect parsing behavior.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: @tootallnate/once==2.0.0 — 1 advisory(ies): CVE-2026-3449 (@tootallnate/once vulnerable to Incorrect Control Flow Scoping)

Low
Category
Supply Chain
Confidence
61% confidence
Finding

The vulnerable @tootallnate/once 2.0.0 package is included transitively. The reported issue is low severity and this package is a tiny utility with no obvious direct exposure in the skill, but it is still a real vulnerable component in the dependency tree.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: qs==6.14.1 — 3 advisory(ies): CVE-2026-82417 (qs: Denial of Service via Attacker Controlled isBuffer); CVE-2026-8723 (qs has a remotely triggerable DoS: qs.stringify crashes with TypeError on null/u); CVE-2026-2391 (qs's arrayLimit bypass in comma parsing allows denial of service)

Low
Category
Supply Chain
Confidence
78% confidence
Finding

qs 6.14.1 is associated with low-severity denial-of-service issues around parsing/stringifying crafted data structures. In this skill it is a transitive HTTP/query helper, so impact is constrained, but malformed attacker-controlled objects or query inputs could still trigger crashes or resource exhaustion in edge cases.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: uuid==9.0.1 — 1 advisory(ies): CVE-2026-41907 (uuid: Missing buffer bounds check in v3/v5/v6 when buf is provided)

Low
Category
Supply Chain
Confidence
72% confidence
Finding

uuid 9.0.1 is flagged for a missing bounds check in certain hash-based versions when a caller supplies a buffer. This is a real dependency issue, but exploitability is likely low here unless the code directly exposes uuid v3/v5/v6 buffer-based APIs to attacker-controlled input.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.