Back to skill

Security audit

costco-research

Security checks for vulnerabilities and agentic risk

Overview

The skill is mainly a disclosed Costco research helper, but its authenticated API script allows broader POST and nested Costco routes than the documented read-only endpoints.

Install only if you are comfortable giving this skill a Crawlora API key and sending Costco search terms plus any ZIP/state or coordinates you provide to Crawlora. Review is warranted because the helper can make authenticated POST calls and reach undocumented nested Costco API paths, so it should be tightened to documented GET-only routes before use in sensitive or automated workflows.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/crawlora.sh:43
Finding
Overly Broad API Route and HTTP Method Authorization<![CDATA[ ## Vulnerability Details **File Location**: `scripts/crawlora.sh`, lines 43–68 **Vulnerability Type**: Insufficient route and method allowlisting **Risk Level**: Medium ### Vulnerable Code ```bash [ "${#args[@]}" -ge 1 ] || { echo "usage: crawlora.sh [-X METHOD] /path [k=v ... | json-body]" >&2; exit 2; } path="${args[0]}" rest=("${args[@]:1}") # This skill's helper is limited to its documented Crawlora route set. Keep # caller-account surfaces and unrelated API routes out of the helper even if # someone supplies an undocumented path directly. case "$method" in GET|POST) ;; *) echo "only GET and POST are supported by the costco-research skill" >&2 exit 2 ;; esac # Reject path syntax that could smuggle a route through a shell glob check. case "$path" in ""|*[?#%]*|*..*|*//* ) echo "invalid path for the costco-research skill" >&2 exit 2 ;; esac case "$path" in /costco/categories) ;; /costco/product/*) ;; /costco/product/*/availability) ;; /costco/product/*/reviews) ;; /costco/search) ;; /costco/warehouses) ;; *) echo "path is not in the costco-research skill catalog" >&2 exit 2 ;; esac ``` ### Technical Analysis The endpoint reference documents six read-only `GET` endpoints, but the helper authorizes both `GET` and `POST` for all accepted paths. POST access is not necessary for the Skill’s declared Costco research functionality. The route pattern `/costco/product/*` is also broader than the documented `/costco/product/{id}` route. In a shell `case` pattern, `*` can match slash characters and multiple path segments. Consequently, this pattern accepts arbitrary nested paths such as `/costco/product/123/undocumented-route`. Because it appears before the more specific availability and reviews patterns, those later patterns do not constrain product subroutes. Requests accepted through this broad allowlist are authenticated with the user's `CRAWLORA_API_KEY`. The fixed HTTPS origin prevents redir ...[truncated 1686 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove POST support because every endpoint documented in `reference/endpoints.md` uses GET: ```bash [ "$method" = "GET" ] || { echo "only GET is supported by the costco-research skill" >&2 exit 2 } ``` 2. Replace the broad `/costco/product/*` pattern with explicit route validation that permits exactly one product-ID segment: - `/costco/product/{id}` - `/costco/product/{id}/availability` - `/costco/product/{id}/reviews` 3. Validate product IDs against the narrowest format supported by Costco, preferably numeric-only if that is guaranteed by the API. At minimum, reject empty IDs and IDs containing `/`. 4. Keep the exact allowlist for: - `/costco/categories` - `/costco/search` - `/costco/warehouses` 5. Add negative tests confirming rejection of: - Every POST request. - `/costco/product/123/extra` - `/costco/product/123/reviews/extra` - Empty or multi-segment product IDs. - Undocumented account, billing, or administrative routes. 6. Retain the existing fixed HTTPS API origin, restricted API-key format, private temporary configuration file, and rejection of curl file-upload syntax. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (9)

Lp3

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding
The skill invokes shell commands (`scripts/crawlora.sh ... | jq`) but does not declare any tool scope such as `allowed-tools` or permissions. That creates an under-specified trust boundary: a host may expose broader shell capability than intended, increasing the risk of unintended command execution or misuse if the skill is run in a permissive environment.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This markdown file explains that requests require an `x-api-key` header and later documents endpoints using ZIP code and latitude/longitude, but it does not include any warning that the skill handles sensitive credential or location information. For markdown files, omitting warnings about behaviors that could affect privacy or system integrity is in scope for SQP-2.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
# Crawlora REST helper — minimal, dependency-free (curl only).
# Calls https://api.crawlora.net/api/v1 with your Crawlora API key.
# Get a free key (2,000 credits/mo, no card) at https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills.
#
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
# Crawlora REST helper — minimal, dependency-free (curl only).
# Calls https://api.crawlora.net/api/v1 with your Crawlora API key.
# Get a free key (2,000 credits/mo, no card) at https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills.
#
# Usage:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
# Crawlora REST helper — minimal, dependency-free (curl only).
# Calls https://api.crawlora.net/api/v1 with your Crawlora API key.
# Get a free key (2,000 credits/mo, no card) at https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills.
#
# Usage:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
# Crawlora REST helper — minimal, dependency-free (curl only).
# Calls https://api.crawlora.net/api/v1 with your Crawlora API key.
# Get a free key (2,000 credits/mo, no card) at https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills.
#
# Usage:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
#!/usr/bin/env bash
# Crawlora REST helper — minimal, dependency-free (curl only).
# Calls https://api.crawlora.net/api/v1 with your Crawlora API key.
# Get a free key (2,000 credits/mo, no card) at https://crawlora.net?utm_source=github&utm_medium=referral&utm_campaign=crawlora-skills.
#
# Usage:
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# Keep the API key out of the curl process command line. A private temporary
# config supplies the header and is removed automatically on exit.
curl_config="$(mktemp "${TMPDIR:-/tmp}/crawlora-curl.XXXXXX")"
chmod 600 "$curl_config"
trap 'rm -f "$curl_config"' EXIT
printf 'header = "x-api-key: %s"\n' "$CRAWLORA_API_KEY" >"$curl_config"
auth=(--config "$curl_config")
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

External Transmission

Medium
Category
Data Exfiltration
Content
[ -n "$body" ] || body='{}'
  # Stream the body on stdin so curl never interprets a user value as its
  # @file shorthand (and cannot read local files supplied in a request body).
  printf '%s' "$body" | curl -fsS -X "$method" "${auth[@]}" \
    -H "Content-Type: application/json" --data-binary @- "${base}${path}"
fi
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Static analysis

No suspicious patterns detected.