diff --git a/src/kits/package/PackageInfoParser.cpp b/src/kits/package/PackageInfoParser.cpp
index f684815..ed241e7 100644
--- a/src/kits/package/PackageInfoParser.cpp
+++ b/src/kits/package/PackageInfoParser.cpp
@@ -1,5 +1,6 @@
 /*
  * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
+ * Copyright 2016, Andrew Lindesay <apl@lindesay.co.nz>
  * Distributed under the terms of the MIT License.
  */
 
@@ -508,19 +509,22 @@ BPackageInfo::Parser::_ParseList(ListElementParser& elementParser,
 
 void
 BPackageInfo::Parser::_ParseStringList(BStringList* value,
-	bool requireResolvableName, bool convertToLowerCase)
+	bool requireResolvableName, bool convertToLowerCase,
+	StringValidator* stringValidator)
 {
 	struct StringParser : public ListElementParser {
 		BStringList* value;
 		bool requireResolvableName;
 		bool convertToLowerCase;
+		StringValidator* stringValidator;
 
 		StringParser(BStringList* value, bool requireResolvableName,
-			bool convertToLowerCase)
+			bool convertToLowerCase, StringValidator* stringValidator)
 			:
 			value(value),
 			requireResolvableName(requireResolvableName),
-			convertToLowerCase(convertToLowerCase)
+			convertToLowerCase(convertToLowerCase),
+			stringValidator(stringValidator)
 		{
 		}
 
@@ -541,9 +545,13 @@ BPackageInfo::Parser::_ParseStringList(BStringList* value,
 			if (convertToLowerCase)
 				element.ToLower();
 
+			if (stringValidator != NULL)
+				stringValidator->Validate(element, token.pos);
+			
 			value->Add(element);
 		}
-	} stringParser(value, requireResolvableName, convertToLowerCase);
+	} stringParser(value, requireResolvableName, convertToLowerCase,
+		stringValidator);
 
 	_ParseList(stringParser, true);
 }
@@ -1008,11 +1016,15 @@ BPackageInfo::Parser::_Parse(BPackageInfo* packageInfo)
 				break;
 
 			case B_PACKAGE_INFO_URLS:
-				_ParseStringList(&packageInfo->fURLList);
+				UrlStringValidator stringValidator;
+				_ParseStringList(&packageInfo->fURLList,
+					false, false, &stringValidator);
 				break;
 
 			case B_PACKAGE_INFO_SOURCE_URLS:
-				_ParseStringList(&packageInfo->fSourceURLList);
+				UrlStringValidator stringValidator;
+				_ParseStringList(&packageInfo->fSourceURLList,
+					false, false, &stringValidator);
 				break;
 
 			case B_PACKAGE_INFO_GLOBAL_WRITABLE_FILES:
@@ -1146,4 +1158,66 @@ BPackageInfo::Parser::_IsValidResolvableName(const char* string,
 }
 
 
+/*static*/ bool
+BPackageInfo::Parser::UrlStringValidator::_HasUrlProtocol(const BString& url)
+{
+	return url.StartsWith("http://")
+		|| url.StartsWith("https://")
+		|| url.StartsWith("ftp://")
+		|| url.StartsWith("file:/");
+}
+
+
+/*static*/ bool
+BPackageInfo::Parser::UrlStringValidator::_IsUrlChar(char ch)
+{
+	if ( (ch >= 'A' && ch <= 'Z') ||
+		 (ch >= 'a' && ch <= 'z') ||
+		 (ch >= '0' && ch <= '9') ) {
+		return true;
+	}
+	
+	switch (ch) {
+		case '-':
+		case '.':
+		case '_':
+		case '~':
+		case ':':
+		case '/':
+		case '?':
+		case '#':
+		case '[':
+		case ']':
+		case '@':
+		case '!':
+		case '$':
+		case '&':
+		case '\'':
+		case '(':
+		case ')':
+		case '*':
+		case '+':
+		case ',':
+		case ';':
+		case '=':
+			return true;
+	}
+	
+	return false;
+}
+
+
+void
+BPackageInfo::Parser::UrlStringValidator::Validate(const BString& url, const char *pos)
+{
+	for (int32 i = 0; i < url.Length(); i++) {
+		if (!_IsUrlChar(url.ByteAt(i)))
+			throw ParseError("invalid character in url", pos);
+	}
+	
+	if (!_HasUrlProtocol(url))
+		throw ParseError("missing or unrecognized protocol in url", pos);
+}
+
+
 } // namespace BPackageKit
diff --git a/src/kits/package/PackageInfoParser.h b/src/kits/package/PackageInfoParser.h
index 6824b9e..3cdf82e 100644
--- a/src/kits/package/PackageInfoParser.h
+++ b/src/kits/package/PackageInfoParser.h
@@ -1,5 +1,6 @@
 /*
  * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
+ * Copyright 2016, Andrew Lindesay <apl@lindesay.co.nz>
  * Distributed under the terms of the MIT License.
  */
 #ifndef PACKAGE_INFO_PARSER_H
@@ -31,6 +32,8 @@ public:
 									BPackageResolvableExpression& _expression);
 
 private:
+			struct UrlStringValidator;
+			struct StringValidator;
 			struct ParseError;
 			struct Token;
 			struct ListElementParser;
@@ -74,7 +77,8 @@ private:
 									bool allowSingleNonListElement);
 			void				_ParseStringList(BStringList* value,
 									bool requireResolvableName = false,
-									bool convertToLowerCase = false);
+									bool convertToLowerCase = false,
+									StringValidator* stringValidator = NULL);
 			void				_ParseResolvableList(
 									BObjectList<BPackageResolvable>* value);
 			void				_ParseResolvableExprList(
@@ -152,6 +156,22 @@ struct BPackageInfo::Parser::ListElementParser {
 };
 
 
+struct BPackageInfo::Parser::StringValidator {
+public:
+	virtual void Validate(const BString &string, const char *pos) = 0;
+};
+
+
+struct BPackageInfo::Parser::UrlStringValidator : public BPackageInfo::Parser::StringValidator {
+private:
+	static	bool				_HasUrlProtocol(const BString& url);
+	static	bool				_IsUrlChar(char ch);
+
+public:
+	virtual	void				Validate(const BString &string, const char *pos);
+};
+
+
 } // namespace BPackageKit
 
 
