Back to skill

Security audit

tmrland-personal-demo

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent TMR Land marketplace agent, but it needs review because it can perform money, KYC, and deletion actions while forwarding its API key to an unconstrained configurable endpoint.

Install only if you are comfortable giving this skill a TMR personal API key that can affect marketplace, wallet, KYC, orders, and disputes. Leave TMR_BASE_URL unset or set only to the official HTTPS TMR endpoint, use the narrowest API-key permissions available, keep low wallet exposure, and do not submit KYC identity numbers through shell commands or agent transcripts unless you accept that they may be logged.

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

Error
Location
scripts/_lib.mjs:6
Finding
Bearer Token and Sensitive Request Data Can Be Sent to an Arbitrary Host<![CDATA[ ## Vulnerability Details **File Location**: `scripts/_lib.mjs:6-7, 21-33` **Vulnerability Type**: Unrestricted credential forwarding through a user-configurable API endpoint **Risk Level**: High ### Vulnerable Code ```js const API_KEY = (process.env.TMR_API_KEY ?? "").trim(); const BASE_URL = (process.env.TMR_BASE_URL ?? "https://tmrland.com/api/v1").replace(/\/$/, ""); export async function tmrFetch(method, path, body = null) { const url = `${BASE_URL}${path}`; const opts = { method, headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json", }, }; if (body !== null) { opts.body = JSON.stringify(body); } const resp = await fetch(url, opts); ``` ### Technical Analysis The shared HTTP helper reads `TMR_BASE_URL` from the environment and uses it without validating its protocol, hostname, port, or origin. The helper then unconditionally attaches the `TMR_API_KEY` bearer credential to every request. Although sending the API key to the legitimate TMR Land API is necessary for the declared functionality, allowing an unrestricted destination exceeds the minimum privilege required. A malicious or accidentally modified environment can set `TMR_BASE_URL` to an attacker-controlled server, including a plaintext HTTP endpoint. Because all scripts use this helper, the affected request bodies may include: - KYC identity information - Marketplace intentions and negotiation messages - Order and contract identifiers - Dispute reasons - Wallet transaction amounts - Reviews and other account data No hostname allowlist, HTTPS requirement, or credential-origin check prevents this disclosure. ### Attack Path 1. An attacker influences the environment used to launch the Skill, such as through a wrapper, deployment configuration, shell profile, compromised automation, or misleading setup instructions. 2. The attacker sets an environment variable such as: ```bash TMR_BASE_URL=https://attacker.exam ...[truncated 1358 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Allowlist the production origin** - Parse the configured value with `new URL()`. - Require the hostname to be exactly `tmrland.com`. - Require the expected `/api/v1` path prefix. - Reject embedded credentials, unexpected ports, and malformed URLs. 2. **Require encrypted transport** - Permit only `https:` in production. - Reject plaintext HTTP before constructing or sending a request. 3. **Bind credentials to an approved origin** - Add the `Authorization` header only when the final request origin exactly matches an approved origin. - Ensure authorization is not forwarded across redirects. - Prefer disabling redirects or validating every redirect target. 4. **Separate development credentials** - If custom endpoints are needed for testing, require an explicit development-only option. - Use a separate low-privilege test credential rather than the production `TMR_API_KEY`. 5. **Apply least privilege** - Issue scoped API keys with only the endpoints required for the current operation. - Separate read-only marketplace access from KYC, wallet, payment, and destructive privileges where the platform supports it. A hardened validation pattern should resemble: ```js const configured = process.env.TMR_BASE_URL ?? "https://tmrland.com/api/v1"; const base = new URL(configured); if ( base.protocol !== "https:" || base.hostname !== "tmrland.com" || base.port !== "" || !base.pathname.startsWith("/api/v1") ) { throw new Error("Unapproved TMR API endpoint"); } const url = new URL(path.replace(/^\//, ""), `${base.href.replace(/\/?$/, "/")}`); if (url.origin !== base.origin) { throw new Error("Cross-origin API request rejected"); } ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/submit-kyc.mjs:4
Finding
KYC Identity Information Is Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/submit-kyc.mjs:4-15` **Vulnerability Type**: Sensitive personal data exposure through process arguments and shell history **Risk Level**: Medium ### Vulnerable Code ```js const { help, named } = parseArgs(process.argv); if (help || !named.name || !named["id-type"] || !named["id-number"]) { console.error("Usage: submit-kyc.mjs --name '...' --id-type passport|national_id|driver_license --id-number '...'"); process.exit(2); } const body = { name: named.name, id_type: named["id-type"], id_number: named["id-number"], }; const data = await tmrFetch("POST", `/wallet/kyc`, body); console.log(JSON.stringify(data, null, 2)); ``` ### Technical Analysis The KYC script requires a legal name and identity-document number to be supplied directly as command-line arguments. Command-line arguments are not a suitable secret-input channel. Depending on the operating system and execution environment, these values may be exposed through: - Interactive shell history - Process inspection tools - Process accounting or endpoint monitoring - CI/CD command logs - Agent execution transcripts - Debugging and telemetry systems - Parent-process logging The KYC operation legitimately requires identity data, but exposing that data in `process.argv` is not necessary. The script should use a protected input channel instead. The shared HTTP helper also prints complete API error bodies. If the remote service reflects submitted values in validation errors, those values could be copied into terminal or automation logs. The documented successful response masks the identity number, but the script does not independently redact output. ### Attack Path 1. A user follows the documented invocation pattern: ```bash node scripts/submit-kyc.mjs \ --name "Legal Name" \ --id-type passport \ --id-number "P123456789" ``` 2. The command, including the legal name and identity number, may be saved in shell hist ...[truncated 1045 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Remove sensitive command-line parameters** - Do not accept legal names or identity numbers through `process.argv`. - Avoid including realistic identity numbers in usage examples. 2. **Use protected input** - Read structured KYC input from standard input. - For interactive use, prompt for the identity number with terminal echo disabled. - If file input is supported, require restrictive permissions and avoid persistent temporary files. 3. **Minimize output** - Print only the KYC submission status. - Redact identity values from successful responses and errors. - Do not print the complete response object unless an explicit secure debugging mode is enabled. 4. **Harden operational guidance** - Warn users that KYC data is sensitive. - Instruct automation systems to use secret-masked input channels. - Ensure Agent transcripts and CI/CD logs do not retain submitted KYC data. 5. **Correct the request schema** - The API reference specifies `full_name`, while the script sends `name`. - Align the request field with the documented schema to prevent validation failures that could increase logging of sensitive requests. A safer interface would accept JSON through standard input: ```js let input = ""; for await (const chunk of process.stdin) { input += chunk; } const body = JSON.parse(input); const data = await tmrFetch("POST", "/wallet/kyc", { full_name: body.full_name, id_type: body.id_type, id_number: body.id_number, }); console.log(JSON.stringify({ kyc_status: data.kyc_status }, null, 2)); ``` ]]>
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (58)

Tool Parameter Abuse

High
Category
Tool Misuse
Content
---

## DELETE /api/v1/api-keys/{key_id}

Permanently revoke and delete an API key. Only the key owner can delete their own keys.
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### Request Example

```
DELETE /api/v1/api-keys/d4e5f6a7-b8c9-0123-defa-234567890123
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
```
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Missing User Warnings

High
Confidence
98% confidence
Finding
Showing one-time verification codes in response examples without an explicit warning normalizes an unsafe pattern and increases the risk developers copy it into real implementations. Because this skill covers authentication for business marketplace accounts, leaked login codes could directly enable unauthorized access to financial, identity, or escrow-related actions.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The documented `send-code` response includes a `code_preview` containing the one-time login code, which defeats the purpose of out-of-band verification if implemented in production. In a marketplace and escrow context, exposing OTPs would let any caller initiate passwordless login and immediately obtain the code needed to authenticate, enabling account takeover.

Context-Inappropriate Capability

High
Confidence
99% confidence
Finding
The documented `forgot-password` response exposes a password reset code directly in the API response, collapsing the reset flow into a single unauthenticated request. If this behavior exists, an attacker who knows a user's email could request a reset and use the returned code to proceed toward changing the victim's password.

Missing User Warnings

High
Confidence
98% confidence
Finding
Documenting reset codes in example responses without clear security warnings promotes a dangerous implementation pattern for account recovery. In this marketplace context, compromised reset flows can cascade into account takeover, fraudulent transactions, and exposure of sensitive user and business data.

Credential Access

High
Category
Privilege Escalation
Content
| Status | Code | Description |
|---|---|---|
| 401 | `not_authenticated` | Missing or invalid access token |
| 404 | `business_not_found` | No business with this ID |

---
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
| Status | Code | Description |
|---|---|---|
| 401 | `not_authenticated` | Missing or invalid access token |
| 404 | `business_not_found` | No business with this ID |

---
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
| Status | Code | Description |
|---|---|---|
| 401 | `not_authenticated` | Missing or invalid access token |
| 404 | `business_not_found` | No business with this ID |

---
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
| Status | Code | Description |
|---|---|---|
| 401 | `not_authenticated` | Missing or invalid access token |
| 404 | `business_not_found` | No business with this ID |

---
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
---

## DELETE /api/v1/intentions/{intention_id}

Hard-delete an intention and all associated data (profile, candidates, negotiation sessions). Active negotiation sessions are automatically cancelled before deletion. Blocked for intentions with `contracted` status.
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Tool Parameter Abuse

High
Category
Tool Misuse
Content
### Request Example

```
DELETE /api/v1/intentions/f6a7b8c9-d0e1-2345-fabc-456789012345
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
```
Confidence
80% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Missing User Warnings

High
Confidence
93% confidence
Finding
The accept endpoint creates a contract and order from a final_deal, but the API description does not emphasize the commitment and side effects beyond the response example. In an agent-driven marketplace, this increases the risk of accidental acceptance by users or automated clients, potentially committing funds and creating binding transactions without adequate confirmation semantics.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill advertises extensive network-backed transactional capabilities but does not declare any explicit tool scope or allowed-tools boundary. In an agent environment, this weakens least-privilege controls and can let the skill invoke broader network/code functionality than users or the host platform may expect, which is especially risky because the documented operations include payments, escrow release, KYC, wallet withdrawals, and disputes.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
Three levels define how the agent handles each parameter:

- **AUTO** — Agent can infer directly without asking (IDs, locale, pagination).
- **CONFIRM** — Agent may draft a value but MUST show it to the user for approval before submitting.
- **ASK** — Agent MUST ask the user directly. Never guess or generate.
Confidence
88% confidence
Finding
The skill explicitly authorizes the agent to infer some parameters and proceed 'without asking,' which introduces autonomous decision-making in a workflow that includes financially and operationally sensitive actions. Even though some destructive operations require confirmation, AUTO handling of identifiers and workflow state can still cause the agent to act on the wrong resource, continue a risky sequence farther than intended, or submit actions based on incorrect context.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The documentation describes creation of long-lived API credentials and notes that the raw key is only shown once, but it omits explicit handling guidance such as secure storage, prohibition on logging/sharing, rotation, and the consequences of exposure. In an agent/SDK integration context, this increases the chance that users or downstream tools mishandle secrets, leading to credential leakage and unauthorized access.

Natural-Language Policy Violations

Medium
Confidence
87% confidence
Finding
This documentation states that `locale_preference` defaults to `zh`, which imposes a specific language/locale on users who do not explicitly choose one. Under the policy, forcing a locale without user opt-in is a natural-language policy violation unless clearly justified or optional.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The `reset-password` section says the endpoint expects a reset token from the prior verification step, but the example supplies a short code instead. This inconsistency can lead implementers to accept weaker direct codes at the final reset step or to bypass the intended token exchange, weakening the password reset design and increasing the chance of insecure implementations.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
This markdown file documents public unauthenticated endpoints and includes `user_id` fields in example responses, but it provides no warning that these identifiers are publicly exposed or may have privacy implications. Under the markdown-specific warning rule, documentation should disclose behaviors that can affect user data or privacy when public access is involved.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The summary endpoint exposes business profiling and reputation data without authentication, and the documentation provides no warning about privacy, enumeration, or misuse risks. Even if the data is intended to be public, unauthenticated bulk access can enable scraping, profiling, and automated ranking of businesses at scale.

Missing User Warnings

Medium
Confidence
82% confidence
Finding
The API is explicitly designed for autonomous decision-making and deep-dive analysis of reputation, review, and dispute data, but the documentation omits safeguards or warnings about sensitive profiling and automated use. This increases the risk of unfair ranking, overreliance on noisy reputation signals, and secondary misuse of dispute/review histories by agents.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The API documentation states that disputes are resolved by 9 AI jurors and exposes juror vote reasoning, but it does not clearly warn users at submission time that their dispute text and evidence URLs will be processed and shared with automated evaluators. In a marketplace handling potentially sensitive business, contractual, and performance evidence, this omission can lead users to disclose confidential or personal data without informed consent, increasing privacy, confidentiality, and compliance risk.

Natural-Language Policy Violations

Medium
Confidence
96% confidence
Finding
The request schema states that the locale defaults to "zh", which imposes a specific language/locale behavior when the user does not choose one. This is a natural-language policy concern because the documentation does not present locale selection as an explicit user opt-in or justify the default as region-specific.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The markdown documents a hard-delete operation that removes an intention and all associated data, and auto-cancels active negotiation sessions, but it does not include any explicit caution or user-facing warning about the irreversible impact. For markdown files, destructive behaviors affecting user data should be accompanied by a clear warning.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
This endpoint description says it creates an intention, generates an NLP profile, matches businesses, and returns results synchronously, which implies user-submitted content is analyzed and shared with matching systems. The markdown does not warn users that their content will be processed for profiling/matching or persisted as an intention.

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/_lib.mjs:6

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/api-keys-api.md:75

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/apparatus-api.md:255

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/contracts-api.md:31

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/intentions-api.md:83

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/messages-api.md:28

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/notifications-api.md:29

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/reviews-api.md:88

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/user-api.md:23

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
references/wallet-api.md:23