T09 · Insecure Skill Coding Practices
- Location
scripts/create_task.py:13- Finding
API Key Exfiltration Through an Unvalidated Network Destination
- Content
View full analysis
dict: """创建酱板鸭视频生成任务""" url = f"https://{host}/task/openapi/create" headers = { "Host": host, "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } data = { "apiKey": api_key, "workflowId": "2037239092089458690", "nodeInfoList": [ { "nodeId": "385", "fieldName": "value", "fieldValue": language } ] } req = urllib.request.Request( url, data=json.dumps(data).encode("utf-8"), headers=headers, method="POST" ) with urllib.request.urlopen(req, timeout=30) as response: return json.loads(response.read().decode("utf-8")) ``` `scripts/config_host.py:57-73, 88-90`: ```python def set_host(host): """设置sauce-duck-videos.env.RH_HOST""" config = load_config() or {} if "skills" not in config: config["skills"] = {} if "entries" not in config["skills"]: config["skills"]["entries"] = {} skill_config = config["skills"]["entries"].get("sauce-duck-videos", {}) skill_config["enabled"] = True if "env" not in skill_config: skill_config["env"] = {} skill_config["env"]["RH_HOST"] = host config["skills"]["entries"]["sauce-duck-videos"] = skill_config save_config(config) ``` ```python elif sys.argv[1] == "--set" and len(sys.argv) >= 3: host = sys.argv[2] set_host(host) ``` `scripts/query_task.py:13-33`: ```python def query_task(host: str, api_key: str, task_id: str) -> dict: """ ...[truncated 3575 chars]- Remediation
View remediation
str: normalized = host.strip().lower().rstrip(".") if normalized not in ALLOWED_HOSTS: raise ValueError("Unsupported RunningHub host") return normalized ``` 2. Do not use suffix-based checks such as `host.endswith("runninghub.ai")`, because values such as `evilrunninghub.ai` can bypass them. 3. Reject values containing URL schemes, user information, paths, query strings, fragments, or unauthorized ports. Prefer selecting a predefined base URL from an internal mapping rather than constructing it from free-form input: ```python BASE_URLS = { "cn": "https://www.runninghub.cn", "global": "https://www.runninghub.ai", } ``` 4. Validate the destination again immediately before every credential-bearing request. This prevents direct invocation of the request scripts from bypassing configuration-time checks. 5. Verify whether RunningHub requires `apiKey` in the request body. If bearer authentication is sufficient, remove the duplicate body field to minimize credential exposure. 6. Add tests that reject attacker-controlled hosts, subdomain tricks, trailing-dot variants, embedded credentials, custom ports, and path-bearing input. ]]>
