Back to skill

Security audit

기상청 날씨 (KMA Weather Korea)

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches a Korea weather and air-quality purpose, but one script reads an API key from a hard-coded other-user home path, which is a real credential-scope problem.

Install only if you are comfortable fixing or accepting the credential handling risk. Before use, change morning_briefing.sh to read the invoking user's configured key, store the key with 0700 directory and 0600 file permissions, and rotate the key if it was previously exposed through shell history or process monitoring.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/morning_briefing.sh:11
Finding
Hard-Coded Cross-User Credential File Access<![CDATA[ ## Vulnerability Details **File Location**: `scripts/morning_briefing.sh:11` **Vulnerability Type**: Cross-user credential access that violates least privilege **Risk Level**: High ### Vulnerable Code ```python API_KEY = open("/home/scott/.config/data-go-kr/api_key").read().strip() ``` ### Technical Analysis The morning briefing script reads an API key from an absolute path belonging to the fixed user `scott`. This conflicts with the documented configuration path, `~/.config/data-go-kr/api_key`, which should resolve to the account invoking the Skill. The weather functionality only requires access to the invoking user's configured API credential. Accessing a different user's home directory is not necessary. If the script is executed by a privileged service, shared automation account, or agent with broad filesystem permissions, it can read and use another user's credential without that user's authorization. Although the key is subsequently transmitted only to the documented HTTPS API host, the initial cross-user credential access violates the principle of least privilege. ### Attack Path 1. A privileged agent, service, or shared automation account invokes `morning_briefing.sh`. 2. The process has permission to read `/home/scott/.config/data-go-kr/api_key`. 3. The script reads Scott's API key regardless of which user initiated the request. 4. The script uses that credential to authenticate requests to KMA and AirKorea. 5. An operator controlling the execution environment can modify the script, trace the process, or intercept diagnostic data to recover or misuse the credential. ### Impact Assessment Successful exploitation permits unauthorized use or disclosure of another local user's data.go.kr API credential. The direct scope is limited to the services and quotas authorized by that key, but abuse may consume quotas, cause service disruption, expose associated usage records, or result in actions being attributed to the credential owner. The iss ...[truncated 317 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Resolve the credential relative to the invoking user's home directory instead of using `/home/scott`: ```python from pathlib import Path key_path = Path.home() / ".config" / "data-go-kr" / "api_key" API_KEY = key_path.read_text(encoding="utf-8").strip() ``` - Alternatively, accept an explicit configuration path through a narrowly scoped environment variable, while rejecting unexpected or untrusted paths. - Verify that the credential file is a regular file, is owned by the invoking user, and is not group- or world-readable. - Refuse to run with an effective user different from the intended account unless privileged execution is explicitly required. - Return a controlled error when the file is absent or inaccessible rather than probing another user's home directory. - Rotate the affected API key if this script has run under accounts capable of reading the hard-coded path. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:144
Finding
API Key Setup Does Not Enforce Restrictive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:144-148` **Vulnerability Type**: Insecure credential storage configuration **Risk Level**: Medium ### Vulnerable Code ```bash mkdir -p ~/.config/data-go-kr echo "YOUR_API_KEY" > ~/.config/data-go-kr/api_key ``` ### Technical Analysis The documented setup procedure creates the configuration directory and API-key file without explicitly setting secure permissions. Their resulting permissions depend on the user's current `umask`. Under a permissive `umask`, the API-key file or its parent directory may be readable or traversable by other local users. The command also encourages users to place the API key directly in an interactive shell command, which may save the credential in shell history. Credentials should be created with deterministic, restrictive permissions rather than relying on ambient system configuration. ### Attack Path 1. A user follows the documented setup instructions on a multi-user system. 2. The user's `umask` permits group or world read access. 3. The resulting `api_key` file is created with insufficiently restrictive permissions. 4. Another local user traverses the configuration directory and reads the file. 5. The attacker uses the recovered credential against the data.go.kr APIs, consuming the victim's quota or impersonating the victim's API access. A second exposure path exists if the user substitutes the actual key directly into the `echo` command and the shell records that command in persistent history. ### Impact Assessment An attacker with local account access may obtain the data.go.kr API key. The recovered key can be used from another system for any API services authorized under that credential, potentially consuming quotas, disrupting legitimate calls, and causing malicious activity to be attributed to the credential owner. This does not directly expose arbitrary files or grant operating-system privileges. Its scope is the API account and services associated wi ...[truncated 25 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Replace the setup instructions with commands that enforce restrictive permissions: ```bash install -d -m 700 "$HOME/.config/data-go-kr" install -m 600 /dev/null "$HOME/.config/data-go-kr/api_key" read -r -s -p "data.go.kr API key: " API_KEY printf '\n' printf '%s\n' "$API_KEY" > "$HOME/.config/data-go-kr/api_key" unset API_KEY ``` Additional hardening should include: - Require directory mode `0700` and file mode `0600`. - Avoid putting the actual key directly in a command that may be written to shell history. - Document how users can verify permissions with `stat`. - Have the scripts reject credential files that are group- or world-readable. - Recommend rotating the key if it was previously stored with permissive permissions or entered directly into shell history. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/weather.sh:120
Finding
API Key Exposed Through Curl Process Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/weather.sh:120-128` **Vulnerability Type**: Sensitive credential exposure through command-line arguments **Risk Level**: Medium ### Vulnerable Code ```bash RESPONSE=$(curl -s -G "$URL" --data-urlencode "serviceKey=$API_KEY" \ --data "pageNo=1" \ --data "numOfRows=1000" \ --data "dataType=JSON" \ --data "base_date=$BASE_DATE" \ --data "base_time=$BASE_TIME" \ --data "nx=$NX" \ --data "ny=$NY") ``` ### Technical Analysis The shell expands `$API_KEY` before launching `curl`, placing the resulting `serviceKey=<secret>` value in curl's process argument list. Depending on the operating system's process visibility policy, other local users, monitoring agents, diagnostic tools, or process supervisors may be able to inspect those arguments while the request is running. Using HTTPS protects the request from ordinary network interception, but it does not protect secrets exposed locally before curl establishes the encrypted connection. The network transmission itself is necessary for API authentication and is sent only to the documented `https://apis.data.go.kr` endpoint; the vulnerability is the local argv exposure. ### Attack Path 1. A user or automated service invokes `scripts/weather.sh`. 2. The shell expands `$API_KEY` into the curl command-line arguments. 3. Curl remains active while DNS resolution, connection setup, or the API request is in progress. 4. A local attacker or monitoring process reads the curl command line through process-inspection facilities. 5. The attacker extracts the `serviceKey` value. 6. The attacker reuses the key to make unauthorized data.go.kr API requests. The practical exploitation window may be short, but repeated or scheduled weather requests make observation easier. ### Impact Assessment A local attacker who can inspect process arguments may recover the API key and use all data.go.kr services authorized for it. Potential effects include qu ...[truncated 318 chars]
Remediation
<![CDATA[ ## Remediation Suggestions - Avoid expanding the API key into curl's command-line arguments. - Supply sensitive curl options through standard input using a protected curl configuration stream, for example: ```bash RESPONSE=$( { printf 'url = "%s"\n' "$URL" printf 'get\n' printf 'silent\n' printf 'data-urlencode = "serviceKey=%s"\n' "$API_KEY" printf 'data = "pageNo=1"\n' printf 'data = "numOfRows=1000"\n' printf 'data = "dataType=JSON"\n' printf 'data = "base_date=%s"\n' "$BASE_DATE" printf 'data = "base_time=%s"\n' "$BASE_TIME" printf 'data = "nx=%s"\n' "$NX" printf 'data = "ny=%s"\n' "$NY" } | curl --config - ) ``` - Ensure debugging and error output never prints the complete request URL or API key. - Run the Skill under a dedicated, unprivileged account with process visibility restricted where supported. - Avoid temporary configuration files. If one is unavoidable, create it atomically with mode `0600` and delete it using a reliable cleanup trap. - Rotate the API key if process monitoring or diagnostic capture may previously have recorded it. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The manifest presents the skill as weather-only, while the documentation also includes cross-skill air-quality access and local credential file reads. Hidden or under-declared capabilities reduce transparency and can lead operators to grant or trust broader data access than intended, especially when local file access is involved.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The manifest presents the skill as weather-only, while the documentation also includes cross-skill air-quality access and local credential file reads. Hidden or under-declared capabilities reduce transparency and can lead operators to grant or trust broader data access than intended, especially when local file access is involved.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documents shell scripts and outbound API usage but does not declare any explicit tool scope such as permissions or allowed-tools. In an agent environment, this creates an authorization gap where the runtime may permit broader shell or network access than users expect, increasing the chance of unintended command execution or external requests.

Description-Behavior Mismatch

Medium
Confidence
89% confidence
Finding
The description omits documented air-quality and notification-related scope, creating a capability disclosure gap. In agent ecosystems, incomplete disclosure can mislead reviewers and users about what external systems the skill may contact or what downstream actions it may trigger.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The intent router lists common conversational phrases such as "오늘 날씨 어때?", "기온 몇 도?", and routes based on simple keywords like 현재/지금, 내일/모레/주말, 브리핑. These are broad natural phrases and the file does not provide negative examples or constraints describing when the skill should not activate, increasing the risk of unintended invocation overlap with ordinary conversation.

Session Persistence

Medium
Category
Rogue Agent
Content
2. 로그인 → 마이페이지 → **일반 인증키(Decoding)** 복사
3. API 키 저장:
   ```bash
   mkdir -p ~/.config/data-go-kr
   echo "YOUR_API_KEY" > ~/.config/data-go-kr/api_key
   ```
4. 아래 서비스 **활용신청** 후 사용 (자동승인)
Confidence
90% confidence
Finding
The setup instructs users to persist an API key in a plaintext file under the home directory. Plaintext credential storage increases the risk of credential theft by other local processes, overly permissive file permissions, backups, or accidental disclosure through logs and support bundles.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
The script directly reads an API key from a sensitive local path, which is credential access covered by the missing-warning rule for code files. There is no confirmation prompt, user-facing disclosure, or explanatory comment warning that the skill accesses a credential file.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The manifest describes the skill as a KMA short-term forecast API for ultra-short-term observation and short-term forecast. In addition to those expected KMA weather calls, the code performs a separate AirKorea API request for particulate and ozone data, which is a distinct capability not covered by the stated description.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The script's human-facing comments, accepted aliases, and error/help text are partly or wholly Korean-specific, including Korean trigger values like 실황, 초단기, 예보, 단기, and 버전. Under the language/locale policy, forcing a specific language without user opt-in or clear justification is a policy concern.

External Transmission

Medium
Category
Data Exfiltration
Content
echo "API: $ENDPOINT | Date: $BASE_DATE | Time: $BASE_TIME | Grid: ($NX,$NY)" >&2

# 요청 실행
RESPONSE=$(curl -s -G "$URL" --data-urlencode "serviceKey=$API_KEY" \
    --data "pageNo=1" \
    --data "numOfRows=1000" \
    --data "dataType=JSON" \
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Natural-Language Policy Violations

Low
Confidence
80% confidence
Finding
Most trigger examples, routing logic, setup text, and response guidance are written only in Korean, and the skill does not state that language handling is limited to Korean or offer any user language choice. This can violate a language/locale policy when a skill implicitly forces one language without opt-in or justification.

Natural-Language Policy Violations

Low
Confidence
78% confidence
Finding
The natural-language comments, usage text, default station name, and output labels indicate the skill is designed specifically for Korean-language use, but there is no visible opt-in or documented locale restriction. This can violate the language/locale policy when a skill implicitly forces a specific language without user choice.

Context-Inappropriate Capability

Low
Confidence
78% confidence
Finding
The manifest only states a weather forecast API purpose and does not mention local file access or credential loading behavior. While credentials may be needed operationally, reading a specific user-home config file is an additional capability outside the manifested intent as written.

Missing User Warnings

Low
Confidence
81% confidence
Finding
This shell script accesses a sensitive API key from the user's config directory and later transmits it to a remote weather API. Although the code has developer comments and debug output, there is no explicit user-facing disclosure that credentials will be read and used in a network request.

Static analysis

No suspicious patterns detected.