uripath

package
v1.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2026 License: MIT Imports: 0 Imported by: 0

Documentation

Overview

Package uripath holds the one decision every local-file resolver has to make before it parses a reference as a URI: whether the reference is a Windows drive-letter path rather than something naming a scheme.

It is a leaf package because xslt, relaxng and dtd each own a resolver that needs the same answer and none of the three may import another. Copying the rule into three files would mean three places to get a security decision wrong, and the copies would drift.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsDriveLetterPath

func IsDriveLetterPath(s string) bool

IsDriveLetterPath reports whether s is a Windows absolute path naming a drive — "C:\dir\f.rng", "C:/dir/f.rng", "C:" — rather than a URI reference carrying a one-letter scheme.

Why this exists

url.Parse("C:/dir/f.rng") returns Scheme "c". A resolver that refuses every scheme but "file" therefore refuses every absolute path on Windows, before the code that knows how to turn a drive path into a filesystem path ever runs. The guard sits upstream of the knowledge.

The rule, and why it is the only safe one

A drive letter and a genuine one-letter scheme are textually identical up to the colon, and they are identical AFTER url.Parse as well:

url.Parse("C:/Users/x")      -> Scheme "c", Host "",  Path "/Users/x"
url.Parse("c:///secret.rng") -> Scheme "c", Host "",  Path "/secret.rng"

Nothing in the parse result separates them. So the decision has to be made on the raw string, and the discriminator is the two slashes:

a reference is a drive-letter path iff its first byte is an ASCII
letter, its second byte is ':', and what follows the colon does not
begin with "//".

RFC 3986 section 3 is what makes that sound: "//" immediately after the scheme's colon is the delimiter that introduces an authority component. A filesystem drive path has no authority and can never produce one — "C://x" is not a path any Windows API accepts. So every string that could be a hierarchical URI with an authority is excluded, and what remains is the drive-path shape. Concretely:

"C:\Users\x"      -> admitted (remainder "\Users\x")
"C:/Users/x"      -> admitted (remainder "/Users/x")
"C:"              -> admitted (remainder "")
"C:rel\x"         -> admitted (drive-relative; a real Windows spelling)
"c:///secret.rng" -> REFUSED  (remainder "///..." begins "//")
"c://host/x"      -> REFUSED  (remainder "//host/x" begins "//")
"http://e/x"      -> REFUSED  (two-letter-plus scheme)
"/etc/passwd"     -> REFUSED  (no colon at index 1; not a drive path)

The "c:///" form is the escape payload the confinement tests plant. It must keep being refused, because admitting it would let a reference reach the filesystem as "/secret.rng" — a rooted path outside any grant.

Why this is not gated on runtime.GOOS

Two reasons. Admitting "c:/x" on a Unix host gives up nothing: it is not an absolute path there, so it is joined against the base directory and then meets the same root-confinement check as any relative reference. The scheme guard is not the confinement boundary — filepath.Rel against the root is, and that is unchanged on every platform.

And a security branch that only executes on one OS is a security branch that the CI host running most of the suite never tests. Keeping the rule unconditional keeps it exercised everywhere, which matters more than narrowing a surface that the confinement check already covers. It also keeps this package consistent with the rest of the tree, which carries almost no runtime.GOOS branching outside tests.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL