T05 · Unauthorized Access and Privilege Escalation
Warning
- Location
- scripts/transfer_owner.py:76
- Finding
- Ownership transfers do not consistently prevent reassignment of human-owned documents<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/transfer_owner.py:76-90` - `scripts/transfer_wiki.py:142-155` - Related declared behavior: `SKILL.md:14-20` **Vulnerability Type**: Missing source-owner authorization filtering **Risk Level**: Medium ### Vulnerable Code Single-token transfer mode in `scripts/transfer_owner.py:76-90`: ```python if args.token: parts = args.token.split(":", 1) file_type, token = parts[0], parts[1] info = get_file_info(file_type, token) owner = info.get("owner_id", "unknown") fname = info.get("name", file_type) print(f" 文件: {fname}") print(f" 类型: {file_type}") print(f" 当前所有者: {owner}") if not args.list: resp = transfer_owner(file_type, token, args.target, args.member_type) if resp.get("code") == 0: print(f" 转移成功 -> {args.target}") ``` Wiki transfer mode in `scripts/transfer_wiki.py:142-155`: ```python # 跳过已是目标所有者的 if current_owner == args.target: print(f"{indent} ✅ 已是目标所有者,跳过") skipped += 1 print() continue if args.list: print(f"{indent} [DRY-RUN] 将转移 -> {args.target}") transferred += 1 else: resp = transfer_owner(ftype, docs_token, args.target, args.member_type) if resp.get("code") == 0: print(f"{indent} ✅ 转移成功") transferred += 1 ``` ### Technical Analysis The Skill declares that it transfers documents created by an AI agent and automatically skips files already owned by humans. Root-directory batch mode implements a heuristic for this behavior by treating owner IDs beginning with `ou_` as human owners. That protection is not applied consistently: 1. In single-token mode, the script retrieves and displays the current owner but transfers the document without checking whether that owner is an AI identity, a permitted source owner, or a human. 2. In Wiki mode, the only ownership restriction is that a document already owned by the destination user is skipped. Any other accessible document is s ...[truncated 2959 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Require a verified source owner in every mutating mode** - Add a required `--source-owner` or `--ai-owner` parameter for single-token and Wiki transfers. - Abort the transfer if owner metadata is absent, unknown, or does not exactly match the expected source identity. - Do not rely solely on an owner-ID prefix to determine whether an account is human or automated. 2. **Apply one shared authorization policy** - Implement a central function such as: ```python def is_transfer_allowed(current_owner, target_owner, allowed_source_owner): if not current_owner: return False if current_owner == target_owner: return False return current_owner == allowed_source_owner ``` - Invoke this function from root batch, single-token, and Wiki workflows before every transfer. 3. **Fail closed when metadata lookup fails** - A missing owner must not be represented as `"unknown"` and then ignored. - Abort or skip when Feishu returns an error, incomplete metadata, or an unrecognized owner type. 4. **Require explicit authorization for human-owned content** - If transferring human-owned documents is a necessary advanced feature, require a conspicuous override such as `--include-human-owned`. - Combine that override with an exact source-owner allowlist and interactive confirmation. - Clearly state that the override exceeds the default AI-document scope. 5. **Make batch workflows safe by default** - Default Wiki and broad root scans to dry-run behavior. - Require a separate `--apply` flag to perform mutations. - Before applying changes, display the source owner, destination owner, document name, type, and total number of affected documents. - Require confirmation for interactive use and a separate explicit flag for non-interactive execution. 6. **Constrain destination identities** - Validate `--member-type` against a fixed allowlist supported by the transfer API. - Valida ...[truncated 706 chars]
