{"data":{"skill":{"slug":"tahodev-taiwan-weather","name":"taiwan-weather","icon":"📦","repo":"https://github.com/tahodev/baodao-skill/tree/3ce4b58e4525f5a66390e1236b6d38702790225a/taiwan-weather","status":"approved","author":"tahodev","authorVersion":null,"skillstoreRevision":1},"audit":{"id":"140de2b4-60bd-448c-9043-01b28d93765c","skill_id":"295076f5-7915-4b0f-bd0b-05c327f17cb5","version":1,"content_hash":"v3:2aab20a3878daa05021884e089a7dd7739e08581:52ec4b080ca3d5c0f1ff6caeff84857294ef1bc87a7e76211c5e0a3a9f8d47a8:f2d143b35673eaeb7ce33e54d4e66bbfc41d1c2cfb7b2e36921050f560a082d5:736b696c6c732f7461686f6465762f74616977616e2d77656174686572:693deca285d79a26955a4cf5d171bc72","risk_level":"safe","is_blocked":false,"safe_to_publish":true,"analysis_status":"ok","agent_auto_install_policy":"allowed","manual_install_policy":"allowed","summary":"Markdown backticks, public weather URLs, and readable Chinese documentation explain the command, network, and entropy false positives. Two filesystem findings confirm shared temporary-file risks: symlink-based overwrite and local alert-data substitution. No evidence found of prompt injection, credential theft, or intentional data exfiltration.","remediation":[{"issue":"SKILL.md:106 downloads to a predictable shared temporary path that can follow an attacker-created symlink.","severity":"medium","suggestion":"Create a private temporary directory with mktemp -d, download inside it, and remove it after processing."},{"issue":"SKILL.md:127 reads the shared temporary path, allowing substituted or stale alert data to be reported.","severity":"medium","suggestion":"Read only the private file from a verified successful download; stop on HTTP failures and validate alert timestamps before reporting."}],"risk_factor_evidence":[{"factor":"external_commands","evidence":[{"file":"SKILL.md","line_end":14,"line_start":14},{"file":"SKILL.md","line_end":16,"line_start":16},{"file":"SKILL.md","line_end":57,"line_start":57},{"file":"SKILL.md","line_end":61,"line_start":59},{"file":"SKILL.md","line_end":63,"line_start":61},{"file":"SKILL.md","line_end":63,"line_start":63},{"file":"SKILL.md","line_end":73,"line_start":67},{"file":"SKILL.md","line_end":75,"line_start":73},{"file":"SKILL.md","line_end":75,"line_start":75},{"file":"SKILL.md","line_end":95,"line_start":95},{"file":"SKILL.md","line_end":96,"line_start":96},{"file":"SKILL.md","line_end":97,"line_start":97},{"file":"SKILL.md","line_end":107,"line_start":105},{"file":"SKILL.md","line_end":109,"line_start":107},{"file":"SKILL.md","line_end":121,"line_start":109},{"file":"SKILL.md","line_end":121,"line_start":121},{"file":"SKILL.md","line_end":134,"line_start":123},{"file":"SKILL.md","line_end":136,"line_start":134}]},{"factor":"network","evidence":[{"file":"SKILL.md","line_end":18,"line_start":18},{"file":"SKILL.md","line_end":60,"line_start":60},{"file":"SKILL.md","line_end":69,"line_start":69},{"file":"SKILL.md","line_end":72,"line_start":72},{"file":"SKILL.md","line_end":106,"line_start":106},{"file":"SKILL.md","line_end":109,"line_start":109}]},{"factor":"filesystem","evidence":[{"file":"SKILL.md","line_end":106,"line_start":106},{"file":"SKILL.md","line_end":127,"line_start":127}]}],"critical_findings":[],"high_findings":[],"medium_findings":[{"title":"Temp directory access","locations":[{"file":"SKILL.md","line_end":106,"line_start":106}],"confidence":0.96,"description":"curl -sm 30 'https://alerts.ncdr.nat.gov.tw/RssAtomFeed.ashx?AlertType=5' -o /tmp/typhoon.xml","review_kind":"capability","source_category":"filesystem","source_severity":"medium","confidence_reasoning":"curl writes to the predictable shared path /tmp/typhoon.xml without exclusive creation. A local attacker can pre-create a symlink to overwrite another writable file."},{"title":"Temp directory access","locations":[{"file":"SKILL.md","line_end":127,"line_start":127}],"confidence":0.94,"description":"h = open('/tmp/typhoon.xml', encoding='utf-8').read()","review_kind":"capability","source_category":"filesystem","source_severity":"medium","confidence_reasoning":"The parser trusts the same predictable shared path without binding the read to a verified download. Local substitution can feed forged alert text into reporting."}],"low_findings":[],"dangerous_patterns":[],"files_scanned":1,"total_lines":151,"audit_model":"codex","audited_at":"2026-10-13T04:26:15.188+00:00","created_at":"2026-10-13T18:37:59.500932+00:00","static_findings":[{"id":"external_commands:SKILL.md:14:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"用 Open-Meteo 的免費 API 查台灣各地天氣。免 API 金鑰、免登入,`curl` 即可。","category":"external_commands","line_end":14,"severity":"medium","line_start":14},{"id":"external_commands:SKILL.md:16:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"**定位:免金鑰的立即備援。** 有 CWA 授權碼時,正式預報請優先用 `cwa-weather` 技能(官方資料);本技能適合手邊沒有金鑰、只要快速概況時使用。","category":"external_commands","line_end":16,"severity":"medium","line_start":16},{"id":"external_commands:SKILL.md:57:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"表裡沒有的地點,用免金鑰的地理編碼 API 查,**`name` 請用英文或拼音**(例:`Hengchun`、`Lugang`):","category":"external_commands","line_end":57,"severity":"medium","line_start":57},{"id":"external_commands:SKILL.md:59:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```bash","category":"external_commands","line_end":61,"severity":"medium","line_start":59},{"id":"external_commands:SKILL.md:61:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":63,"severity":"medium","line_start":61},{"id":"external_commands:SKILL.md:63:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"2026-09-09 實測:中文地名(「台北市」「嘉義」「墾丁」等)在此 API 一律查無結果;英文地名也要注意同名地點(`Nantou` 會先命中中國廣東,`Kenting` 不在庫),務必確認回傳","category":"external_commands","line_end":63,"severity":"medium","line_start":63},{"id":"external_commands:SKILL.md:67:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```bash","category":"external_commands","line_end":73,"severity":"medium","line_start":67},{"id":"external_commands:SKILL.md:73:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":75,"severity":"medium","line_start":73},{"id":"external_commands:SKILL.md:75:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"2026-09-09 實測:HTTP 200,`current` 回傳溫度、濕度、降水量、天氣代碼,時間為 Asia/Taipei 當地時間。回報時附上回傳的 `time` 欄位。","category":"external_commands","line_end":75,"severity":"medium","line_start":75},{"id":"external_commands:SKILL.md:95:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- **連線逾時 / 5xx**:`curl` 一律加 `-m 30`,重試 1~2 次;仍失敗就告知 Open-Meteo 暫時異常,正式預報請看中央氣象署。不要編造天氣。","category":"external_commands","line_end":95,"severity":"medium","line_start":95},{"id":"external_commands:SKILL.md:96:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- **回傳不是 JSON 或缺 `current`/`daily`**:視為失敗,不要用舊資料冒充。","category":"external_commands","line_end":96,"severity":"medium","line_start":96},{"id":"external_commands:SKILL.md:97:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"- **座標不在台灣**:確認 `country_code=TW` 的地理編碼結果,回傳的 `name` 與使用者問的地點不符時,先回報找到的地名再給天氣。中文地名在地理編碼 API 查不到是已知限制","category":"external_commands","line_end":97,"severity":"medium","line_start":97},{"id":"external_commands:SKILL.md:105:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```bash","category":"external_commands","line_end":107,"severity":"medium","line_start":105},{"id":"external_commands:SKILL.md:107:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":109,"severity":"medium","line_start":107},{"id":"external_commands:SKILL.md:109:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"URL 形式為 `https://alerts.ncdr.nat.gov.tw/RssAtomFeed.ashx?AlertType=<類型代碼>`。類型代碼(2026-09-09 逐一實測):","category":"external_commands","line_end":121,"severity":"medium","line_start":109},{"id":"external_commands:SKILL.md:121:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"1~4 回「存取檔案有誤」(不存在或未開放)。feed 是 Atom + CAP 格式:每則 entry 有 `<title>`(類型)、`<updated>`、`<summary>`(警報全文)、`","category":"external_commands","line_end":121,"severity":"medium","line_start":121},{"id":"external_commands:SKILL.md:123:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```bash","category":"external_commands","line_end":134,"severity":"medium","line_start":123},{"id":"external_commands:SKILL.md:134:ruby-shell-backtick-execution","file":"SKILL.md","pattern":"Ruby/shell backtick execution","snippet":"```","category":"external_commands","line_end":136,"severity":"medium","line_start":134},{"id":"network:SKILL.md:18:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"**資料來源是 Open-Meteo 的國際氣象模式,不是中央氣象署(CWA)。** 颱風動態、豪雨特報、各種警報與正式預報,請一律以中央氣象署 https://www.cwa.gov.tw 為準。","category":"network","line_end":18,"severity":"low","line_start":18},{"id":"network:SKILL.md:60:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"curl -sm 30 'https://geocoding-api.open-meteo.com/v1/search?name=<英文地名>&count=5&country_code=TW'","category":"network","line_end":60,"severity":"low","line_start":60},{"id":"network:SKILL.md:69:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"curl -sm 30 'https://api.open-meteo.com/v1/forecast?latitude=25.053&longitude=121.526&current=temper","category":"network","line_end":69,"severity":"low","line_start":69},{"id":"network:SKILL.md:72:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"curl -sm 30 'https://api.open-meteo.com/v1/forecast?latitude=25.053&longitude=121.526&daily=weather_","category":"network","line_end":72,"severity":"low","line_start":72},{"id":"network:SKILL.md:106:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"curl -sm 30 'https://alerts.ncdr.nat.gov.tw/RssAtomFeed.ashx?AlertType=5' -o /tmp/typhoon.xml","category":"network","line_end":106,"severity":"low","line_start":106},{"id":"network:SKILL.md:109:hardcoded-url","file":"SKILL.md","pattern":"Hardcoded URL","snippet":"URL 形式為 `https://alerts.ncdr.nat.gov.tw/RssAtomFeed.ashx?AlertType=<類型代碼>`。類型代碼(2026-09-09 逐一實測):","category":"network","line_end":109,"severity":"low","line_start":109},{"id":"filesystem:SKILL.md:106:temp-directory-access","file":"SKILL.md","pattern":"Temp directory access","snippet":"curl -sm 30 'https://alerts.ncdr.nat.gov.tw/RssAtomFeed.ashx?AlertType=5' -o /tmp/typhoon.xml","category":"filesystem","line_end":106,"severity":"medium","line_start":106},{"id":"filesystem:SKILL.md:127:temp-directory-access","file":"SKILL.md","pattern":"Temp directory access","snippet":"h = open('/tmp/typhoon.xml', encoding='utf-8').read()","category":"filesystem","line_end":127,"severity":"medium","line_start":127},{"id":"obfuscation:SKILL.md:1:heuristic-high-file-entropy-6-74-bits-possible-b","file":"SKILL.md","pattern":"[HEURISTIC] High file entropy (6.74 bits) - possible binary/encrypted content","snippet":"File: SKILL.md","category":"obfuscation","line_end":1,"severity":"high","line_start":1}],"finding_verdicts":[{"id":"external_commands:SKILL.md:14:ruby-shell-backtick-execution","reason":"The backticks format the command name curl in Markdown prose. There is no shell command substitution or Ruby execution.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:16:ruby-shell-backtick-execution","reason":"The backticks mark the related skill name cwa-weather as inline code. This is a documentation reference, not executable syntax.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:57:ruby-shell-backtick-execution","reason":"The backticks format the name parameter and example place names. These are explanatory labels, not shell substitutions.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:59:ruby-shell-backtick-execution","reason":"The triple backticks open a Markdown Bash example for a quoted public geocoding request. No backtick execution appears in that example.","verdict":"false_positive","confidence":0.98},{"id":"external_commands:SKILL.md:61:ruby-shell-backtick-execution","reason":"The triple backticks close the geocoding example. The following place names are inline Markdown, not executable shell expressions.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:63:ruby-shell-backtick-execution","reason":"The inline backticks identify geocoding names and response fields. The prose asks users to validate Taiwan coordinates and contains no execution.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:67:ruby-shell-backtick-execution","reason":"This is a Markdown fence around two quoted HTTPS weather requests with fixed example coordinates. No shell substitution or downloaded-code execution occurs.","verdict":"false_positive","confidence":0.98},{"id":"external_commands:SKILL.md:73:ruby-shell-backtick-execution","reason":"The triple backticks close the forecast examples. Subsequent inline backticks describe response fields rather than commands.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:75:ruby-shell-backtick-execution","reason":"The backticks format current and time response-field names. This line documents reporting behavior, not code execution.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:95:ruby-shell-backtick-execution","reason":"The inline backticks name curl and its timeout option. The instruction bounds retries and forbids fabricated weather; it does not execute backtick expressions.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:96:ruby-shell-backtick-execution","reason":"The backticks identify expected current and daily fields. The line instructs rejection of invalid responses and contains no executable expression.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:97:ruby-shell-backtick-execution","reason":"The backticks format geocoding filters and field names. The surrounding instructions require location validation, not shell execution.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:105:ruby-shell-backtick-execution","reason":"The triple backticks open an ordinary curl example, not command substitution. Its unsafe temporary-file destination is addressed by the separate filesystem verdict.","verdict":"false_positive","confidence":0.98},{"id":"external_commands:SKILL.md:107:ruby-shell-backtick-execution","reason":"This is the closing Markdown fence for the alert download example. The following inline URL is documentation, not backtick execution.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:109:ruby-shell-backtick-execution","reason":"The backticks format the public feed URL and XML field names. The surrounding type table contains no shell substitutions.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:121:ruby-shell-backtick-execution","reason":"The inline backticks mark Atom and CAP element names. The prose explicitly requires expiration checks and does not execute these strings.","verdict":"false_positive","confidence":0.99},{"id":"external_commands:SKILL.md:123:ruby-shell-backtick-execution","reason":"This Markdown fence encloses a quoted Python heredoc that extracts and prints XML text without evaluating it. The shared-file risk is adjudicated separately.","verdict":"false_positive","confidence":0.98},{"id":"external_commands:SKILL.md:134:ruby-shell-backtick-execution","reason":"The triple backticks close the parser example. The following rate-limit prose contains no backtick execution.","verdict":"false_positive","confidence":0.99},{"id":"network:SKILL.md:18:hardcoded-url","reason":"The URL directs users to the Taiwan Central Weather Administration for authoritative announcements. No data upload or secret transmission is requested.","verdict":"false_positive","confidence":0.98},{"id":"network:SKILL.md:60:hardcoded-url","reason":"The HTTPS request sends a requested place name to Open-Meteo for geocoding, matching the declared purpose. No credentials or local files are transmitted.","verdict":"false_positive","confidence":0.97},{"id":"network:SKILL.md:69:hardcoded-url","reason":"The HTTPS request retrieves current weather using fixed Taipei coordinates and weather-field selectors. This is necessary functionality with no credential or file upload.","verdict":"false_positive","confidence":0.98},{"id":"network:SKILL.md:72:hardcoded-url","reason":"The HTTPS request retrieves three forecast days from Open-Meteo using fixed example coordinates. The query contains weather parameters, not secrets or unrelated data.","verdict":"false_positive","confidence":0.98},{"id":"network:SKILL.md:106:hardcoded-url","reason":"The HTTPS GET retrieves a public NCDR typhoon feed without uploading local data. The destination-file hazard is separate from the legitimate network request.","verdict":"false_positive","confidence":0.98},{"id":"network:SKILL.md:109:hardcoded-url","reason":"This is the documented NCDR feed endpoint with an alert-type placeholder. It supports the advertised alert lookup and contains no exfiltration instruction.","verdict":"false_positive","confidence":0.98},{"id":"filesystem:SKILL.md:106:temp-directory-access","reason":"curl writes to the predictable shared path /tmp/typhoon.xml without exclusive creation. A local attacker can pre-create a symlink to overwrite another writable file.","verdict":"confirmed","severity":"medium","confidence":0.96},{"id":"filesystem:SKILL.md:127:temp-directory-access","reason":"The parser trusts the same predictable shared path without binding the read to a verified download. Local substitution can feed forged alert text into reporting.","verdict":"confirmed","severity":"medium","confidence":0.94},{"id":"obfuscation:SKILL.md:1:heuristic-high-file-entropy-6-74-bits-possible-b","reason":"The entire file is readable Chinese and English Markdown with coordinate tables and short examples. No evidence found of binary, encrypted, or obfuscated payloads.","verdict":"false_positive","confidence":0.99}],"semantic_findings":[],"subject_marketplace_commit_sha":"2aab20a3878daa05021884e089a7dd7739e08581","subject_content_hash":"52ec4b080ca3d5c0f1ff6caeff84857294ef1bc87a7e76211c5e0a3a9f8d47a8","subject_tree_hash":"f2d143b35673eaeb7ce33e54d4e66bbfc41d1c2cfb7b2e36921050f560a082d5","subject_plugin_path":"skills/tahodev/taiwan-weather","audit_payload_hash":"693deca285d79a26955a4cf5d171bc72","confirmed_risk_level":"safe","scanner_version":"3.0.0","policy_version":"skillstore-security-audit-policy-v1","subject":{"marketplaceCommitSha":"2aab20a3878daa05021884e089a7dd7739e08581","contentHash":"52ec4b080ca3d5c0f1ff6caeff84857294ef1bc87a7e76211c5e0a3a9f8d47a8","treeHash":"f2d143b35673eaeb7ce33e54d4e66bbfc41d1c2cfb7b2e36921050f560a082d5","pluginPath":"skills/tahodev/taiwan-weather","auditPayloadHash":"693deca285d79a26955a4cf5d171bc72"},"scannerVersion":"3.0.0","policyVersion":"skillstore-security-audit-policy-v1"},"auditTranslation":null,"localization":{"requestedLocale":"en","contentLocale":"en","availableLocales":["en"],"fallbackToEnglish":false},"attestation":{"availability":"issued","url":"/api/skills/tahodev-taiwan-weather/audits/1/attestation","status":"active"},"trust":{"publicState":"public","auditState":"complete","auditCurrentness":null,"confirmedRiskLevel":"safe","confirmedFindingCount":0,"capabilityReviewCount":2,"needsReviewCount":0,"falsePositiveCount":0,"agentAutoInstallPolicy":"allowed","manualInstallPolicy":"allowed","artifactSignatureState":"available","attestationState":"active","verificationState":"not_verified"},"isLatest":true}}