T09 · Insecure Skill Coding Practices
- Location
references/oauth-setup.md:127- Finding
OAuth Credentials Stored in an Unprotected Plaintext JSON File
- Content
View full analysis
Vulnerability Details
File Location:
references/oauth-setup.md:127-140; related token-refresh logic inSKILL.md:54-62
Vulnerability Type: Plaintext storage of reusable OAuth credentials
Risk Level: MediumVulnerable Code
references/oauth-setup.md:127-140:powershell # 保存配置 $config = @{ access_token = $resp2.data.access_token refresh_token = $resp2.data.refresh_token calendar_id = $calendarId app_id = $appId app_secret = $appSecret } $tokenFile = "$env:USERPROFILE\.openclaw\workspace\skills\feishu-calendar-oauth\scripts\.user_token.json" New-Item -ItemType Directory -Force -Path (Split-Path $tokenFile) | Out-Null $config | ConvertTo-Json | Out-File $tokenFile -Encoding UTF8SKILL.md:54-62:powershell # 刷新 Token $config = Get-Content "$env:USERPROFILE\.openclaw\workspace\skills\feishu-calendar-oauth\scripts\.user_token.json" | ConvertFrom-Json $body1 = @{ app_id = $config.app_id; app_secret = $config.app_secret } | ConvertTo-Json $appToken = (Invoke-RestMethod -Uri "https://open.feishu.cn/open-apis/auth/v3/app_access_token/internal" -Method Post -Body $body1 -ContentType "application/json").app_access_token $body2 = @{ grant_type = "refresh_token"; refresh_token = $config.refresh_token } | ConvertTo-Json $newToken = Invoke-RestMethod -Uri "https://open.feishu.cn/open-apis/authen/v1/oidc/refresh_access_token" -Method Post -Body $body2 -ContentType "application/json" -Headers @{ Authorization = "Bearer $appToken" } $config.access_token = $newToken.data.access_token $config.refresh_token = $newToken.data.refresh_token $config | ConvertTo-Json | Out-File "$env:USERPROFILE\.openclaw\workspace\skills\feishu-calendar-oauth\scripts\.user_token.json"Technical Analysis
The documented setup procedure stores the Feishu application secret, access token, refresh token, calendar identifier, and application identifier in an ordinary JSON file. T ...[truncated 2407 chars]
- Remediation
View remediation
Remediation Suggestions
- Store the App Secret and OAuth refresh token in an operating-system-backed secret store, such as Windows Credential Manager or a DPAPI-protected credential container, rather than in the workspace.
- Avoid retaining the App Secret in the calendar configuration file when it is not required for normal calendar operations.
- If file storage is unavoidable, encrypt sensitive values with DPAPI under the current user context and decrypt them only in memory when needed.
- Create the credential file with an explicit current-user-only ACL. Do not rely solely on inherited directory permissions.
- Use atomic replacement with restrictive permissions during token refresh so that rewrites do not temporarily create a broadly readable file or weaken the existing ACL.
- Add
.user_token.jsonto version-control, packaging, backup, logging, and workspace-synchronization exclusion rules. - Document credential revocation and rotation procedures. Users should revoke the refresh token and rotate the App Secret if the file may have been exposed.
- Store non-sensitive data such as
calendar_idseparately from secrets to minimize the contents of the protected credential store.
