T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/cleanup_executor.py:210
- Finding
- Filename-Only Asset Matching Can Delete Unintended Photos<![CDATA[ ## Vulnerability Details **File Location**: `scripts/cleanup_executor.py:210-224` **Vulnerability Type**: Non-unique identifier used for destructive operations **Risk Level**: High ### Vulnerable Code ```python # Build the filename matching list with proper escaping filename_list = ", ".join(f'"{escape_applescript(fn)}"' for fn in filenames) script = f""" set targetNames to {{{filename_list}}} set matchCount to 0 tell application "Photos" repeat with targetName in targetNames try set matchingItems to (search for targetName) repeat with anItem in matchingItems if (filename of anItem) is equal to (contents of targetName) then delete anItem ``` ### Technical Analysis Cleanup candidates are initially selected from the Photos database with a unique `Z_PK` value. However, the destructive AppleScript operation discards that identifier and searches the entire Photos library using only `ZFILENAME`. Photo filenames are not guaranteed to be unique. Cameras and phones commonly reuse names such as `IMG_0001.JPG`, particularly after counter resets, device migrations, or imports from multiple devices. The generated AppleScript iterates over every search result and deletes every asset whose filename equals the candidate filename. AppleScript string escaping reduces script-injection risk, but it does not address identifier ambiguity. The comment claiming that filename matching is the safest approach is therefore incorrect for destructive operations. The execution result is also potentially misleading. After a successful AppleScript batch, `success_count` is increased by the number of database candidates rather than by the number of Photos assets actually matched and moved. Consequently, the program may delete more items than it reports. ### Attack Path 1. The Photos library contains two or more assets with the same filename. 2. One of those assets satisfies a cleanup category, such as ...[truncated 1074 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not authorize deletion using filenames alone. 2. Preserve and use a stable Photos identifier that can be resolved through Photos.app if such an identifier is available. 3. If Photos.app cannot resolve the database identifier, use a composite identity containing filename, exact creation timestamp, media type, dimensions, and other stable metadata. 4. Treat every lookup producing more than one result as ambiguous and skip it rather than deleting all matches. 5. Resolve the final Photos.app asset set before confirmation and display every resolved item to the user. 6. Require a second confirmation when any ambiguity or candidate-count mismatch is detected. 7. Parse and validate the actual AppleScript match count instead of increasing `success_count` by the requested batch size. 8. Add tests with multiple assets sharing the same filename and verify that no unrelated asset can be deleted. 9. Update comments and documentation to disclose that filename searches are ambiguous unless additional identity checks are applied. ]]>
