T09 · Insecure Skill Coding Practices
- Location
scripts/powpow-register.mjs:38- Finding
Predictable shared temporary state file permits session-token disclosure or redirected writes
- Content
View full analysis
Vulnerability Details
File Location:
scripts/powpow-register.mjs, lines 38–55 and 203–211
Vulnerability Type: Predictable sensitive temporary file / symlink vulnerability
Risk Level: MediumComplete code snippet:
js const BASE_URL = 'https://global.powpow.online'; const STATE_FILE = join(tmpdir(), 'powpow-register-state.json'); const PASSWORD_ENV = 'POWPOW_REGISTER_PASSWORD'; // ---------- 状态文件 ---------- function loadState() { try { return JSON.parse(readFileSync(STATE_FILE, 'utf8')); } catch { return {}; } } function saveState(patch) { const s = { ...loadState(), ...patch }; writeFileSync(STATE_FILE, JSON.stringify(s, null, 2), { mode: 0o600 }); return s; }The sensitive token is subsequently written through this function:
js const token = r.cookies['powpow_token'] || ''; if (!token) die('注册成功但未捕获到会话 cookie(平台响应异常)'); saveState({ username: r.data?.user?.username || username, nickname: r.data?.user?.nickname || nickname, userId: r.data?.userId, token, step: 'registered-pending', registeredAt: new Date().toISOString(), });Technical Analysis
The application stores workflow state at the fixed path
powpow-register-state.jsonin the operating system's shared temporary directory. The state includes the user's email address, account identity, order information, and a JWT session token.Although
writeFileSyncspecifies mode0600, that mode primarily controls permissions when a new file is created. It does not safely handle an existing attacker-created file, verify file ownership, require a regular file, prevent symbolic-link traversal, or request exclusive creation.On a multi-user system whose temporary-directory protections permit the operation, another local user can create the predictable path before the Skill runs. The attacker can use a permissively accessible regular file to capture state or a symb ...[truncated 1821 chars]
- Remediation
View remediation
Remediation Suggestions
- Create a private per-workflow directory with
mkdtempSyncand restrictive permissions, then place the state file inside it. - Create the state file atomically and exclusively, using flags equivalent to
O_CREAT | O_EXCL; useO_NOFOLLOWwhere supported. - Before every read or write, verify that the path is a regular file owned by the current effective user and is not a symbolic link.
- Open the file descriptor securely first and perform reads and writes through that descriptor rather than repeatedly resolving a shared pathname.
- Preserve workflow resumption by storing the randomly generated private state path in a user-private application data directory, not through another predictable shared-temporary file.
- Keep permissions at
0600and ensure the containing directory is accessible only to the current user. - Delete both the state file and its private temporary directory during cleanup.
- Create a private per-workflow directory with
