T09 · Insecure Skill Coding Practices
- Location
aippt-cli.js:191- Finding
Bearer Token Disclosure Through an Unrestricted API Base URL
- Content
View full analysis
Vulnerability Details
File Location:
aippt-cli.js:191-194, 228, 237-240
Vulnerability Type: Credential disclosure caused by an untrusted network destination
Risk Level: HighVulnerable Code
js async function buildFetchOptions(args, method, operation, requestBody) { const token = args.token || process.env.AIPPT_TOKEN; const headers = { Accept: 'application/json' }; if (token) headers.Authorization = `Bearer ${token}`; const content = getRequestContent(operation); const contentTypes = Object.keys(content); const wantsMultipart = contentTypes.includes('multipart/form-data') || Boolean(args.file); if (wantsMultipart) { if (!args.file) fail('This endpoint requires --file for multipart/form-data'); const filePath = path.resolve(args.file); const fileBytes = fs.readFileSync(filePath); const form = new FormData(); form.append('file', new Blob([fileBytes]), path.basename(filePath)); appendMultipartFields(form, args.field); return { method: method.toUpperCase(), headers, body: form }; } headers['Content-Type'] = 'application/json'; return { method: method.toUpperCase(), headers, body: JSON.stringify(requestBody === undefined ? parseRequestBody(args) : requestBody), }; }js const baseUrl = (args['base-url'] || process.env.AIPPT_BASE_URL || apiDoc.servers?.[0]?.url || '').replace(/\/+$/, '');js const response = await fetch(`${baseUrl}${apiPath}`, { ...(await buildFetchOptions(args, method, operation, requestBody)), signal: controller.signal, });The expected service defined in
apidoc.json:3312-3315is:json "servers": [ { "url": "https://api.mindshow.vip", "description": "正式环境" } ]Technical Analysis
The CLI obtains the API destination from the
--base-urlargument, theAIPPT_BASE_URLenvironment variable, or a server URL in a potentially user-supplied API document. It does not validate the resulting scheme, hostname, port, or ...[truncated 2770 chars]- Remediation
View remediation
Remediation Suggestions
-
Allowlist trusted API origins
- Permit
https://api.mindshow.vipby default. - If alternate deployments are required, use an explicit administrator-managed allowlist rather than accepting arbitrary URLs.
- Permit
-
Bind credentials to an approved origin
- Add the
Authorizationheader only after parsing and validating the final URL. - Never send the production AIPPT token when the destination origin differs from the approved API origin.
- Require a separate explicitly supplied token for each approved alternate environment.
- Add the
-
Enforce secure URL properties
- Parse destinations with the
URLclass. - Require HTTPS.
- Reject embedded URL credentials, unexpected ports, malformed hosts, and non-HTTP protocols.
- Resolve hostnames and reject loopback, private, link-local, multicast, and unspecified address ranges where custom hosts are supported.
- Revalidate redirect destinations or disable redirects to prevent an approved endpoint from redirecting credentials to an untrusted origin.
- Parse destinations with the
-
Restrict custom API documents
- Do not trust
servers[0].urlfrom arbitrary--apidocfiles for authenticated requests. - Treat an alternate API document as schema input only, or require explicit approval of its server origin.
- Do not trust
-
Minimize sensitive transmission
- Before uploading a file or sending presentation content to a non-default approved environment, clearly identify the destination and request user confirmation.
- Document that selected files and presentation content leave the local system and are processed by the configured service.
-
Add regression tests
- Verify that credentials are sent to the official HTTPS origin.
- Verify that credentials are withheld from unapproved origins.
- Verify rejection of HTTP, loopback, private, link-local, redirect-based, and credential-bearing URLs.
-
