Skip to content

Commit ea248e1

Browse files
committed
Auto merge of #1898 - jtgeibel:issue-169, r=smarnach
Check that URLs begin with `http://` or `https://` This switches to a manual check of the string prefix, because `Url::parse` may sanitize URLs as they are parsed, making it difficult to ensure both slashes are present. Fixes: #169
2 parents 3248b4d + b46821b commit ea248e1

File tree

1 file changed

+26
-18
lines changed

1 file changed

+26
-18
lines changed

src/models/krate.rs

+26-18
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub struct NewCrate<'a> {
9999

100100
impl<'a> NewCrate<'a> {
101101
pub fn create_or_update(
102-
mut self,
102+
self,
103103
conn: &PgConnection,
104104
uploader: i32,
105105
rate_limit: Option<&PublishRateLimit>,
@@ -128,31 +128,25 @@ impl<'a> NewCrate<'a> {
128128
})
129129
}
130130

131-
fn validate(&mut self) -> CargoResult<()> {
131+
fn validate(&self) -> CargoResult<()> {
132132
fn validate_url(url: Option<&str>, field: &str) -> CargoResult<()> {
133133
let url = match url {
134134
Some(s) => s,
135135
None => return Ok(()),
136136
};
137-
let url = Url::parse(url)
138-
.map_err(|_| human(&format_args!("`{}` is not a valid url: `{}`", field, url)))?;
139-
match &url.scheme()[..] {
140-
"http" | "https" => {}
141-
s => {
142-
return Err(human(&format_args!(
143-
"`{}` has an invalid url \
144-
scheme: `{}`",
145-
field, s
146-
)));
147-
}
148-
}
149-
if url.cannot_be_a_base() {
137+
138+
// Manually check the string, as `Url::parse` may normalize relative URLs
139+
// making it difficult to ensure that both slashes are present.
140+
if !url.starts_with("http://") && !url.starts_with("https://") {
150141
return Err(human(&format_args!(
151-
"`{}` must have relative scheme \
152-
data: {}",
142+
"URL for field `{}` must begin with http:// or https:// (url: {})",
153143
field, url
154144
)));
155145
}
146+
147+
// Ensure the entire URL parses as well
148+
Url::parse(url)
149+
.map_err(|_| human(&format_args!("`{}` is not a valid url: `{}`", field, url)))?;
156150
Ok(())
157151
}
158152

@@ -524,7 +518,21 @@ sql_function!(fn to_char(a: Date, b: Text) -> Text);
524518

525519
#[cfg(test)]
526520
mod tests {
527-
use crate::models::Crate;
521+
use crate::models::{Crate, NewCrate};
522+
523+
#[test]
524+
fn deny_relative_urls() {
525+
let krate = NewCrate {
526+
name: "name",
527+
description: None,
528+
homepage: Some("https:/example.com/home"),
529+
documentation: None,
530+
readme: None,
531+
repository: None,
532+
max_upload_size: None,
533+
};
534+
assert!(krate.validate().is_err());
535+
}
528536

529537
#[test]
530538
fn documentation_blocked_no_url_provided() {

0 commit comments

Comments
 (0)