T09 · Insecure Skill Coding Practices
- Location
src/auth.js:21- Finding
OAuth Tokens Are Encrypted with a Public, Hard-Coded Fallback Key
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill matches its Baidu Netdisk file-management purpose, but it under-discloses credential and upload behavior and uses weak secret handling.
Review before installing. Only use this in an environment where local config files, shell history, terminal logs, and process listings are protected. Prefer OAuth with a strong ENCRYPTION_KEY set, avoid passing tokens or secrets on the command line, rotate any credentials previously configured this way, and confirm you are comfortable granting basic and netdisk read/write scope to this skill.
src/auth.js:21OAuth Tokens Are Encrypted with a Public, Hard-Coded Fallback Key
src/index.js:25Manual Configuration Exposes Secrets in Process Arguments and Stores Them in Plaintext
skill.json:9Security Metadata Incorrectly Denies Credential Collection and Outbound User Data
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
The README states that API keys, secret keys, access tokens, and refresh tokens are stored in a local config.json. Even with claims of encryption elsewhere, documenting local storage of all sensitive credentials without clear details on file permissions, encryption-key management, and rotation creates a substantial credential exposure risk on shared or compromised hosts.
默认存储在本地 `config.json`,包含:
- `apiKey` - 百度 API Key
- `secretKey` - 百度 Secret Key
- `accessToken` - Access Token(OAuth 授权后自动保存)
- `refreshToken` - Refresh Token(OAuth 授权后自动保存)
---
The file states that Baidu access tokens are stored locally and describes encryption using AES-256-CBC with crypto-js-style key derivation from a user password. This is security-sensitive because local token storage creates credential theft risk if the host or config file is exposed, and the described scheme lacks details about robust KDF parameters, authenticated encryption, secure key management, and token lifecycle protections. In the context of a file-management skill with read/write cloud-storage scope, compromise of the token could allow unauthorized access to user files.
用户的百度 Access Token 使用 AES-256 加密,存储在本地配置文件中。
// 加密存储,密钥由用户密码派生
The declared purpose understates the actual capability surface by omitting credential storage, account info lookup, manual token handling, and cache-related behavior. In agent ecosystems, such mismatches weaken informed consent and can cause operators to grant a skill broader trust than its description warrants.
The documented configuration includes storage and handling of apiKey, secretKey, accessToken, and refreshToken, which are highly sensitive credentials. In the context of an agent skill that also uses unpinned executable package commands, this broad credential handling materially increases the risk of account takeover or long-lived unauthorized access if secrets are logged, exposed, or intercepted.
|--------|------|------|
| `apiKey` | 百度 API Key(自带 API key 模式使用) | 否 |
| `secretKey` | 百度 Secret Key(自带 API key 模式使用) | 否 |
| `accessToken` | Access Token(OAuth 授权后自动保存) | 否 |
| `refreshToken` | Refresh Token(OAuth 授权后自动保存) | 否 |
| `encryptionKey` | 自定义加密密钥(可选,增强安全性) | 否 |
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- 创建新应用
- 获取 **API Key** 和 **Secret Key**
### 4. 获取 Access Token
方法一:OAuth 授权(推荐)
The curl example places the authorization code, API key, and especially the client secret directly in the URL query string. Query-string secrets are prone to leakage through shell history, terminal logs, browser or proxy logs, process inspection, and copied command history, which is particularly dangerous because the endpoint returns bearer tokens and refresh tokens for cloud storage access.
访问后获得 code,然后用 code 换 token:
curl "https://openapi.baidu.com/oauth/2.0/token?grant_type=authorization_code&code=你的 CODE&client_id=你的 API_KEY&client_secret=你的 SECRET_KEY&redirect_uri=oob"
返回的 JSON 里有 access_token 和 refresh_token。
The lockfile pins axios at 1.13.6, and the provided advisory set includes multiple high-severity issues affecting request handling, proxy behavior, and prototype-pollution-related exploitation paths. In a skill that performs OAuth and remote file management over HTTP, a vulnerable HTTP client is especially relevant because it directly mediates authentication, downloads, uploads, and outbound requests.
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
form-data is a runtime dependency commonly used for multipart uploads, which is directly relevant to a file-upload skill. If attacker-controlled filenames or field names are incorporated into multipart requests without proper escaping, CRLF injection could corrupt request structure or enable header injection against upstream services.
Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.
The manifest permits axios versions that static analysis maps to a version with numerous advisories, including SSRF- and MITM-related issues. In a Baidu Netdisk skill handling OAuth flows and remote file operations, an HTTP client vulnerability can expose access tokens, redirect requests, bypass proxy protections, or tamper with responses from external services.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
},
"accessToken": {
"type": "string",
"description": "Access Token(OAuth 授权后自动保存,无需手动配置)",
"required": false,
"secret": true
},
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
},
"accessToken": {
"type": "string",
"description": "Access Token(OAuth 授权后自动保存,无需手动配置)",
"required": false,
"secret": true
},
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
},
"accessToken": {
"type": "string",
"description": "Access Token(OAuth 授权后自动保存,无需手动配置)",
"required": false,
"secret": true
},
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
},
"accessToken": {
"type": "string",
"description": "Access Token(OAuth 授权后自动保存,无需手动配置)",
"required": false,
"secret": true
},
The skill stores OAuth access and refresh tokens with AES using a default key derived from a hardcoded constant, and merely reports that the token is encrypted locally. Anyone with access to the code and local config can reproduce the default key and decrypt stored tokens unless the operator overrides ENCRYPTION_KEY, making credential theft feasible on shared or compromised systems.
console.log(chalk.green('\n✅ 百度网盘授权完成!\n'));
console.log('Token 已加密保存在本地配置文件');
console.log(`Access Token 有效期:${Math.floor(expires_in / 86400)} 天`);
console.log('\n你现在可以开始使用百度网盘 Skill 了!\n');
console.log('常用命令:');
console.log(' npx baidu-netdisk-skill whoami # 查看用户信息');
This file handles access and refresh tokens plus client credentials, and it derives a default encryption key from a hardcoded constant if the environment variable is absent. Because that fallback is embedded in code and encryption is reversible, anyone with local config access and source knowledge can potentially recover persisted tokens, leading to account access and long-lived credential compromise.
}
/**
* 刷新 Access Token
*/
async refreshAccessToken() {
const response = await axios.post(
The CLI accepts API keys, access tokens, and refresh tokens directly as command-line arguments. On many systems, command-line arguments can be exposed through shell history, process listings, audit logs, or job runners, which can leak long-lived credentials and enable unauthorized access to the user's Baidu Netdisk account.
.description('配置百度 API 密钥')
.option('-k, --apikey <key>', 'API Key')
.option('-s, --secret <secret>', 'Secret Key')
.option('-t, --token <token>', 'Access Token')
.option('-r, --refresh <refresh>', 'Refresh Token')
.action(async (options) => {
console.log(chalk.blue('🔧 配置百度 API 密钥\n'));
The tool echoes the first 8 characters of the API key and access token after configuration. Even partial credential disclosure can aid correlation, leak identifying token prefixes into logs/screenshots, and normalize unsafe secret handling in terminal output; combined with the prior CLI-argument issue, this increases accidental exposure risk.
if (apiKey && secretKey && accessToken) {
console.log(chalk.green('✅ 配置完成!'));
console.log(`API Key: ${apiKey.slice(0, 8)}...`);
console.log(`Access Token: ${accessToken.slice(0, 8)}...`);
} else {
console.log(chalk.yellow('⚠️ 配置不完整,请运行:'));
console.log('npx baidu-netdisk-skill config -k <apikey> -s <secret> -t <token> -r <refresh>');
This line explicitly outputs portions of the access token and refresh token from the local config file. In a local test script for an OAuth-integrated file-management skill, these credentials are highly sensitive because anyone obtaining them may access or refresh access to the user's Baidu Netdisk account; printing even truncated values raises the chance of accidental disclosure through logs or shared environments.
cat "$CONFIG_FILE" | jq -r '
" API Key: " + (if .apiKey then (.apiKey[0:8] + "...") else "未设置" end) +
"\n Secret Key: " + (if .secretKey then (.secretKey[0:8] + "...") else "未设置" end) +
"\n Access Token: " + (if .accessToken then (.accessToken[0:8] + "...") else "未设置" end) +
"\n Refresh Token: " + (if .refreshToken then (.refreshToken[0:8] + "...") else "未设置" end) +
"\n Token 过期时间: " + (if .tokenExpires then (.tokenExpires | tostring) else "未设置" end)
' 2>/dev/null || echo " (无法解析 JSON)"
The README instructs users to execute npx baidu-netdisk-auth without a pinned package version. This can fetch the latest package at execution time, creating a supply-chain risk if the package is compromised or a malicious update is published. Because this skill is explicitly intended for credentialed OAuth flows, running an unpinned helper is more dangerous than a generic utility.