T09 · Insecure Skill Coding Practices
- Location
contract_reviewer.py:130- Finding
Unvalidated API Base URL Exposes Credentials and Confidential Contract Data
- Content
View full analysis
Vulnerability Details
File Location:
contract_reviewer.py:130-135, 150-157, 179-180, 212-217
Vulnerability Type: Arbitrary external endpoint and sensitive-data disclosure
Risk Level: HighVulnerable Code
python parser.add_argument( "--base-url", type=str, default="", help="SoMark API base URL(覆盖 SOMARK_BASE_URL 环境变量)," "例如 https://somark.cn/api/v1(中国大陆)或 https://somark.ai/api/v1(海外)", )python data.add_field("api_key", api_key) data.add_field("file", file_path.read_bytes(), filename=file_path.name) for fmt in output_formats: data.add_field("output_formats", fmt) data.add_field("element_formats", json.dumps(element_formats, ensure_ascii=False)) data.add_field("feature_config", json.dumps(feature_config, ensure_ascii=False)) async with session.post(async_url, data=data) as resp:python async with session.post( check_url, data={"api_key": api_key, "task_id": task_id} ) as resp:python base_url = ( args.base_url or os.environ.get("SOMARK_BASE_URL", "https://somark.cn/api/v1") ).rstrip("/") if not base_url: print("错误:SoMark API base URL 不能为空") raise SystemExit(1) async_url = f"{base_url}/parse/async" check_url = f"{base_url}/parse/async_check"Technical Analysis
The API destination is accepted from either the
--base-urlcommand-line argument or theSOMARK_BASE_URLenvironment variable without validating its scheme, hostname, port, user information, or relationship to an official SoMark endpoint.The resulting URL is used for two outbound requests. The initial parsing request includes the complete contract file and
SOMARK_API_KEYin multipart form data. Polling requests repeatedly transmit the same API key together with the task identifier.Consequently, any party capable of influencing the command invocation or process environment can redirect these secrets to an attacker-controlled service. The implementation does not enforce HTTPS, so it also permits a ...[truncated 1688 chars]
- Remediation
View remediation
Remediation Suggestions
-
Allowlist the exact official endpoint origins and expected path prefixes:
python ALLOWED_BASE_URLS = { "https://somark.cn/api/v1", "https://somark.ai/api/v1", } base_url = ( args.base_url or os.environ.get("SOMARK_BASE_URL", "https://somark.cn/api/v1") ).rstrip("/") if base_url not in ALLOWED_BASE_URLS: raise SystemExit("The API base URL must be an approved SoMark endpoint.") -
Parse the URL with
urllib.parse.urlsplitand independently enforce:httpsas the only permitted scheme;- an exact approved hostname;
- no embedded username or password;
- no unexpected port;
- the expected
/api/v1path; - no query string or fragment.
-
If custom endpoints are operationally required, disable them by default and require an explicit high-friction opt-in that clearly states that both the API credential and complete document will be transmitted to the selected host. Do not permit arbitrary custom endpoints in unattended skill execution.
-
Prefer an authorization header rather than placing the API key in multipart form data, provided the upstream API supports it. This reduces accidental credential exposure in body logging, although destination validation remains mandatory.
-
Configure strict connection and total timeouts and ensure TLS certificate verification remains enabled.
-
Avoid including credentials, document contents, or complete server error bodies in logs and exception messages.
-
Add automated tests proving that HTTP URLs, lookalike domains, URLs with user information, unexpected ports, and attacker-controlled hosts are rejected before any network request or file read occurs.
-
