T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- index.js:15
- Finding
- Overbroad Authentication Profile Access and Account Identifier Disclosure<![CDATA[ ## Vulnerability Details **File Location**: `index.js:15`, `index.js:44-66`, and `index.js:334-343` **Vulnerability Type**: T05: Unauthorized Access and Privilege Escalation **Risk Level**: Medium ### Relevant Code ```js const AUTH_FILE = path.join(process.env.HOME, '.openclaw/agents/main/agent/auth-profiles.json'); ``` ```js function loadAuthProfiles() { if (!fs.existsSync(AUTH_FILE)) { return { profiles: {}, error: 'Auth file not found' }; } try { const data = JSON.parse(fs.readFileSync(AUTH_FILE, 'utf8')); return { profiles: data.profiles || {}, raw: data }; } catch (e) { return { profiles: {}, error: e.message }; } } function getLoggedInProviders(profiles) { const providers = {}; for (const [key, profile] of Object.entries(profiles)) { const provider = profile.provider; if (!providers[provider]) { providers[provider] = { loggedIn: true, email: profile.email || null, expires: profile.expires || null, isExpired: profile.expires ? Date.now() > profile.expires : false }; } } return providers; } ``` ```js const providerNames = ['google-antigravity', 'github-copilot', 'openai-codex']; for (const p of providerNames) { const info = loggedIn[p]; if (info) { const status = info.isExpired ? '⚠️ Token Expired' : '✅ Logged In'; console.log(`| ${p} | ${status} | ${info.email || '-'} |`); } else { console.log(`| ${p} | ❌ Not Logged In | - |`); } } ``` ### Technical Analysis The Skill reads and parses the complete shared OpenClaw authentication profile file even though its declared purpose only requires credentials and expiration information for three supported providers. It also returns the complete parsed object through the unused `raw` property, unnecessarily retaining all data from the authentication store. The dashboard includes provider account email addresses in its standard output. `SKILL.md` instructs the invoking Agent to reproduce this o ...[truncated 1715 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the unused `raw` return value so the complete authentication document is not retained: ```js return { profiles: data.profiles || {} }; ``` 2. Immediately filter profiles to the explicitly supported providers: - `google-antigravity` - `github-copilot` - `openai-codex` 3. Copy only required fields into short-lived objects rather than passing complete profile records through the program. 4. Do not display email addresses by default. Show a redacted identifier or `-`. 5. If account display is necessary, require an explicit option such as `--show-account`. 6. Document the authentication file being accessed and the specific fields used. 7. Run the Skill under an account or sandbox that cannot read unrelated authentication stores where possible. ]]>
