Documentation
¶
Overview ¶
Package localimage reads an image from a directory the person allowed in GITLAB_MCP_UPLOAD_DIRS, for upload_file to send (docs/architecture.md §7.10). It touches no network.
An upload tool is an exfiltration channel by construction: a comment that persuades a model to "attach" a key file would send the key. So four checks stand between a path and the bytes sent:
- The path is absolute, has no ".." element, and is lexically inside a directory the person allowed.
- It is opened through os.Root on that directory, so neither ".." nor a symbolic link can lead outside it.
- It names a regular file, not a symbolic link, a directory or a FIFO. That is checked before opening and again on the open file, so a file swapped in between is refused.
- At most MaxBytes are read, and the bytes must sniff as PNG, JPEG, GIF or WebP, the way GitLab's Workhorse sniffs the uploads it serves. SVG is text that can carry script, and is refused.
The sniff keeps out what is not an image: a key, a configuration file, a document. It does not prove the whole file is one. Bytes after a valid image header go too, and a file made that way needs someone who can write to this machine, which an instruction planted in GitLab content cannot do by itself.
Index ¶
Constants ¶
const MaxBytes = 10 << 20
MaxBytes is the largest image read: 10 MiB, a tenth of gitlab.com's attachment limit. A screenshot or a mock-up is far smaller, and the whole image is held in memory and sent in one request that the HTTP timeout bounds (§7.10).
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Image ¶
type Image struct {
// Name is the name it is sent under: the file's base name with every
// character but ASCII letters, digits, '.', '-' and '_' made '_', and
// the extension of its type in place of its own. No directory goes
// with it.
Name string
// Type is the media type its bytes sniff as.
Type string
Data []byte
}
Image is an image read and checked, ready to send.
type Kind ¶
type Kind int
Kind is why an image was not read. The caller words each one and gives it a class: the names of the tool and the setting are its.
const ( // NotAbsolute: the path is relative. NotAbsolute Kind = iota + 1 // DotDot: the path has a ".." element. DotDot // NoDirectories: no directory is allowed. NoDirectories // Outside: the path is in none of the allowed directories. Outside // NoDirectory: an allowed directory holding the path does not exist. NoDirectory // Missing: nothing is at the path. Missing // Escapes: a symbolic link along the path leads out of every allowed // directory holding it. Escapes // NotRegular: a symbolic link, a directory, a FIFO or a device; // Detail says which. NotRegular // Changed: the file was swapped between the check and the open. Changed // TooLarge: more than MaxBytes. TooLarge // NotImage: the bytes are not a PNG, JPEG, GIF or WebP. NotImage // Unreadable: the operating system refused; Detail is its reason, // without the path. Unreadable )
The kinds.