T09 · Insecure Skill Coding Practices
- Location
scripts/corpus_api.py:30- Finding
Bearer token can be transmitted to an arbitrary or plaintext endpoint
- Content
View full analysis
None: self.base_url = base_url.rstrip("/") self.token = token self.timeout = timeout def request(self, method: str, candidate: RequestCandidate) -> Any: url = f"{self.base_url}{candidate.path}" if candidate.query: pairs = [] for key, value in candidate.query.items(): if value is None: continue pairs.append((key, str(value))) if pairs: url = f"{url}?{urllib.parse.urlencode(pairs)}" data = None headers = { "Authorization": f"Bearer {self.token}", "Accept": "application/json", } ``` ```python parser.add_argument( "--base-url", default=os.getenv("CORPUS_API_BASE_URL", DEFAULT_BASE_URL), help=f"Corpus API base URL (default: {DEFAULT_BASE_URL})", ) ``` ```python client = CorpusClient(base_url=args.base_url, token=args.token, timeout=args.timeout) ``` The corresponding configuration documentation explicitly permits an environment-controlled destination: ```markdown - `CORPUS_API_BASE_URL`: API base URL (default: `https://corpusai.app`). ``` ### Technical Analysis The client accepts `--base-url` or `CORPUS_API_BASE_URL` without validating the URL scheme, hostname, port, embedded credentials, query, or fragment. It then attaches the Corpus bearer token to every request sent to the resulting URL. Consequently, authenticated requests are not limited to the declared Corpus service. A malicious configuration can direct them to an attacker-controlled HTTP or HTTPS server. An `http://` destination would additionally expose the bearer token ...[truncated 1781 chars]- Remediation
View remediation
