T09 · Insecure Skill Coding Practices
- Location
lib/api.js:68- Finding
Bearer Token and Uploaded File Content May Be Transmitted Over Plaintext HTTP
- Content
View full analysis
Vulnerability Details
File Location:
lib/api.js:68-77,lib/api.js:502-510,lib/config.js:21-25,README.md:54-61,config/wikijs.example.json:1-4
Vulnerability Type: Plaintext transmission of sensitive information
Risk Level: HighVulnerable Code
lib/api.js:68-77:js const config = loadConfig(); client = axios.create({ baseURL: config.url, headers: { 'Authorization': `Bearer ${config.apiToken}`, 'Content-Type': 'application/json' }, timeout: 30000 });lib/api.js:502-510:js const response = await axios.post( `${config.url}/u`, form, { headers: { ...form.getHeaders(), 'Authorization': `Bearer ${config.apiToken}` } } );lib/config.js:21-25:js if (!cachedConfig.url) { throw new Error('Missing "url" in config'); } if (!cachedConfig.apiToken) { throw new Error('Missing "apiToken" in config'); }README.md:54-61:json { "url": "http://your-wiki-server:3000", "apiToken": "YOUR_API_TOKEN_HERE", "defaultEditor": "markdown", "defaultLocale": "en" }config/wikijs.example.json:1-4:json { "url": "http://localhost:3000", "apiToken": "YOUR_API_TOKEN_HERE", "defaultEditor": "markdown" }Technical Analysis
The API client attaches the Wiki.js bearer token to every GraphQL request and asset-upload request. However, configuration validation only checks that
urlandapiTokenare present. It does not parse the URL or require TLS.The documentation also demonstrates a non-loopback HTTP URL. A user following this example may transmit the bearer token, GraphQL request data, page content, and uploaded file content without encryption. An attacker with a suitable network position could inspect or modify this traffic.
Sending an authentication token to the explicitly configured Wiki.js server is necessary for the declar ...[truncated 1499 chars]
- Remediation
View remediation
Remediation Suggestions
- Parse the configured URL using the standard
URLclass before creating the client. - Require
https:for all non-loopback destinations. - If local development requires HTTP, permit it only for strict loopback hostnames or addresses such as
localhost,127.0.0.1, and::1. - If a broader insecure-HTTP override is necessary, require an explicit option and display a prominent warning before transmitting credentials.
- Replace the non-loopback HTTP example in
README.mdwith an HTTPS URL. - Add tests confirming that non-loopback HTTP endpoints are rejected.
- Ensure authorization headers are never forwarded to a different origin during redirects.
- Recommend API tokens with only the permissions required by the intended commands.
- Document restrictive permissions for
~/.config/wikijs.json, such as mode0600, to reduce local token exposure.
Example validation:
js function validateServerUrl(value) { const parsed = new URL(value); const loopbackHosts = new Set(['localhost', '127.0.0.1', '::1']); if (parsed.protocol !== 'https:' && !loopbackHosts.has(parsed.hostname)) { throw new Error('Wiki.js URL must use HTTPS for non-loopback hosts'); } return parsed.toString().replace(/\/$/, ''); }- Parse the configured URL using the standard
