@@ -48,6 +48,13 @@ pub struct Url {
48
48
/// The port to use when connecting to a host. If `None`, standard ports depending on `scheme` will be used.
49
49
pub port : Option < u16 > ,
50
50
/// The path portion of the URL, usually the location of the git repository.
51
+ ///
52
+ /// # Security-Warning
53
+ ///
54
+ /// URLs allow paths to start with `-` which makes it possible to mask command-line arguments as path which then leads to
55
+ /// the invocation of programs from an attacker controlled URL. See https://secure.phabricator.com/T12961 for details.
56
+ ///
57
+ /// If this value is going to be used in a command-line application, call [Self::path_argument_safe()] instead.
51
58
pub path : bstr:: BString ,
52
59
}
53
60
@@ -123,9 +130,34 @@ impl Url {
123
130
self . password . as_deref ( )
124
131
}
125
132
/// Returns the host mentioned in the url, if present.
133
+ ///
134
+ /// # Security-Warning
135
+ ///
136
+ /// URLs allow hosts to start with `-` which makes it possible to mask command-line arguments as host which then leads to
137
+ /// the invocation of programs from an attacker controlled URL. See https://secure.phabricator.com/T12961 for details.
138
+ ///
139
+ /// If this value is going to be used in a command-line application, call [Self::host_argument_safe()] instead.
126
140
pub fn host ( & self ) -> Option < & str > {
127
141
self . host . as_deref ( )
128
142
}
143
+
144
+ /// Return the host of this URL if present *and* if it can't be mistaken for a command-line argument.
145
+ ///
146
+ /// Use this method if the host is going to be passed to a command-line application.
147
+ pub fn host_argument_safe ( & self ) -> Option < & str > {
148
+ self . host ( ) . filter ( |host| !looks_like_argument ( host. as_bytes ( ) ) )
149
+ }
150
+
151
+ /// Return the path of this URL *and* if it can't be mistaken for a command-line argument.
152
+ /// Note that it always begins with a slash, which is ignored for this comparison.
153
+ ///
154
+ /// Use this method if the path is going to be passed to a command-line application.
155
+ pub fn path_argument_safe ( & self ) -> Option < & BStr > {
156
+ self . path
157
+ . get ( 1 ..)
158
+ . and_then ( |truncated| ( !looks_like_argument ( truncated) ) . then_some ( self . path . as_ref ( ) ) )
159
+ }
160
+
129
161
/// Returns true if the path portion of the url is `/`.
130
162
pub fn path_is_root ( & self ) -> bool {
131
163
self . path == "/"
@@ -146,6 +178,10 @@ impl Url {
146
178
}
147
179
}
148
180
181
+ fn looks_like_argument ( b : & [ u8 ] ) -> bool {
182
+ b. get ( 0 ) == Some ( & b'-' )
183
+ }
184
+
149
185
/// Transformation
150
186
impl Url {
151
187
/// Turn a file url like `file://relative` into `file:///root/relative`, hence it assures the url's path component is absolute, using
0 commit comments