Back to skill

Security audit

google-autoreply

Security checks for vulnerabilities and agentic risk

Overview

The skill matches its onboarding purpose, but it needs review because it handles long-lived account tokens in URLs and persistent storage while making real account and Google Business changes.

Install only if you trust the product backend and are comfortable letting the agent perform real account setup, Google Business linking, persistent auto-reply configuration, and checkout initiation. Before broad use, the publisher should remove bearer tokens from URLs, require allowlisted HTTPS redirect destinations, replace token handoff with short-lived one-time codes, shorten token lifetime, and require clear user confirmation before linking accounts, changing settings, or starting payment.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:28
Finding

Long-Lived Bearer Session Token Transmitted Through URLs

Content
View full analysis
&redirectState= ``` ```text 3. The callback carries `?token=`; store `Bearer ` as the session token (in web: `localStorage`; in app: uni storage under key `token`). ``` ```text - **Mode A (agent has browser automation):** open the login URL, read `token` from the callback URL, store `Bearer `. ``` ```text 2. If not connected, initiate OAuth connect. Build: ``` {API_BASE_URL}/oauth2/connectGoogleBusiness?token=&redirectState= ``` ``` ### Technical Analysis The skill directs the agent to place a bearer session token in OAuth callback and Google Business connection URLs. URL encoding changes only the representation of the credential; it does not protect its confidentiality. Query-string values can be retained or disclosed through: - Browser history and address-bar synchronization - Screenshots, copied URLs, and support diagnostics - Reverse-proxy, load-balancer, web-server, and monitoring logs - Browser extensions and local browser data - Analytics and crash-reporting systems - Referrer propagation where an appropriate `Referrer-Policy` is absent - Automation tool traces and navigation logs HTTPS protects the URL while it is in transit, but it does not prevent the browser, endpoints, intermediaries, or application telemetry from retaining the query string. This exposure is particularly serious because `SKILL.md` describes the session JWT as having an approximately seven-year lifetime. The network access itself is consistent with the declared onboarding function. However, transmitting the bearer credential in a URL is not necessary to pro ...[truncated 1590 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:70
Finding

Caller-Provided Handoff Return URL Receives Reusable Session Credentials

Content
View full analysis
` (e.g. a URL the invoking application — workbuddy / openclaw — listens on). Response `data.handoffId` (one-time slot, usable for 3 min). If `returnUrl` is omitted the login falls back to the product login page. 2. Give the merchant this URL: `{API_BASE_URL}/oauth2/authorization/google-autoreply?handoffId=` and ask them to complete the sign-in. After login the browser is **redirected back to `returnUrl` with `token` & `tokenHead` appended** (e.g. `returnUrl?token=...&tokenHead=...`). 3. Poll `GET /oauth2/handoff//token` (every ~2–3s) until `data.status === "READY"`. - `PENDING` → keep polling. - `EXPIRED` → the slot expired / was never opened; create a new handoff and retry, or fall back to asking the merchant to paste the `?token=` value. 4. On `READY`, take `data.authorization` (e.g. `Bearer `, exactly the `Authorization` header value). It is single-use — the slot is deleted after being read. ``` ### Technical Analysis The handoff procedure accepts a caller-provided `returnUrl` and instructs the backend to append `token` and `tokenHead` directly to that destination. The audited skill does not require an allowlist of pre-registered redirect URIs, exact redirect matching, HTTPS-only destinations, proof of destination ownership, or cryptographic binding between the initiating client and the return endpoint. Although the handoff slot is documented as one-time and valid for three minutes, those properties do not protect a reusable session token after it has been delivered to the return URL. The handoff polling respon ...[truncated 1723 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:15
Finding

Approximately Seven-Year Bearer Token Persisted in Browser and Environment Storage

Content
View full analysis
`). Set once after Step 1 and reused verbatim for **every** backend API call and the next session. Re-authorize only when the API returns `401`. - GMB OAuth client credentials (`client_id`/`client_secret`) are read by the backend from Spring config (`spring.security.oauth2...client-id/secret`), **not** by the agent — no env var needed. - Google Business `access_token`/`refresh_token` are **owned and persisted by the backend** in the shop's `googleBusinessToken` (DB) and auto-refreshed; the agent never stores or forwards these. A once-made GMB connection stays valid. - **Token lifetime (checked)**: login/session JWT is long-lived (`jwt.expiration` ≈ 7 years). GMB `access_token` is short-lived (`expires_in`, typically ~3600s / 1h), `refresh_token` is long-lived — the backend refreshes automatically. - To read a stored value for diagnostics, print only a masked/truncated version (e.g. first 6 chars), never the full token. ``` ```text 3. The callback carries `?token=`; store `Bearer ` as the session token (in web: `localStorage`; in app: uni storage under key `token`). ``` ### Technical Analysis The skill instructs the agent to reuse the same bearer token across every backend request and future sessions, with reauthorization occurring only after an HTTP `401`. It also states that the token remains valid for approximately seven years. A bearer token grants access based on possession alone. Such an extended lifetime substantially increases the chance that a token exposed once through URLs, logs, browser storage, backups, diagnostics, or local process access will remain useful to an attacker. Storing a bearer token ...[truncated 1786 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The invocation description is broad enough to trigger on generic account setup, status, or Google Business connection requests, which can cause the agent to enter a workflow that performs live authentication, token retrieval, backend changes, and potentially payment-related actions without a tightly scoped user request. In this skill’s context, overbroad matching is more dangerous because the workflow is stateful and high-impact: it handles persistent auth tokens, connects external business accounts, and can steer users toward Stripe checkout after trial expiry.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill does not provide a prominent upfront warning that execution involves real backend actions, OAuth authorization, persistent session-token handling, account linking, and a possible paid checkout path once the trial has expired. That omission can undermine informed consent and increase the chance that a user triggers sensitive actions without realizing the skill will access accounts, store credentials/tokens, and modify production settings.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The instruction says to report the empty-state message as '此账户下没有谷歌店铺信息' to the merchant, which forces a specific language in user-facing output. Because the file otherwise supports multiple reply languages and does not justify a Chinese-only constraint here, this appears to violate the language/locale policy.

Content

No source excerpt is available for this finding.