T09 · Insecure Skill Coding Practices
- Location
scripts/flight_query.py:119- Finding
API Credential Exposure Through Command-Line Arguments, Plaintext Files, and URL Query Parameters
- Content
View full analysis
Vulnerability Details
File Location:
scripts/flight_query.py:90-105, 119-126, 245-247, 329-337;SKILL.md:29-40
Vulnerability Type: Insecure handling and transmission of sensitive API credentials
Risk Level: MediumVulnerable Code
The script loads the API key from an unprotected plaintext
.envfile:python def load_api_key(cli_key: str = None) -> str: """按优先级加载 API Key""" if cli_key: return cli_key env_key = os.environ.get("JUHE_FLIGHT_KEY", "").strip() if env_key: return env_key env_file = Path(__file__).parent / ".env" if env_file.exists(): for line in env_file.read_text(encoding="utf-8").splitlines(): line = line.strip() if line.startswith("JUHE_FLIGHT_KEY="): val = line.split("=", 1)[1].strip().strip('"').strip("'") if val: return val return ""It then places the credential directly in the request URL:
python params = { "key": api_key, "departure": departure, "arrival": arrival, "departureDate": departure_date, } url = f"{API_URL}?{urllib.parse.urlencode(params)}" try: with urllib.request.urlopen(url, timeout=15) as resp: result = json.loads(resp.read().decode("utf-8"))The command-line parser supports passing the credential as a process argument:
python if args[i] == "--key" and i + 1 < len(args): cli_key = args[i + 1] i += 2The missing-key error also recommends both plaintext-file and command-line storage:
python if not api_key: print("❌ 未找到 API Key,请通过以下方式之一配置:") print(" 1. 环境变量:export JUHE_FLIGHT_KEY=your_api_key") print(" 2. .env 文件:在脚本目录创建 .env,写入 JUHE_FLIGHT_KEY=your_api_key") print(" 3. 命令行参数:python flight_query.py --key your_api_key --departure BJS --arrival SHA --date 2025-06-18") print(f"\n免费申请 Key: ...[truncated 3864 chars]- Remediation
View remediation
Remediation Suggestions
- Remove or deprecate the
--keycommand-line option. PreferJUHE_FLIGHT_KEYsupplied through the environment or a platform-managed secret facility. - If interactive entry is needed, use
getpass.getpass()so the key is neither echoed nor included in process arguments. - If
.envsupport remains necessary:- Require the file to be owned by the current user.
- Reject or warn about permissions broader than
0600. - Add
scripts/.envand equivalent secret files to.gitignore. - Update the documentation to create it securely, such as with
umask 077. - Clearly warn users never to commit, archive, or share the file.
- If the Juhe API supports header-based authentication, send the key in an authorization header instead of the query string.
- If the upstream API requires the key in the query string, document that unavoidable risk and ensure application, proxy, telemetry, and exception logs redact the
keyparameter. - Avoid printing or propagating complete request URLs in future diagnostics. Introduce a URL-redaction helper before logging network errors.
- Rotate any API key that may previously have been passed through command-line arguments, stored with permissive file permissions, committed to source control, or captured in logs.
- Remove or deprecate the
