T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/todoist_api.py:207
- Finding
- Bearer Token Can Be Transmitted to an Arbitrary or Plaintext Destination## Vulnerability Details **File Location**: `scripts/todoist_api.py:139-143, 207-217, 2300-2301`; `scripts/smoke_test.py:37-52` **Vulnerability Type**: Unrestricted credential destination and insecure transport configuration **Risk Level**: High ### Vulnerable Code `scripts/todoist_api.py:139-143`: ```python def with_base(base_url: str, path: str) -> str: base = base_url.rstrip("/") if not path.startswith("/"): path = "/" + path return f"{base}{path}" ``` `scripts/todoist_api.py:207-217`: ```python url = with_base(base_url, path) if query: encoded_query = urllib.parse.urlencode( {k: v for k, v in query.items() if v is not None}, doseq=True, ) if encoded_query: url = f"{url}?{encoded_query}" headers = { "Authorization": f"Bearer {token}", ``` `scripts/todoist_api.py:2300-2301`: ```python parser.add_argument("--token", help="Todoist API token. Defaults to TODOIST_API_TOKEN.") parser.add_argument("--base-url", default=DEFAULT_BASE_URL, help=f"API base URL (default: {DEFAULT_BASE_URL})") ``` `scripts/smoke_test.py:37-52`: ```python parser.add_argument("--token", help="Todoist API token. Defaults to TODOIST_API_TOKEN.") parser.add_argument("--base-url", default=DEFAULT_BASE_URL, help=f"API base URL (default: {DEFAULT_BASE_URL})") parser.add_argument("--timeout", type=int, default=20, help="HTTP timeout in seconds (default: 20).") args = parser.parse_args(argv) token = args.token or os.getenv("TODOIST_API_TOKEN") or os.getenv("TODOIST_TOKEN") if not token: emit({"ok": False, "error": "Missing Todoist token. Pass --token or set TODOIST_API_TOKEN."}) return 2 url = args.base_url.rstrip("/") + "/projects?" + urllib.parse.urlencode({"limit": 1}) request = urllib.request.Request( url=url, method="GET", ...[truncated 2611 chars]
- Remediation
- ## Remediation Suggestions 1. Remove `--base-url` from production-facing commands unless custom endpoints are an essential requirement. 2. Centralize endpoint validation and apply it to both scripts before retrieving or attaching the token. 3. Require the `https` scheme and reject embedded credentials, fragments, unexpected ports, and malformed URLs. 4. Allowlist the exact official API origin, such as `https://api.todoist.com`, including the expected API path prefix. 5. If development endpoints are required, place them behind an explicit unsafe-development option and require a separate non-production credential. 6. Disable redirects for authenticated requests or validate every redirect target and strip authorization whenever the scheme, hostname, or port changes. 7. Add tests proving that HTTP URLs, lookalike domains, subdomain tricks, user-info URLs, and cross-origin redirects are rejected. 8. Document that agent-generated or user-supplied URLs must never determine the destination of a request carrying a Todoist credential.
