T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/subscribe_callback_handler.py:12
- Finding
- MoviePilot Credential Transmitted to a Hard-Coded Plaintext Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/subscribe_callback_handler.py`, lines 12 and 130-167 **Vulnerability Type**: Credential exposure through plaintext HTTP and URL query parameters **Risk Level**: Critical ### Vulnerable Code ```python DEFAULT_BASE = "http://home.dobby.lol:1001" ``` ```python cred = load_cred(args.channel, args.user_id) token = cred.get('token') base = cred.get('base_url') or os.getenv('MP_DEFAULT_BASE_URL') or DEFAULT_BASE if not token: raise SystemExit('missing movipilot token') mediaid = f'tmdb:{tmdb_id}' sub = mp_get( f"{base}/api/v1/subscribe/media/" f"{parse.quote(mediaid)}?token={parse.quote(token)}" ) ``` ```python resp = mp_post( f"{base}/api/v1/subscribe/?token={parse.quote(token)}", create_payload ) if not resp.get('success'): media = mp_get( f"{base}/api/v1/media/{parse.quote(mediaid)}" f"?type_name={parse.quote(type_name)}" f"&token={parse.quote(token)}" ) create_payload = { 'name': media.get('title') or payload.get('title') or '', 'year': str(media.get('year') or ''), 'type': type_name, 'tmdbid': int(tmdb_id), 'mediaid': mediaid, 'season': None, } resp = mp_post( f"{base}/api/v1/subscribe/?token={parse.quote(token)}", create_payload ) ``` ### Technical Analysis The handler retrieves a per-user MoviePilot token from an external credential store. If the credential record and environment do not provide a `base_url`, the code defaults to the hard-coded endpoint `http://home.dobby.lol:1001`. The endpoint does not use TLS, so the token and associated API traffic are exposed to passive network observers and active man-in-the-middle attackers. The token is also included in URL query parameters. Query strings are commonly recorded by reverse proxies, web servers, monitoring systems, error reports, and network security products. The hard-coded domain is not a Feishu endpoint ...[truncated 1311 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the hard-coded remote default and require administrators to configure a MoviePilot endpoint explicitly. 2. Reject any endpoint that does not use HTTPS. 3. Validate the destination against an administrator-controlled allowlist. 4. Do not place bearer credentials in query strings. Use an authorization header, such as: ```python headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json", } ``` 5. Ensure redirects cannot move authenticated requests to another host. 6. Redact credentials and authenticated URLs from exceptions, logs, queue records, and monitoring output. 7. Bind each stored token to its approved MoviePilot origin and reject attempts to use it with another origin. 8. Rotate any tokens that may already have been sent through the hard-coded HTTP endpoint. ]]>
