Back to skill

Security audit

ats-job-boards-research

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed helper for querying public ATS job-board data through Crawlora, with one overbroad POST-capable helper behavior users should be aware of.

Install only if you are comfortable sending ATS slugs, company domains, job IDs, filters, and your Crawlora API key to Crawlora. Avoid using it for confidential target lists or internal identifiers, and do not ask the agent to place secrets or private context into POST bodies or query parameters.

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:35
Finding
Unnecessary POST Support Permits Sensitive Data Forwarding to a Third-Party API<![CDATA[ ## Vulnerability Details **File Location**: `scripts/crawlora.sh`, lines 35–43, 54–59, and 119–126 **Vulnerability Type**: Excessive network capability and arbitrary request-body forwarding **Risk Level**: Medium ### Vulnerable Code ```bash method="GET" body="" args=() while [ $# -gt 0 ]; do case "$1" in -X) method="$2"; shift 2 ;; -d) body="$2"; shift 2 ;; *) args+=("$1"); shift ;; esac done ``` ```bash case "$method" in GET|POST) ;; *) echo "only GET and POST are supported by the ats-job-boards-research skill" >&2 exit 2 ;; esac ``` ```bash 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 in `reference/endpoints.md` documents all 30 supported ATS endpoints as HTTP `GET` operations. Nevertheless, the helper accepts `POST` and allows the caller to provide an arbitrary JSON request body through `-d` or a positional argument. It then forwards that body to `https://api.crawlora.net/api/v1`. Although the destination is fixed, uses HTTPS, and cannot be redirected through an environment variable, arbitrary request-body transmission is not required for the declared ATS job-board research functionality. It therefore exceeds the skill's minimum necessary network privileges. The implementation protects against curl's `@file` expansion by streaming the body through standard input. Consequently, this issue does not independently permit arbitrary local-file reads. Exploitation instead requires an agent, user, or untrusted instruction source to place sensitive information directly into the body. The fixed destination and route allowlist limit disclosure to the Crawl ...[truncated 1685 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove support for `POST`, `-X`, and `-d`, because every endpoint documented for this skill uses GET: ```bash method="GET" args=("$@") ``` 2. Reject method-related options explicitly so they cannot be interpreted as ordinary arguments: ```bash case "${1:-}" in -X|-d|--request|--data|--data-raw|--data-binary) echo "only documented GET requests are supported" >&2 exit 2 ;; esac ``` 3. Validate query parameter names separately for each allowed endpoint. For example, `/jobs/company-search` should accept only `slug`, while `/jobs/greenhouse/job` should accept only `token` and `id`. 4. Reject malformed arguments that do not follow the expected `name=value` form and enforce reasonable value-length limits. 5. Retain the existing fixed HTTPS API base, route allowlist, API-key character validation, private temporary configuration file, and rejection of curl `@file` syntax. 6. Add automated tests confirming that POST requests, body options, undocumented parameters, non-allowlisted paths, path traversal syntax, and local-file expansion attempts are rejected before any network request occurs. ]]>
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
89% confidence
Finding
The skill invokes shell commands (`scripts/crawlora.sh ... | jq ...`) but does not declare any tool scope, permissions, or allowed-tools constraints. That mismatch can let an agent execute shell-based network actions without explicit sandboxing expectations, increasing the chance of overbroad command execution or misuse in environments that rely on manifest-declared tool restrictions.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The file explicitly instructs callers to send requests to a third-party service using an API key, but it does not disclose that user-provided company slugs, job IDs, domains, and search terms will be transmitted off-platform. In a skill context, this is a real data-handling transparency issue because users may provide sensitive research targets or internal identifiers without realizing they are being sent to Crawlora.

External Transmission

Medium
Category
Data Exfiltration
Content
Endpoints this skill uses, grouped by platform. Call them via `scripts/crawlora.sh` (see SKILL.md).

All paths are relative to the API base `https://api.crawlora.net/api/v1` and require the header `x-api-key: $CRAWLORA_API_KEY`. Path params like `{id}` are substituted into the URL; `GET` params go in the query string; `POST` params go in a JSON body.

**30 endpoints across 1 platform group(s).**
Confidence
95% confidence
Finding
The reference documents direct outbound requests to https://api.crawlora.net/api/v1 with authentication via x-api-key, confirming external data transmission to a third-party API. Although the service appears to be the intended backend for the skill and the data is mostly public ATS lookup data, any user-supplied parameters and metadata are still exposed to an external provider, which creates privacy, compliance, and auditability risks if not disclosed and controlled.

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.

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.