T09 · Insecure Skill Coding Practices
- Location
agent.py:95- Finding
Insecure Temporary-File Creation Enables Symlink Race Attacks
- Content
View full analysis
Vulnerability Details
File Location:
agent.py, lines 95 and 106
Vulnerability Type: Insecure temporary-file creation
Risk Level: MediumVulnerable Code
python def get_screenshot(save_path=None): """Get a screenshot and return its path.""" if not save_path: save_path = tempfile.mktemp(suffix='.png') out, _, code = adb(['exec-out', 'screencap', '-p'], binary=True) if code == 0 and out: with open(save_path, 'wb') as f: f.write(out) return save_path return Nonepython def get_uidump(save_path=None): """Get the UI hierarchy XML.""" if not save_path: save_path = tempfile.mktemp(suffix='.xml') _, _, code = adb(['exec-out', 'uiautomator', 'dump', '/sdcard/dump.xml']) if code != 0: return None _, _, code = adb(['pull', '/sdcard/dump.xml', save_path]) if code == 0 and os.path.exists(save_path): return save_path return NoneTechnical Analysis
tempfile.mktemp()generates a candidate pathname but does not atomically create or reserve the corresponding file. A time-of-check-to-time-of-use window therefore exists between generating the path and writing screenshot data withopen()or passing the path toadb pull.A local attacker who can access the shared temporary directory could create a symbolic link or another filesystem object at the generated path during this window. The later operation may then use the attacker-controlled destination. Exploitation depends on the attacker's local access, ability to identify or predict the temporary pathname, filesystem protections, and the privileges under which the skill runs.
Attack Path
- A user invokes the
screenshotoruidumpcommand. - The process calls
tempfile.mktemp()and receives a pathname that has not been securely reserved. - Before
open(save_path, 'wb')oradb pull ... save_pathexecutes, a local attacker places a symbolic link at that pathname.
...[truncated 903 chars]
- A user invokes the
- Remediation
View remediation
Remediation Suggestions
- Replace
tempfile.mktemp()with an API that atomically creates the temporary file, such astempfile.mkstemp()ortempfile.NamedTemporaryFile(delete=False). - Retain and use the securely created file descriptor where possible, rather than closing it and reopening the path.
- Restrict temporary-file permissions to the owning user, preferably mode
0600. - For
adb pull, securely create a private temporary directory withtempfile.TemporaryDirectory()and place the destination file inside it. - Remove screenshots and UI dumps promptly after use because they may contain sensitive device data.
- When accepting an explicit
save_path, validate the destination according to the intended trust boundary and avoid following untrusted symbolic links where supported.
Example hardening pattern:
python fd, save_path = tempfile.mkstemp(suffix='.png') try: os.fchmod(fd, 0o600) with os.fdopen(fd, 'wb') as f: f.write(out) except Exception: os.close(fd) raiseFor UI dumps, use a private temporary directory:
python temp_dir = tempfile.mkdtemp(prefix='phone-agent-') os.chmod(temp_dir, 0o700) save_path = os.path.join(temp_dir, 'dump.xml')- Replace
