Back to skill

Security audit

AFOL BrickEconomy

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a coherent read-only BrickEconomy helper, but it can send the user's API key to an arbitrary configured URL and can expose full private collection or sales data.

Install only if you trust the environment using your BrickEconomy API key. Do not set BRICKECONOMY_BASE_URL or pass --base-url unless it is exactly the real BrickEconomy API endpoint, and be aware that collection and sales-ledger commands may place detailed private financial and note data into terminal output or agent logs.

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/brickeconomy_cli.py:49
Finding

API Key Disclosure Through an Unrestricted API Base URL

Content
View full analysis
Any: query = urllib.parse.urlencode(clean_params(params or {}), doseq=True) url = f"{self.base_url}{path}" if query: url = f"{url}?{query}" headers = {"Accept": "application/json", "x-apikey": self.api_key} return self._request("GET", url, headers) def _request(self, method: str, url: str, headers: dict[str, str]) -> Any: request = urllib.request.Request(url, headers=headers, method=method) try: with urllib.request.urlopen(request, timeout=self.timeout) as response: raw = response.read().decode("utf-8") ``` The destination is exposed as a command-line or environment-controlled value: ```python parser.add_argument( "--base-url", default=os.getenv("BRICKECONOMY_BASE_URL", DEFAULT_BASE_URL), help="BrickEconomy API base URL", ) ``` ```python def client_from_args(args: argparse.Namespace) -> BrickEconomyClient: return BrickEconomyClient(require_api_key(), args.base_url, args.timeout) ``` ### Technical Analysis The CLI permits `--base-url` and `BRICKECONOMY_BASE_URL` to specify an arbitrary URL. It does not validate the URL scheme, hostname, port, or path before attaching the real `BRICKECONOMY_API_KEY` as the `x-apikey` header. Consequently, the credential is not restricted to the documented BrickEconomy endpoint, `https://www.brickeconomy. ...[truncated 2041 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/brickeconomy_cli.py:183
Finding

Unminimized Output of Complete Private Collections and Sales-Ledger Data

Content
View full analysis
Any: path = "/collection/sets" params = {"currency": args.currency} if dry_run(args, path, params): return None return client_from_args(args).get(path, params) def cmd_collection_minifigs(args: argparse.Namespace) -> Any: path = "/collection/minifigs" params = {"currency": args.currency} if dry_run(args, path, params): return None return client_from_args(args).get(path, params) def cmd_sales_ledger(args: argparse.Namespace) -> Any: # Provider quirk: the checked-in OpenAPI spec does not define a currency # parameter for /salesledger, unlike set/minifig/collection value endpoints. path = "/salesledger" if dry_run(args, path): return None return client_from_args(args).get(path) def main(argv: list[str] | None = None) -> int: parser = build_parser() args = parser.parse_args(argv) try: result = args.handler(args) if result is not None: print_json(result) return 0 except BrickEconomyCliError as exc: print(f"error: {exc}", file=sys.stderr) return 2 ``` The accompanying prompt guidance further encourages complete output: ```text ALWAYS return complete collections - don't limit results Let users explore all their data with appropriate sorting ``` ### Technical Analysis The collection and sales-ledger commands retrieve the complete authenticated datasets and pass the full API response to `print_json()`. No field selection, redaction, aggregation, or output confirmation is applied. The checked-in OpenAPI schema shows that sales-ledger responses may contain: - Origi ...[truncated 2152 chars]
Remediation
View remediation
Vulnerability Patterns
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill invokes a CLI that uses both environment variables and outbound network access, but the manifest does not declare any explicit tool scope such as allowed tools or permissions. That weakens least-privilege controls and makes it harder for a host agent to enforce or audit what the skill is allowed to access, especially because the skill handles a secret API key and can reach authenticated personal collection and sales-ledger endpoints.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The API description broadly states that it supports automated interaction with personal collection data but does not define when such access should occur or what constraints govern it. In an agent skill context, ambiguous trigger scope increases the chance that sensitive account data is fetched unnecessarily or without sufficiently informed user intent.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The OpenAPI spec includes authenticated endpoints that return a user's entire set and minifig collection, including acquisition dates, paid prices, current values, growth, and historical periods. That exceeds a narrow public-reference valuation use case and creates a real data-minimization risk if the skill can invoke these endpoints without an explicit, user-scoped reason for access.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The collection and sales endpoints are described as routine getters without any warning that they access sensitive account-specific inventory and transaction history. In a skill environment, this missing disclosure makes the capability more dangerous because users may not realize the tool can retrieve detailed personal financial and collection records.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The sales ledger endpoint exposes account-specific transactional history, including sale dates, prices, fees, notes, buy dates, and buy prices. This is sensitive financial and behavioral data, and exposing it through a skill whose description emphasizes valuation/analysis can enable over-collection of personal information beyond what users may reasonably expect.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/prompts/brickeconomy-tools.txt (reported line 92)May include surrounding context.

text
- Be efficient: Don't call APIs unnecessarily
- If user asks about multiple sets, consider batching questions
- Collection tools return ALL items in a single API call - use them instead of pagination
- Don't ask users to paginate through collection results - return everything sorted appropriately

Collection Sorting Best Practices:
- Default to 'growth' sort when user asks about "best performers" or "investments"

Static analysis

No suspicious patterns detected.