Back to skill

Security audit

macys-research

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly transparent about using Crawlora for Macy's product data, but its helper can make authenticated requests beyond the documented GET-only Macy's endpoints.

Review before installing. The Crawlora integration and API-key use are disclosed, but users should restrict use to the documented GET examples, avoid arbitrary -X POST calls, and monitor API credit use. The publisher should narrow the helper to GET-only Macy's routes and validate numeric product IDs before this is treated as fully scoped.

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

Warning
Location
scripts/crawlora.sh:48
Finding
Undocumented POST Requests Are Permitted on GET-Only Endpoints## Vulnerability Details **File Location**: `scripts/crawlora.sh`, lines 48-53 and 96-100 **Vulnerability Type**: Method allowlist exceeds the documented API capability **Risk Level**: Medium ### Vulnerable Code ```sh case "$method" in GET|POST) ;; *) echo "only GET and POST are supported by the macys-research skill" >&2 exit 2 ;; esac ``` ```sh else [ -n "$body" ] || body="${rest[0]:-}" [ -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 ``` ### Technical Analysis The endpoint catalog declares all three supported Macy's operations as `GET` endpoints. The helper nevertheless accepts `POST` and sends an arbitrary caller-controlled JSON body with the user's `CRAWLORA_API_KEY`. This creates a mismatch between the reviewed/documented capability and the executable capability. Although destination and top-level path validation remain constrained, the helper can attempt authenticated operations that the skill does not claim to support. Whether a particular request produces a side effect depends on the remote Crawlora API's handling of undocumented methods. ### Attack Path 1. An attacker influences a caller or agent to invoke the helper with `-X POST`. 2. The attacker chooses one of the paths accepted by the helper and supplies a controlled JSON body. 3. The script reads the victim's `CRAWLORA_API_KEY` from the environment. 4. The helper sends the body and API key to Crawlora using an authenticated POST request. 5. If the remote service supports undocumented POST behavior for the selected route, it processes the operation under the victim's API account. Example invocation: ```sh scripts/crawlora.sh -X POST /ma ...[truncated 606 chars]
Remediation
## Remediation Suggestions Enforce the exact HTTP method declared for each route. Because every endpoint currently documented by this skill is GET-only, reject POST entirely: ```sh [ "$method" = "GET" ] || { echo "only GET is supported by the macys-research skill" >&2 exit 2 } ``` Remove the POST body-processing branch and update usage comments so they describe only this skill's supported operations. If POST endpoints are added later, implement an explicit route-to-method allowlist rather than a global method allowlist. Add negative tests confirming that `-X POST`, unsupported methods, and bodies supplied to GET-only routes are rejected before any network request occurs.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/crawlora.sh:61
Finding
Overbroad Wildcard Allows Undocumented Product Subroutes## Vulnerability Details **File Location**: `scripts/crawlora.sh`, lines 61-68 **Vulnerability Type**: Insufficient route validation **Risk Level**: Low ### Vulnerable Code ```sh case "$path" in /macys/product/*) ;; /macys/product/reviews) ;; /macys/suggest) ;; *) echo "path is not in the macys-research skill catalog" >&2 exit 2 ;; esac ``` ### Technical Analysis The documented product-detail route is `/macys/product/{productId}`, where `productId` must be numeric. The shell wildcard `/macys/product/*` instead accepts any nonempty suffix, including additional slash-separated path segments and arbitrary nonnumeric identifiers. The wildcard also matches `/macys/product/reviews` before the explicit reviews branch is reached, making that branch redundant. Consequently, route validation does not implement the endpoint catalog's stated constraints and may expose undocumented Crawlora routes beneath the `/macys/product/` prefix. Existing checks reject query fragments, percent characters, path traversal markers, and duplicate slashes. The destination is also fixed to Crawlora. These controls limit the issue, but they do not enforce the intended route set or numeric product identifier. ### Attack Path 1. An attacker supplies an undocumented path beginning with `/macys/product/`. 2. The wildcard route check accepts the path even when its suffix is not a numeric product ID. 3. The script attaches the victim's API key through its temporary curl configuration. 4. Curl sends the authenticated request to the corresponding Crawlora API path. 5. If a matching undocumented server route exists, it is accessed under the victim's API account. Example accepted path: ```sh scripts/crawlora.sh /macys/product/undocumented-route ``` ### Impact Assessment Exploitation is constrained to the fixed Crawlora host and paths below the accepted prefix. It does not permit arbitrary-host requests, shell i ...[truncated 380 chars]
Remediation
## Remediation Suggestions Replace the broad wildcard with exact route validation. Match the reviews and suggestion routes explicitly, and require the product-detail suffix to contain digits only: ```sh case "$path" in /macys/product/reviews|/macys/suggest) ;; /macys/product/[0-9]*) product_id="${path#/macys/product/}" case "$product_id" in ""|*[!0-9]*) echo "productId must be numeric" >&2 exit 2 ;; esac ;; *) echo "path is not in the macys-research skill catalog" >&2 exit 2 ;; esac ``` Preserve the existing rejection of traversal and URL-delimiter syntax. Add tests for alphabetic IDs, extra path segments, empty IDs, encoded delimiters, traversal attempts, and undocumented subroutes. Also validate each endpoint's permitted query parameter names and required values so the executable interface precisely matches `reference/endpoints.md`.
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 (8)

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill explicitly instructs use of a shell helper script but does not declare any tool scope such as allowed-tools or permissions. That creates an avoidable mismatch between documented capabilities and declared execution boundaries, increasing the chance an agent can invoke shell access more broadly than intended.

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.