Back to skill

Security audit

KTO TourAPI CLI

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent Korea tourism API wrapper, but one command can be tricked into running shell code and an environment override can redirect the TourAPI key.

Review before installing. Use only with trusted prompts, trusted command arguments, and a trusted environment. Do not expose nearby.sh through automation or user-facing tools until radius is validated as a plain integer, and pin TOURAPI_BASE to the official HTTPS TourAPI endpoint or use a low-value test key for nonproduction endpoints.

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/nearby.sh:19
Finding
Bash Arithmetic Expression Injection Through the Radius Argument<![CDATA[ ## Vulnerability Details **File Location**: `scripts/nearby.sh:19-42` **Vulnerability Type**: Bash arithmetic expression injection **Risk Level**: High ### Vulnerable Code ```bash lng="" lat="" radius="1000" cti="" arrange="E" num="20" page="1" while [[ $# -gt 0 ]]; do case "$1" in --lng) lng="$2"; shift 2;; --lat) lat="$2"; shift 2;; --radius) radius="$2"; shift 2;; --content-type-id) cti="$2"; shift 2;; --arrange) arrange="$2"; shift 2;; --num) num="$2"; shift 2;; --page) page="$2"; shift 2;; -h|--help) sed -n '2,14p' "$0" | sed 's/^# \{0,1\}//' exit 0;; *) echo "error: unknown flag '$1'" >&2; exit 64;; esac done [[ -z "$lng" || -z "$lat" ]] && { echo "error: --lng and --lat are required." >&2; exit 64; } [[ -n "$cti" ]] && valid_content_type "$cti" if (( radius > 20000 )); then echo "error: --radius max is 20000 (got $radius)." >&2; exit 64 fi ``` ### Technical Analysis The value supplied through `--radius` is stored without numeric validation and then evaluated directly in a Bash arithmetic context: ```bash (( radius > 20000 )) ``` Bash arithmetic expressions are not equivalent to safely parsing an integer. Variable values can be recursively interpreted as arithmetic syntax. Crafted expressions containing array subscripts and command substitutions can therefore cause shell commands to execute during arithmetic evaluation. An illustrative malicious value is: ```bash 'x[$(touch /tmp/nearby-injection)0]' ``` When Bash resolves this value as an arithmetic expression, the command substitution can execute before the numeric comparison completes. Quoting the value when it is assigned does not prevent its subsequent interpretation by `(( ... ))`. ### Attack Path 1. An attacker gains control over an argument passed to `nearby.sh`, such as through an AI-generated tool invocation, web req ...[truncated 1480 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Validate the radius as a decimal integer before using any arithmetic expression: ```bash [[ "$radius" =~ ^[0-9]+$ ]] || { echo "error: --radius must be a positive integer." >&2 exit 64 } if (( 10#$radius < 1 || 10#$radius > 20000 )); then echo "error: --radius must be between 1 and 20000." >&2 exit 64 fi ``` The `10#` prefix forces decimal interpretation and avoids unintended octal handling for values with leading zeroes. Apply strict validation to the other numeric arguments as well: - `--lng`: decimal number within `-180` to `180`. - `--lat`: decimal number within `-90` to `90`. - `--num`: positive integer with a documented upper bound. - `--page`: positive integer. - Area and district codes: digits only where required. Argument handlers should also verify that a value exists before reading `$2`, so malformed invocations produce a controlled usage error rather than an unbound-variable failure. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/_common.sh:9
Finding
TourAPI Credential Disclosure Through an Unrestricted Base URL Override<![CDATA[ ## Vulnerability Details **File Location**: `scripts/_common.sh:9-11,52-74` **Vulnerability Type**: Unrestricted credential destination and sensitive data in process arguments **Risk Level**: Medium ### Vulnerable Code ```bash TOURAPI_BASE="${TOURAPI_BASE:-https://apis.data.go.kr/B551011/KorService2}" TOURAPI_MOBILE_OS="${TOURAPI_MOBILE_OS:-ETC}" TOURAPI_MOBILE_APP="${TOURAPI_MOBILE_APP:-kto-tourapi-cli}" ``` ```bash tourapi_get() { local path="$1"; shift require_key local url="${TOURAPI_BASE}/${path}" # Encode service key (some keys contain '+' '/' '=' which must be URL-encoded). local enc_key enc_key=$(printf '%s' "$TOURAPI_SERVICE_KEY" | jq -Rrn '@uri inputs') local qs="serviceKey=${enc_key}&MobileOS=${TOURAPI_MOBILE_OS}&MobileApp=${TOURAPI_MOBILE_APP}&_type=json" local kv k v enc_v for kv in "$@"; do [[ -z "$kv" ]] && continue k="${kv%%=*}" v="${kv#*=}" [[ -z "$v" ]] && continue enc_v=$(printf '%s' "$v" | jq -Rrn '@uri inputs') qs="${qs}&${k}=${enc_v}" done local out http out=$(mktemp) http=$(curl -sS -G -o "$out" -w '%{http_code}' "${url}?${qs}" || true) ``` ### Technical Analysis `TOURAPI_BASE` is accepted from the process environment without validating its scheme, host, port, or path. The helper then appends the URL-encoded `TOURAPI_SERVICE_KEY` to every request. Consequently, a modified environment can redirect the credential to: - An attacker-controlled HTTPS server. - An unencrypted HTTP endpoint. - An unintended internal service. - A local listener that records the request. The full URL, including the service key, is also passed to `curl` as a command-line argument. Depending on operating-system process visibility controls, command tracing, debugging configuration, or monitoring software, another local user or logging system may be able to observe it. The base URL override is documented as optional, but no trust boundary or restriction is enforced. This is especially risky when t ...[truncated 1758 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Validate the destination before any request carrying the service key. For production use, allow only the documented HTTPS origin: ```bash readonly DEFAULT_TOURAPI_BASE='https://apis.data.go.kr/B551011/KorService2' TOURAPI_BASE="${TOURAPI_BASE:-$DEFAULT_TOURAPI_BASE}" case "$TOURAPI_BASE" in https://apis.data.go.kr/B551011/KorService2) ;; *) echo "error: TOURAPI_BASE must use the approved HTTPS TourAPI endpoint." >&2 exit 78 ;; esac ``` If alternate endpoints are genuinely required for testing: 1. Require an explicit development-only opt-in. 2. Require an `https://` scheme. 3. Maintain an allowlist of trusted hostnames. 4. Reject embedded user information, fragments, unexpected ports, and ambiguous URL forms. 5. Do not permit production credentials when a nonproduction endpoint is selected. 6. Use a separate low-value test credential for mock or staging servers. Reduce local credential exposure by avoiding secrets in visible command-line arguments. One option is to provide sensitive curl configuration through standard input or a permission-restricted temporary configuration file, with guaranteed cleanup through a trap. Disable shell tracing around credential construction and requests: ```bash set +x # Construct and perform the authenticated request here. ``` Also URL-encode `TOURAPI_MOBILE_OS` and `TOURAPI_MOBILE_APP` instead of directly concatenating them into the query string, and ensure CI systems and error handlers redact any `serviceKey` value before logging URLs. ]]>
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (2)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill exposes shell-based capabilities through multiple `bash scripts/*.sh` commands but does not declare an explicit tool scope such as `permissions` or `allowed-tools`. In an agent ecosystem, this weakens least-privilege controls and can allow broader-than-expected shell execution, especially if downstream prompts or integrations can influence command arguments.

Natural-Language Policy Violations

Low
Confidence
82% confidence
Finding
The file mixes English with Korean-only command guidance and labels such as service names and usage examples, but does not indicate that the skill is Korean-only by design or offer an alternative language option. Under the stated policy, forcing a specific language or locale without user opt-in can be a natural-language policy violation.

Static analysis

No suspicious patterns detected.