T05 · Unauthorized Access and Privilege Escalation
- Location
lib/employees.mjs:48- Finding
Organization-Wide Employee PII Collection Exceeds Functional Requirements
- Content
View full analysis
Vulnerability Details
File Location:
lib/employees.mjs:48-77, 218-240
Vulnerability Type: Excessive directory access and sensitive-data retention
Risk Level: MediumVulnerable Code
javascript async function fetchEmployees() { const employees = new Map(); let pageToken = ''; try { do { const params = { department_id: '0', // Root department = all employees page_size: 50, user_id_type: 'user_id' }; if (pageToken) params.page_token = pageToken; const result = await larkApi('GET', '/contact/v3/users', { params }); for (const user of (result.items || [])) { employees.set(user.user_id, { user_id: user.user_id, name: user.name, en_name: user.en_name, nickname: user.nickname, email: user.email, mobile: user.mobile, department_ids: user.department_ids, open_id: user.open_id }); } pageToken = result.has_more ? result.page_token : ''; } while (pageToken); return employees;javascript export async function listEmployees() { const employees = await getEmployeeCache(); return Array.from(employees.values()); } export async function searchEmployees(query) { const employees = await getEmployeeCache(); const results = []; const q = query.toLowerCase(); for (const emp of employees.values()) { const searchFields = [emp.name, emp.en_name, emp.nickname, emp.email].filter(Boolean); if (searchFields.some(f => f.toLowerCase().includes(q))) { results.push(emp); } } return results; }Technical Analysis
The declared name-resolution feature requires only a limited mapping between employee names and Lark user IDs. Instead, the implementation queries the root department, paginates through the organization-wide directory, and re ...[truncated 1883 chars]
- Remediation
View remediation
Remediation Suggestions
- Retain only fields required for identity resolution:
javascript employees.set(user.user_id, { user_id: user.user_id, name: user.name, en_name: user.en_name, nickname: user.nickname }); - Remove
email,mobile,department_ids, andopen_idunless a separately documented feature strictly requires them. - Avoid retrieving the entire root department for each cache refresh. Prefer a narrow server-side search endpoint or resolve only explicitly requested identities.
- Remove or restrict
listEmployees()andsearchEmployees()if organization-wide enumeration is not part of the declared interface. - Configure the Lark application with the narrowest contact scope capable of resolving attendee and assignee names.
- Document the exact directory data accessed, its retention period, and which exported interfaces can return it.
- Add tests that assert sensitive fields are neither retained nor returned by name-resolution functions.
- Retain only fields required for identity resolution:
