Bug 693940: Restrict SVG-as-an-image to being able to load (local) URIs that have either the URI_INHERITS_SECURITY_CONTEXT or URI_LOADABLE_BY_SUBSUMERS flags. r=bz

This commit is contained in:
Daniel Holbert 2011-11-07 13:45:42 -08:00
parent 13ab90286a
commit 8b0d1d45e6
4 changed files with 115 additions and 14 deletions

View File

@ -51,6 +51,17 @@
NS_IMPL_ISUPPORTS1(nsDataDocumentContentPolicy, nsIContentPolicy)
// Helper method for ShouldLoad()
// Checks a URI for the given flags. Returns true if the URI has the flags,
// and false if not (or if we weren't able to tell).
static bool
HasFlags(nsIURI* aURI, PRUint32 aURIFlags)
{
bool hasFlags;
nsresult rv = NS_URIChainHasFlags(aURI, aURIFlags, &hasFlags);
return NS_SUCCEEDED(rv) && hasFlags;
}
NS_IMETHODIMP
nsDataDocumentContentPolicy::ShouldLoad(PRUint32 aContentType,
nsIURI *aContentLocation,
@ -87,21 +98,26 @@ nsDataDocumentContentPolicy::ShouldLoad(PRUint32 aContentType,
}
if (doc->IsBeingUsedAsImage()) {
// Allow local resources for SVG-as-an-image documents, but disallow
// everything else, to prevent data leakage
bool hasFlags;
nsresult rv = NS_URIChainHasFlags(aContentLocation,
nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
&hasFlags);
if (NS_FAILED(rv) || !hasFlags) {
// resource is not local (or we couldn't tell) - reject!
// We only allow SVG images to load content from URIs that are local and
// also satisfy one of the following conditions:
// - URI inherits security context, e.g. data URIs
// OR
// - URI loadable by subsumers, e.g. moz-filedata URIs
// Any URI that doesn't meet these requirements will be rejected below.
if (!HasFlags(aContentLocation,
nsIProtocolHandler::URI_IS_LOCAL_RESOURCE) ||
(!HasFlags(aContentLocation,
nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT) &&
!HasFlags(aContentLocation,
nsIProtocolHandler::URI_LOADABLE_BY_SUBSUMERS))) {
*aDecision = nsIContentPolicy::REJECT_TYPE;
// report error, if we can.
// Report error, if we can.
if (node) {
nsIPrincipal* requestingPrincipal = node->NodePrincipal();
nsRefPtr<nsIURI> principalURI;
rv = requestingPrincipal->GetURI(getter_AddRefs(principalURI));
nsresult rv =
requestingPrincipal->GetURI(getter_AddRefs(principalURI));
if (NS_SUCCEEDED(rv) && principalURI) {
nsScriptSecurityManager::ReportError(
nsnull, NS_LITERAL_STRING("CheckSameOriginError"), principalURI,
@ -112,8 +128,8 @@ nsDataDocumentContentPolicy::ShouldLoad(PRUint32 aContentType,
doc->GetDocumentURI()) {
// Check for (& disallow) recursive image-loads
bool isRecursiveLoad;
rv = aContentLocation->EqualsExceptRef(doc->GetDocumentURI(),
&isRecursiveLoad);
nsresult rv = aContentLocation->EqualsExceptRef(doc->GetDocumentURI(),
&isRecursiveLoad);
if (NS_FAILED(rv) || isRecursiveLoad) {
NS_WARNING("Refusing to recursively load image");
*aDecision = nsIContentPolicy::REJECT_TYPE;

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<!-- This test checks to be sure we can render SVG-as-an-image
from a MozBlobBuilder-generated 'moz-filedata' URI. -->
<html class="reftest-wait">
<head>
<script>
function go() {
// Generate a moz-filedata URL encoding of an SVG document
var filedataURL = generateMozFiledataURL();
// Tell our img element to render the URL
var img = document.getElementsByTagName("img")[0]
img.src = filedataURL;
// Once our img loads, take reftest snapshot.
img.addEventListener("load", function() {
document.documentElement.removeAttribute("class");
});
}
// Helper function -- returns a moz-filedata URL representing a
// 100x100 fully-lime SVG document.
function generateMozFiledataURL() {
var blobBuilder = new self.MozBlobBuilder;
var svg =
'<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">' +
'<rect height="100%" width="100%" fill="lime"/>' +
'</svg>';
blobBuilder.append(svg);
return self.URL.createObjectURL(blobBuilder.getBlob("image/svg+xml"));
}
</script>
</head>
<body onload="go()">
<img src="">
</body>
</html>

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<!-- This test checks to be sure we allow MozBlobBuilder-generated
'moz-filedata' URIs *inside of* SVG-as-an-image. -->
<html class="reftest-wait">
<head>
<script>
function go() {
// Generate a moz-filedata URL encoding of an SVG document
var filedataURL = generateMozFiledataURL();
// Now generate a data URI, containing our moz-filedata URI
var outerSVG =
'<svg xmlns="http://www.w3.org/2000/svg" ' +
'xmlns:xlink="http://www.w3.org/1999/xlink" ' +
'width="100" height="100">' +
'<image height="100" width="100" ' +
'xlink:href="' + filedataURL + '"/>' +
'</svg>';
// Tell our img element to render the URL
var img = document.getElementsByTagName("img")[0]
img.src = "data:image/svg+xml," + outerSVG;
// Once our img loads, take reftest snapshot.
img.addEventListener("load", function() {
document.documentElement.removeAttribute("class");
});
}
// Helper function -- returns a moz-filedata URL representing a
// 100x100 fully-lime SVG document.
function generateMozFiledataURL() {
var blobBuilder = new self.MozBlobBuilder;
var svg =
'<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">' +
'<rect height="100%" width="100%" fill="lime"/>' +
'</svg>';
blobBuilder.append(svg);
return self.URL.createObjectURL(blobBuilder.getBlob("image/svg+xml"));
}
</script>
</head>
<body onload="go()">
<img src="">
</body>
</html>

View File

@ -55,6 +55,8 @@ fails == canvas-drawImage-slice-1b.html lime100x100-ref.html # XXX all edges fuz
random == img-and-image-1.html img-and-image-1-ref.svg # bug 645267
# More complex <img> tests
== img-blobBuilder-1.html lime100x100-ref.html
== img-blobBuilder-2.html lime100x100-ref.html
== img-content-outside-viewBox-1.html img-content-outside-viewBox-1-ref.html
== img-dyn-1.html img-dyn-1-ref.html
== img-foreignObject-1.html lime100x100-ref.html
@ -120,11 +122,11 @@ random == img-and-image-1.html img-and-image-1-ref.svg # bug 645267
# tests for external resources vs. data URIs in SVG as an image
== svg-image-datauri-1.html lime100x100.svg
HTTP == svg-image-datauri-1.html lime100x100.svg
fails-if(Android) == svg-image-external-1.html lime100x100.svg
== svg-image-external-1.html blue100x100.svg
HTTP == svg-image-external-1.html blue100x100.svg
== svg-stylesheet-datauri-1.html lime100x100.svg
HTTP == svg-stylesheet-datauri-1.html lime100x100.svg
random == svg-stylesheet-external-1.html lime100x100.svg # see bug 629885 comment 9
== svg-stylesheet-external-1.html blue100x100.svg
HTTP == svg-stylesheet-external-1.html blue100x100.svg
# test that :visited status is ignored in image documents