Back to Home

Cleaning Metadata from Python Clipboard

Background Python Service for Windows automatically cleans metadata from files in the clipboard when copying. Supports images, DOCX, PDF with attack protection and atomic overwriting. Analysis of architecture, code, and typical Win32 API errors.

Python Daemon: metadata cleaning in clipboard
Advertisement 728x90

Automatic Metadata Scrubbing for Clipboard Files in Python

A background daemon for Windows intercepts files in the clipboard immediately after copying and removes their metadata before pasting. This eliminates the need for manual processing of images, documents, and videos using ExifTool or system utilities. Processing occurs locally without external data transfer, with protection against corruption and symlink attacks.

Working with the Clipboard via Win32 API

Clipboard monitoring is implemented by a ClipboardMonitor thread that polls the clipboard every 500 ms. The key format is CF_HDROP, which contains a list of file paths.

Issues with pywin32:

Google AdInline article slot
  • In older versions, GetClipboardData(CF_HDROP) returns a pointer to DROPFILES, requiring DragQueryFileW from shell32.dll via ctypes.
  • In newer versions, it returns a list of strings, but PyInstaller or DLL mismatches can break this behavior.

Check code:

if win32clipboard.IsClipboardFormatAvailable(win32clipboard.CF_HDROP):
    file_list = win32clipboard.GetClipboardData(win32clipboard.CF_HDROP)

Path Validation for Security

Before processing, paths undergo strict checks in validate_path:

  • Absolute path.
  • Comparison of original inode and resolved_path (to block symlinks).
  • Exclusion of directories in WINDIR.
  • Limit on the number of files (protection against mass processing).

This prevents symlink attacks and processing of system directories. Additionally, resolved_path.is_file() is checked to exclude folders.

Google AdInline article slot

Processing Architecture: In-Place Overwriting

Files are overwritten at their original path without substitution in the clipboard—this simplifies handling Windows memory locks. Sequence:

  • Copying a file to the clipboard.
  • Detecting CF_HDROP.
  • Validation and passing to MetadataScrubber.
  • Overwriting with the clean version.

Image Scrubbing: Atomic Replacement

Support for JPEG, PNG, TIFF, BMP. Removes EXIF data including geolocation, device, and software information.

Strategy—temporary file for atomicity:

Google AdInline article slot
with Image.open(file_path) as img:
    data = list(img.getdata())
    image_without_exif = Image.new(img.mode, img.size)
    image_without_exif.putdata(data)
    
    temp_path = file_path.with_suffix(file_path.suffix + '.temp')
    image_without_exif.save(temp_path, format=format_name)
    
    shutil.move(str(temp_path), str(file_path))

Ensures integrity: pasting receives either the original or the scrubbed file.

DOCX: Direct XML Editing

python-docx changes properties but not Track Changes and comments. Solution—parsing _blob parts:

xml = part._blob.decode('utf-8')
if 'w:revision' in xml or 'w:ins' in xml or 'w:del' in xml:
    xml = xml.replace('w:revision', 'w:revision_removed')\
             .replace('w:ins ', 'w:p ')\
             .replace('w:del ', 'w:p ')
    part._blob = xml.encode('utf-8')

A hack with replace removes revision tags at the root, making the document final for Word. Risk—complex tables.

PDF and Video: Basic Support

PDF via pypdf:

writer = PdfWriter()
for page in reader.pages:
    writer.add_page(page)
writer.add_metadata({})

Rebuilding without metadata. Video (MP4, MKV, MOV)—basic atom scrubbing; full scrubbing requires ffmpeg.

Issues with the System Tray

Avoiding notifications due to Shell_NotifyIcon errors:

  • Incorrect HWND lifecycle leads to DestroyWindow failures.
  • COM objects crash when closing Tkinter.

Solution—removed the module for background stability. Polling at 500 ms results in 0% CPU usage when idle.

Key Points

  • Automatic metadata scrubbing (EXIF, Track Changes, geolocation) when copying to the clipboard.
  • Protection against symlink attacks and system paths through validation.
  • Atomic file overwriting without risk of corruption.
  • Local processing in Python (PIL, pywin32, pypdf) without external servers.
  • Optimized clipboard monitoring with minimal overhead.

— Editorial Team

Advertisement 728x90

Read Next