T09 · Insecure Skill Coding Practices
- Location
scripts/image_flip.py:23- Finding
Credential-bearing API requests can be redirected to an arbitrary host
- Content
View full analysis
Vulnerability Details
File Location:
scripts/image_flip.py, lines 23-24, 36-57, and 67-81
Vulnerability Type: Unrestricted network destination for sensitive authentication data
Risk Level: HighVulnerable Code
python # API base address, configurable through an environment variable JF_ENDPOINT = os.getenv("JF_ENDPOINT", "api-cn.jftechws.com") JF_BASE_URL = f"https://{JF_ENDPOINT}/gwp/v3" def get_headers(uuid: str, app_key: str, app_secret: str, move_card: int) -> Dict[str, str]: """Generate request headers containing the signature and timestamp.""" time_millis = get_time_millis() signature = generate_signature(uuid, app_key, app_secret, time_millis, move_card) return { "Content-Type": "application/json; charset=UTF-8", "uuid": uuid, "appKey": app_key, "timeMillis": time_millis, "signature": signature, "X-Request-Id": os.urandom(16).hex() } def get_camera_param(device_token: str, uuid: str, app_key: str, app_secret: str, move_card: int, channel: int = 0) -> Dict[str, Any]: url = f"{JF_BASE_URL}/rtc/device/getconfig/{device_token}" headers = get_headers(uuid, app_key, app_secret, move_card) body = {"Name": "Camera.Param"} if channel is not None: body["Channel"] = str(channel) response = requests.post(url, headers=headers, json=body, timeout=30)Technical Analysis
JF_ENDPOINTis read directly from the process environment and interpolated into the destination URL without validation or an allowlist. Every request to this endpoint includes:- The device access token in the URL path
- The platform UUID
- The application key
- A timestamp
- A signature derived from the application secret
- Camera configuration request data
The application secret is not transmitted directly. Nevertheless, the device token is a bea ...[truncated 2081 chars]
- Remediation
View remediation
Remediation Suggestions
-
Replace unrestricted endpoint selection with an exact allowlist:
python ALLOWED_ENDPOINTS = { "api-cn.jftechws.com", "api-as.jftechws.com", "api-eu.jftechws.com", "api-na.jftechws.com", } JF_ENDPOINT = os.getenv("JF_ENDPOINT", "api-cn.jftechws.com").strip().lower() if JF_ENDPOINT not in ALLOWED_ENDPOINTS: raise ValueError("Unsupported JFTech API endpoint") -
Reject endpoints containing schemes, paths, ports, user-information components, IP literals, or trailing-dot hostname variants.
-
Where supported by the API, move the device token from the URL path into an authorization header.
-
Ensure logs redact device tokens, signatures, UUIDs, application keys, and request URLs containing credentials.
-
Use short-lived, device-specific, least-privileged tokens and revoke a token immediately after suspected disclosure.
-
Document the exact permitted regional destinations so deployment-level egress controls can enforce the same allowlist.
-
