T09 · Insecure Skill Coding Practices
- Location
scripts/bing_news.py:600- Finding
API Token Accepted Through Observable Input Channels and Unnecessarily Copied into the Process Environment
- Content
View full analysis
str: token = args.token or os.getenv("DATAIFY_API_TOKEN") or extract_token(args.prompt) if not token: raise MissingTokenError( "缺少 DATAIFY_API_TOKEN。请提供 Dataify API token,或访问 https://dashboard.dataify.com/login?utm_source=skill 注册获取;新账号注册即得 50 免费积分。" ) token = token.strip() if not token.lower().startswith("bearer "): token = f"Bearer {token}" os.environ["DATAIFY_API_TOKEN"] = token return token ``` The command-line credential option is registered separately: ```python parser.add_argument("--token", help="API token for this run. Bearer prefix is added when missing.") ``` The prompt credential extractor used by `resolve_token()` is defined at lines 484–489: ```python def extract_token(prompt: str) -> str | None: match = re.search( r"(?:DATAIFY_API_TOKEN|api[_ -]?token|token|令牌|密钥)\s*(?:=|:|:|是|为)\s*((?:Bearer\s+)?[A-Za-z0-9._~+/=-]+)", prompt, re.IGNORECASE, ) return match.group(1).strip() if match else None ``` ### Technical Analysis The Skill's primary instructions specify that authentication should be read from the `DATAIFY_API_TOKEN` environment variable and explicitly state that users should never paste tokens into chat. The implementation nevertheless accepts the token through two additional channels: 1. The natural-language value supplied through `--prompt`. 2. The `--token` command-line argument. These channels provide no functional capability beyond reading the existing environment variable and expose credentials to additional systems. A token embedded in a natural-language request may be retained in conversation histories, agent tr ...[truncated 2294 chars]- Remediation
View remediation
str: token = os.getenv("DATAIFY_API_TOKEN") if not token: raise MissingTokenError( "DATAIFY_API_TOKEN is not configured. Set it in the current session without sharing it in chat." ) token = token.strip() if not token.lower().startswith("bearer "): token = f"Bearer {token}" return token ``` 4. Remove `os.environ["DATAIFY_API_TOKEN"] = token`. Pass the normalized token directly to `call_api()` and avoid making it available to possible child processes. 5. Ensure errors and diagnostics never print the token, authorization header, entire process environment, or unredacted command line. 6. Add tests confirming that: - A token embedded in `--prompt` is ignored. - `--token` is rejected as an unsupported argument. - Authentication succeeds only when `DATAIFY_API_TOKEN` is present. - Preview and dry-run modes never access or display credentials. 7. Rotate any token previously supplied through chat or command-line arguments because it may already exist in retained logs. ]]>
