T09 · Insecure Skill Coding Practices
- Location
src/config.ts:11- Finding
Wallet Credentials Stored in Plaintext Without Explicitly Restrictive Permissions
- Content
View full analysis
Vulnerability Details
File Location:
src/config.ts:11-32
Vulnerability Type: Plaintext sensitive-data storage with insufficient permission enforcement
Risk Level: HighThe configuration file stores the Circle API key and entity secret. These credentials are supplied to
saveConfig()fromsrc/cli.ts:75-80andsrc/cli.ts:125-130.ts const CONFIG_DIR = path.join(process.env.HOME || '~', '.openclaw', 'circle-wallet'); const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json'); export function ensureConfigDir(): void { if (!fs.existsSync(CONFIG_DIR)) { fs.mkdirSync(CONFIG_DIR, { recursive: true }); } } export function loadConfig(): WalletConfig { ensureConfigDir(); if (!fs.existsSync(CONFIG_FILE)) { throw new Error('No configuration found. Run "circle-wallet setup" first.'); } const config = JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf-8')); return config; } export function saveConfig(config: WalletConfig): void { ensureConfigDir(); fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2)); }The sensitive values written by these functions include:
ts saveConfig({ apiKey, entitySecret, env, defaultChain: env === 'sandbox' ? 'ARC-TESTNET' : 'BASE' });Technical Analysis
config.jsoncontains both the Circle API key and the entity secret in plaintext. The code does not assign an explicit mode when creating the configuration directory or writing the credential file. Consequently, access control depends on the process umask and any pre-existing directory or file permissions.The entity secret is used by the Circle SDK to protect developer-controlled wallet operations, while the API key authenticates API requests. Disclosure of both values can therefore expose financially sensitive wallet capabilities.
This behavior exceeds the minimum safe privilege model for credential storage: persistent storage is neces ...[truncated 1342 chars]
- Remediation
View remediation
Remediation Suggestions
-
Create the credential directory with owner-only permissions:
ts fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 }); fs.chmodSync(CONFIG_DIR, 0o700); -
Create and update the configuration file with mode
0600:ts fs.writeFileSync( CONFIG_FILE, JSON.stringify(config, null, 2), { encoding: 'utf8', mode: 0o600 } ); fs.chmodSync(CONFIG_FILE, 0o600); -
Use an atomic write through a private temporary file to avoid partial writes and permission inconsistencies.
-
Check whether the path is a symbolic link before writing, and avoid following attacker-controlled links.
-
Migrate existing installations by checking and repairing directory and file permissions.
-
Prefer an operating-system keychain, credential vault, or dedicated secret manager instead of plaintext JSON.
-
Document credential rotation procedures and advise users to rotate credentials if the file may previously have been readable by unintended principals.
-
