T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/feishu_file_sender.py:25- Finding
Workspace Prefix Confusion Permits Cross-Agent Feishu Account Selection
- Content
View full analysis
Vulnerability Details
File Location:
scripts/feishu_file_sender.py, lines 25-40
Vulnerability Type: Improper workspace authorization boundary validation
Risk Level: MediumVulnerable Code
python def resolve_agent_id(config: Dict[str, Any]) -> str: cwd = Path.cwd().resolve() best_match = (0, None) for agent in config.get("agents", {}).get("list", []): workspace = agent.get("workspace") agent_id = agent.get("id") if not workspace or not agent_id: continue workspace_path = Path(workspace).resolve() if str(cwd).startswith(str(workspace_path)): match_len = len(str(workspace_path)) if match_len > best_match[0]: best_match = (match_len, agent_id) if best_match[1]: return best_match[1] raise RuntimeError("Unable to resolve agent id from workspace path")Technical Analysis
The current working directory is associated with an agent by performing a raw string-prefix comparison:
python str(cwd).startswith(str(workspace_path))A string prefix is not equivalent to a filesystem ancestry check. For example, if an agent workspace is
/srv/agents/finance, a separate directory named/srv/agents/finance-attackeralso passes this test.The resulting agent ID is subsequently used to select a Feishu account binding and read its
appIdandappSecret. Therefore, workspace resolution serves as an authorization boundary, but the implementation does not accurately verify that the process is inside the selected workspace.The credentials are not printed or returned directly. Nevertheless, the script uses the incorrectly selected credentials to obtain a tenant access token, upload a caller-selected local file, and send it to a caller-selected Feishu recipient. This exposes the victim agent's Feishu bot authority as a confused-deputy capability.
Attack Path
...[truncated 1698 chars]
- Remediation
View remediation
Remediation Suggestions
Replace string-prefix matching with a component-aware filesystem ancestry test:
python workspace_path = Path(workspace).expanduser().resolve() if cwd == workspace_path or workspace_path in cwd.parents: match_len = len(workspace_path.parts) if match_len > best_match[0]: best_match = (match_len, agent_id)Additional hardening should include:
- Prefer receiving the active agent ID from a trusted runtime context rather than inferring authorization from the current working directory.
- Verify that the trusted agent ID, workspace, and Feishu account binding are mutually consistent before reading credentials.
- Reject ambiguous workspace configurations, including duplicate or overlapping workspace roots.
- Restrict selectable recipients to the current inbound conversation unless an explicit policy grants broader delivery rights.
- Consider restricting file paths to the authenticated agent's workspace or a dedicated output directory.
- Add tests covering sibling paths such as
/workspace,/workspace-evil,/workspace2, and legitimate descendants such as/workspace/output.
