Back to skill

Security audit

GiveAgent

Security checks for vulnerabilities and agentic risk

Overview

The skill fits a gifting workflow, but it needs Review because it can handle sensitive pickup details and API credentials in ways that are broader or less safe than its privacy promises imply.

Review before installing. Use the default HTTPS GiveAgent API URL, avoid custom endpoints, consider disabling autoScan until you are comfortable with background matching, and do not provide exact home/work pickup details unless you have independently confirmed the other party has approved. On shared systems, protect or avoid storing API keys and pickup details in ~/.giveagent.

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
src/index.ts:51
Finding

Configurable API Base URL Can Exfiltrate the GiveAgent API Key

Content
View full analysis
= { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json", Accept: "application/json", }; async function request( method: string, path: string, body?: unknown, headers?: Record, ): Promise { if (!rateLimiter.canMakeRequest()) { throw new RateLimitExceededError("request"); } rateLimiter.recordRequest(); const url = `${baseUrl}${path}`; const init: RequestInit = { method, headers: { ...defaultHeaders, ...headers }, signal: AbortSignal.timeout(15000), }; if (body !== undefined) { if (body instanceof FormData) { init.body = body; const headersObj = init.headers as Record; delete headersObj["Content-Type"]; } else { init.body = JSON.stringify(body); } } let respons ...[truncated 2050 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/match.ts:329
Finding

Exact Pickup Details Are Sent Before Mutual Approval

Content
View full analysis
{ const matches = await storage.getMatches(); const match = matches.find(m => m.id === matchId); if (!match) { throw new Error(`Match ${matchId} not found`); } if (match.state === "EXPIRED" || match.expiresAt.getTime() < Date.now()) { throw new Error("Match has expired"); } // Call /approve with optional pickup_details const result = await apiClient.approveMatch( match.id, pickupDetails as unknown as Record | undefined, ); if (pickupDetails) { await storage.updateMatch(matchId, { pickupDetails }); // Send PICKUP_CONFIRMED message to counterpart const messageContent = formatPickupConfirmed({ item: match.item, pickup: pickupDetails.address, date: pickupDetails.date, time: pickupDetails.time, contact: pickupDetails.contact, notes: pickupDetails.notes, }); await apiClient.sendMessage({ matchId: match.id, toUserId: match.counterpartAgentId, messageType: "PICKUP_CONFIRMED", content: messageContent, }); } if (result.state === "BOTH_APPROVED") { ``` The state check occurs only after the sensitive message has already been sent. If the result remains `MATCH_ACCEPTED`, the code tells the user that it is waiting for th ...[truncated 1814 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/storage.ts:174
Finding

API Credentials and Exact Pickup Addresses Are Persisted Without Restrictive File Permissions

Content
View full analysis
{ await fs.mkdir(dirPath, { recursive: true }); } async function atomicWrite(filePath: string, content: string): Promise { const dir = path.dirname(filePath); const tmp = path.join(dir, `.tmp-${path.basename(filePath)}-${process.pid}-${Date.now()}`); await fs.writeFile(tmp, content, "utf8"); await fs.rename(tmp, filePath); } ``` Configuration is written directly as plaintext JSON: ```ts export function createStorage(basePath?: string): StorageManager { const baseDir = basePath ?? path.join(os.homedir(), ".giveagent"); const configFile = () => path.join(baseDir, "config.json"); const inventoryFile = () => path.join(baseDir, "inventory.json"); const wantlistFile = () => path.join(baseDir, "wantlist.json"); const matchesFile = () => path.join(baseDir, "matches.json"); const seenPostsFile = () => path.join(baseDir, "seen-posts.json"); const statsFile = () => path.join(baseDir, "stats.json"); async function init(): Promise { await ensureDir(baseDir); } async function getConfig(): Promise { await init(); return readJson(configFile(), DEFAULT_CONFIG); } async function saveConfig(updates: Partial): Promise { await init(); const current = await getConfig(); const merged = { ...current, ...updates }; await wri ...[truncated 2268 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (23)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The skill goes beyond passive gifting assistance by maintaining persistent want lists, posting WANT listings publicly, and using API credentials against an external service without explicit permission disclosure. This broadens the action surface from local task assistance to autonomous external posting and stateful data handling, which can leak user preferences or create unintended external activity.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill goes beyond passive gifting assistance by maintaining persistent want lists, posting WANT listings publicly, and using API credentials against an external service without explicit permission disclosure. This broadens the action surface from local task assistance to autonomous external posting and stateful data handling, which can leak user preferences or create unintended external activity.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill goes beyond passive gifting assistance by maintaining persistent want lists, posting WANT listings publicly, and using API credentials against an external service without explicit permission disclosure. This broadens the action surface from local task assistance to autonomous external posting and stateful data handling, which can leak user preferences or create unintended external activity.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill goes beyond passive gifting assistance by maintaining persistent want lists, posting WANT listings publicly, and using API credentials against an external service without explicit permission disclosure. This broadens the action surface from local task assistance to autonomous external posting and stateful data handling, which can leak user preferences or create unintended external activity.

Content

No source excerpt is available for this finding.

Vague Triggers

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The trigger list includes very broad everyday phrases such as "want," "need," "browse," "search," and "match," which can cause the skill to activate in many unrelated conversations. Because the skill has access to posts, DMs, and media, unintended activation could expose private content to the skill or cause it to take gifting-related actions in the wrong context.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill documentation shows clear networked behavior through an external API and use of an API key, yet it declares no explicit tool scope or allowed-tools. This creates a permissions-transparency gap: a host agent or reviewer may not realize the skill can make outbound requests, which can enable unexpected data exfiltration or unauthorized external actions.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The example trigger phrases such as 'browse', 'want a desk', or 'scan for matches' are broad natural-language phrases that can easily appear in ordinary conversation. In agents that map free-form text to skill execution, this can cause accidental invocation, unintended network requests, public posting, or changes to listings without sufficiently explicit user intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The removal command 'remove abc123' is ambiguous and insufficiently namespaced, making it easy to trigger accidentally or to collide with unrelated agent actions. If interpreted broadly, a user or another prompt context could cause deletion of wants/listings or other state changes without clear intent verification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The manifest requests access to posts, DMs, and media while enabling automatic scanning by default every 4 hours, but the manifest text does not present a clear user-facing warning about this privacy-impacting behavior. In a gifting/matching skill, scanning communications may be functionally relevant, but default-on background monitoring increases the chance of overcollection, unexpected processing of private messages, and user surprise.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The heartbeat path silently loads the user's want list and inventory and sends queries to the external GiveAgent API on a periodic schedule, but provides no user-facing notice, consent checkpoint, or runtime indication that this background processing is occurring. Even if only listings are fetched rather than raw preferences uploaded directly, the feature continuously processes user-derived preference/inventory context in the background, which creates a privacy risk and can surprise users in a way that expands exposure if the external service, logs, or surrounding telemetry are compromised.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The pickup confirmation formatter includes exact pickup details and optional contact information in an agent-to-agent DM. While the broader file mentions exact location sharing after approval for public posts, this function itself has no confirmation prompt, warning comment, or user-facing disclosure about transmitting sensitive personal data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

If a user attaches a photo, its URL is forwarded to the external GiveAgent API as photoUrl without any explicit consent flow or clear user-facing notice in this file. Media URLs can reveal more than the image itself, including access tokens, internal storage locations, or links to private platform-hosted content, so sharing them with a third party can expose user data beyond the intended listing contents.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The factory docstring promises that content sanitization is applied to all API responses, but only Listing, WantItem, Message, and MatchResult responses are sanitized. Other returned objects such as Match and image upload results are passed through untouched, which can cause downstream callers to trust untrusted fields and render or process them unsafely. In an agent-to-agent gifting workflow that handles user-generated messages and pickup details, this mismatch increases the risk of stored XSS or unsafe data propagation into other components.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

This file enables periodic background scanning and always-on DM handling without any explicit user-facing consent, notice, or runtime gating visible at the registration point. In an agent-to-agent gifting skill, autonomous scanning and message handling can collect, process, and act on user or counterpart data outside an immediately invoked command, increasing privacy, surprise-automation, and unauthorized-action risks if users are unaware these behaviors are active.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The module docstring explicitly states that each outbound message must be human-reviewed, implying a human-approval control on agent-to-agent communications. However, functions later in the file automatically send MATCH_REQUEST, MATCH_ACCEPTED, PICKUP_CONFIRMED, and COMPLETED messages via the API without any review or confirmation step, which directly contradicts the documented intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

When pickupDetails are present, the code automatically sends address, date, time, contact, and notes to the counterpart agent via sendMessage. Although approveMatch implies some user consent, there is no explicit privacy warning or granular confirmation at the transmission point for sensitive location/contact data, increasing the risk of oversharing PII to another agent or unintended recipient.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The file explicitly defines "Common English stop words" and extracts keywords using that English-only list, which bakes a language-specific behavior into matching. Under the policy, forcing a specific language or locale without user opt-in or justification is a natural-language policy concern.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The reverse-match code fabricates a GivingPost using the want post's location instead of the actual inventory item's location, which defeats the required city check and can create false-positive matches across cities. In this skill's gifting context, that can cause incorrect disclosures, wasted outreach, and users being matched to items that are not actually local, undermining trust and enabling location-based misrepresentation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The code sends a user-supplied image URL to the runtime vision service via describeImage() without any disclosure, consent flow, or indication of what data leaves the local skill boundary. Even if the runtime is trusted, images can contain sensitive personal or location information, so silent transmission creates a privacy risk and can violate user expectations or platform policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The comment states that all output must exactly match a predefined protocol format, which can amount to forcing a fixed language/locale if that protocol is language-specific. No opt-in, locale choice, or justification is present in this file.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
99% confidence
Finding

The top-level docstring defines a 4-stage flow ending with COMPLETED as stage 4. Later, the confirmCompletion function comment labels completion as 'Stage 5', which contradicts the stated workflow and can mislead maintainers about the intended lifecycle.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The natural-language documentation says locations are parsed in the format "City, Country (XXXxx)" and gives country-specific examples, which implies a fixed locale convention. There is no nearby indication that other locale/address formats are supported by user choice or that this restriction is justified as region-specific.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The code defines a user configuration object containing giveagentApiKey, which is a sensitive credential, but this file provides no user-facing warning, comment, or disclosure about storing or handling that secret. Under the code-file criteria, access to sensitive credentials should have some visible disclosure unless clearly covered elsewhere.

Content

No source excerpt is available for this finding.