Comment on attachment 578799
WIP - experimental prototype
Review of attachment 578799:
-----------------------------------------------------------------
Drive by comments. These should definitely not be taken as exhaustive.
Looks like this doesn't attempt to cover plugins? Also looks like this doesn't attempt to deal with scripts? I expect those are going to be a significant amount of work.
Reading the spec and the proto-patch here, I think storing the sandbox flags on both the docshell and the document is going to be a source of great pain. I think you're going to want one canonical set of sandbox flags (on the outer window, perhaps?).
Also, you really should request f? from a specific person. I gave an f-, but at this stage that is to be expected.
@@ +1864,5 @@
> + *
> + * @param aAttribute the value of the sandbox attribute as an nsIDOMDOMSettableTokenList
> + * @return the set of flags
> + */
> + static PRUint32 ParseSandboxAttributeToFlags(nsIDOMDOMSettableTokenList * aAttribute);
80 character lines please.
::: content/base/public/nsIDocument.h
@@ +462,5 @@
> }
>
> /**
> + * Set the sandbox flags for this document. This should only happen at
> + * at document load, the flags are immutable after being set at load time.
Can you assert that this is being called during load? (by checking for READYSTATE_LOADING or something?)
@@ +471,5 @@
> + mSandboxFlags = aSandboxFlags;
> + }
> +
> + /**
> + * Get the sandox flags for this document
sandbox
@@ +1786,5 @@
>
> + // The sandbox flags on the document. These reflect the value of the sandbox attribute of the
> + // associated IFRAME or CSP-protectable content, if existent. These are set at load time and
> + //are immutable - see nsDocShell.idl for the possible flags
> + PRUint32 mSandboxFlags;
nsIDocument needs an IID bump for this.
::: content/base/src/nsContentUtils.cpp
@@ +699,5 @@
> + * @param aAttribute the value of the sandbox attribute as an nsIDOMDOMSettableTokenList
> + * @return the set of flags
> + */
> +PRUint32
> +nsContentUtils::ParseSandboxAttributeToFlags(nsIDOMDOMSettableTokenList * aAttribute)
You should rewrite this function to use nsCharSeparatedTokenizer<nsContentUtils::IsHTMLWhitespace>. As it is it'll match things like "allow-scriptsallow-same-origin" which are not allowed per spec.
in nsContentUtils.h and changing the existing users in the tree.
@@ +702,5 @@
> +PRUint32
> +nsContentUtils::ParseSandboxAttributeToFlags(nsIDOMDOMSettableTokenList * aAttribute)
> +{
> + // TODO: how to handle errors in this function ? if we're here, something has a sandbox
> + // attribute set and expects content to be sandboxed... perhaps consider failing closed ??
You can do this one of three ways:
1) Return an explicit nsresult and pass the flags back in a PRUint32 outparam.
2) Return a clearly bogus value for failure (e.g. -1)
3) Fail closed (-1 effectively does this if somebody forgets the check).
What in here is fallible though? Simple tokenization and comparison should be infallible, I think.
@@ +711,5 @@
> + out |= nsIDocShell::SANDBOX_FLAGS_SANDBOXED;
> +
> + bool allowed = false;
> +
> + // TODO: should i try to use atoms even though Contains wants a string ?
Yes, you should use the atoms and do 'if (atom->Equals(token)) ...'
::: content/base/src/nsFrameLoader.cpp
@@ +506,5 @@
> + // and it may not be - maybe fail closed (all restrictions) ???
> + }
> +
> + if (parentSandboxFlags) {
> + // do the intersection with the current flags in the docshell!
I didn't look at this too closely, I assume that permissions can only be removed, not added, for children?
Does this check avoid doing form validation and the like when sandboxed? (I think it does). You'll want tests for that.
::: content/html/content/src/nsHTMLIFrameElement.cpp
@@ +306,5 @@
> + bool aNotify)
> +{
> + if (aName == nsGkAtoms::sandbox && aNameSpaceID == kNameSpaceID_None) {
> + // parse the new value of the sandbox attribute, and if we have a docshell
> + // set its sandbox flags appropriately
When is a sandbox attribute set supposed to take effect?
"While the sandbox attribute is specified, the iframe element's nested browsing context must have the flags given in the following list set. In addition, any browsing contexts nested within an iframe, either directly or indirectly, must have all the flags set on them as were set on the iframe's Document's browsing context when the iframe's Document was created."
So it sounds like a sandbox attr change should only take effect for the next document in the iframe. Setting them on the docshell immediately means they'll take affect for future subloads even on the same document, right? You'll want either tests to show that this isn't the case or to change the code so that it isn't (and then tests :-)).
Please order intializers in the same order variables are declared (doing otherwise will give warnings on gcc).
@@ +2887,5 @@
> + // If our document is sandboxed, we need to do some extra checks
> + PRUint32 sandboxFlags = 0;
> +
> + if (mContentViewer) {
> + nsCOMPtr<nsIDocument> doc = mContentViewer->GetDocument();
No need to use an nsCOMPtr here. nsIDocument* doc is fine.
Somebody who understand docshell (read bz, smaug) should look at this stuff. In my five minutes of looking at docshell it looks like this logic might fit better in CanAccessItem.
I think this would be easier to follow with one callsite whose final parameter varies.
::: docshell/base/nsIDocShell.idl
@@ +561,5 @@
> + * They are only used when loading new content, sandbox flags are also immutably set on the document
> + * when it is loaded. The sandbox flags of a document depend on the sandbox flags on its docshell
> + * and of its parent document, if any.
> + */
> + attribute unsigned long sandboxFlags;
nsIDocShell needs an IID bump for this.
@@ +576,5 @@
> +
> + /**
> + * The content is sandboxed but allowed to have its natural domain.
> + */
> + const unsigned long SANDBOX_FLAGS_ALLOW_SAME_DOMAIN = 0x4;
please make this ALLOW_SAME_ORIGIN so that the terminology is consistent.
Comment on attachment 578799
WIP - experimental prototype
Review of attachment 578799: ------- ------- ------- ------- ------- ------- ------- ------- --
-------
Drive by comments. These should definitely not be taken as exhaustive.
Looks like this doesn't attempt to cover plugins? Also looks like this doesn't attempt to deal with scripts? I expect those are going to be a significant amount of work.
We should detect the situation called out in the first warning (and maybe the second too?) at http:// www.whatwg. org/specs/ web-apps/ current- work/multipage/ the-iframe- element. html#attr- iframe- sandbox and send a warning to the error console.
Reading the spec and the proto-patch here, I think storing the sandbox flags on both the docshell and the document is going to be a source of great pain. I think you're going to want one canonical set of sandbox flags (on the outer window, perhaps?).
Also, you really should request f? from a specific person. I gave an f-, but at this stage that is to be expected.
Finally, this is going to need lots of tests ...
::: content/ base/public/ nsContentUtils. h er(nsIPrincipal * aLoadingPrincipal, lank,
@@ +1838,5 @@
> static bool SetUpChannelOwn
> nsIChannel* aChannel,
> nsIURI* aURI,
> + bool aSetUpForAboutB
> + bool aForceOwner);
You could make aForceOwner default to false here.
@@ +1864,5 @@ leTokenList ributeToFlags( nsIDOMDOMSettab leTokenList * aAttribute);
> + *
> + * @param aAttribute the value of the sandbox attribute as an nsIDOMDOMSettab
> + * @return the set of flags
> + */
> + static PRUint32 ParseSandboxAtt
80 character lines please.
::: content/ base/public/ nsIDocument. h
@@ +462,5 @@
> }
>
> /**
> + * Set the sandbox flags for this document. This should only happen at
> + * at document load, the flags are immutable after being set at load time.
Can you assert that this is being called during load? (by checking for READYSTATE_LOADING or something?)
@@ +471,5 @@
> + mSandboxFlags = aSandboxFlags;
> + }
> +
> + /**
> + * Get the sandox flags for this document
sandbox
@@ +1786,5 @@
>
> + // The sandbox flags on the document. These reflect the value of the sandbox attribute of the
> + // associated IFRAME or CSP-protectable content, if existent. These are set at load time and
> + //are immutable - see nsDocShell.idl for the possible flags
> + PRUint32 mSandboxFlags;
nsIDocument needs an IID bump for this.
::: content/ base/src/ nsContentUtils. cpp leTokenList ::ParseSandboxA ttributeToFlags (nsIDOMDOMSetta bleTokenList * aAttribute)
@@ +699,5 @@
> + * @param aAttribute the value of the sandbox attribute as an nsIDOMDOMSettab
> + * @return the set of flags
> + */
> +PRUint32
> +nsContentUtils
You should rewrite this function to use nsCharSeparated Tokenizer< nsContentUtils: :IsHTMLWhitespa ce>. As it is it'll match things like "allow- scriptsallow- same-origin" which are not allowed per spec.
I'd give extra points for putting a
typedef nsCharSeparated Tokenizer< nsContentUtils: :IsHTMLWhitespa ce> HTMLSplitOnSpac esTokenizer (or something)
in nsContentUtils.h and changing the existing users in the tree.
@@ +702,5 @@ ::ParseSandboxA ttributeToFlags (nsIDOMDOMSetta bleTokenList * aAttribute)
> +PRUint32
> +nsContentUtils
> +{
> + // TODO: how to handle errors in this function ? if we're here, something has a sandbox
> + // attribute set and expects content to be sandboxed... perhaps consider failing closed ??
You can do this one of three ways:
1) Return an explicit nsresult and pass the flags back in a PRUint32 outparam.
2) Return a clearly bogus value for failure (e.g. -1)
3) Fail closed (-1 effectively does this if somebody forgets the check).
What in here is fallible though? Simple tokenization and comparison should be infallible, I think.
@@ +711,5 @@ :SANDBOX_ FLAGS_SANDBOXED ;
> + out |= nsIDocShell:
> +
> + bool allowed = false;
> +
> + // TODO: should i try to use atoms even though Contains wants a string ?
Yes, you should use the atoms and do 'if (atom-> Equals( token)) ...'
::: content/ base/src/ nsDocument. cpp nsIDocShell> docShell = do_QueryInterfa ce(aContainer) ; >GetSandboxFlag s(&mSandboxFlag s); SUCCESS( rv, rv);
@@ +2394,5 @@
> + nsCOMPtr<
> +
> + if (docShell) {
> + nsresult rv = docShell-
> + NS_ENSURE_
ugh tabs
::: content/ base/src/ nsFrameLoader. cpp lags) {
@@ +506,5 @@
> + // and it may not be - maybe fail closed (all restrictions) ???
> + }
> +
> + if (parentSandboxF
> + // do the intersection with the current flags in the docshell!
I didn't look at this too closely, I assume that permissions can only be removed, not added, for children?
e.g. if I have:
- Top Level Doc (A)
- Sandboxed Iframe (B)
- Sandboxed Iframe (C)
And B has permissions 1 and 2 there's no way for C to have permission 3, right?
::: content/ html/content/ src/nsHTMLFormE lement. cpp Flags() ; :SANDBOX_ FLAGS_SANDBOXED ) || :SANDBOX_ FLAGS_ALLOW_ FORM_SUBMIT) )
@@ +691,5 @@
> + PRUint32 sandboxFlags = doc->GetSandbox
> +
> + if (!(sandboxFlags & nsIDocShell:
> + (sandboxFlags & nsIDocShell:
> + rv = DoSubmit(aEvent);
Does this check avoid doing form validation and the like when sandboxed? (I think it does). You'll want tests for that.
::: content/ html/content/ src/nsHTMLIFram eElement. cpp
@@ +306,5 @@
> + bool aNotify)
> +{
> + if (aName == nsGkAtoms::sandbox && aNameSpaceID == kNameSpaceID_None) {
> + // parse the new value of the sandbox attribute, and if we have a docshell
> + // set its sandbox flags appropriately
When is a sandbox attribute set supposed to take effect?
"While the sandbox attribute is specified, the iframe element's nested browsing context must have the flags given in the following list set. In addition, any browsing contexts nested within an iframe, either directly or indirectly, must have all the flags set on them as were set on the iframe's Document's browsing context when the iframe's Document was created."
So it sounds like a sandbox attr change should only take effect for the next document in the iframe. Setting them on the docshell immediately means they'll take affect for future subloads even on the same document, right? You'll want either tests to show that this isn't the case or to change the code so that it isn't (and then tests :-)).
::: docshell/ base/nsDocShell .cpp ed(false) , oadHandler( false), (false) , r(false) ,
@@ +755,5 @@
> mIsBeingDestroy
> mIsExecutingOnL
> mIsPrintingOrPP
> + mSavingOldViewe
> + mSandboxFlags(0)
Please order intializers in the same order variables are declared (doing otherwise will give warnings on gcc).
@@ +2887,5 @@ nsIDocument> doc = mContentViewer- >GetDocument( );
> + // If our document is sandboxed, we need to do some extra checks
> + PRUint32 sandboxFlags = 0;
> +
> + if (mContentViewer) {
> + nsCOMPtr<
No need to use an nsCOMPtr here. nsIDocument* doc is fine.
@@ +2944,5 @@
> + parentAsItem = tmp;
> + }
> + }
> + }
> +
Somebody who understand docshell (read bz, smaug) should look at this stuff. In my five minutes of looking at docshell it looks like this logic might fit better in CanAccessItem.
@@ +4996,5 @@ :GetSandboxFlag s(PRUint32 *aSandboxFlags) ARG_POINTER( aSandboxFlags) ;
> +
> +NS_IMETHODIMP
> +nsDocShell:
> +{
> + NS_ENSURE_
Usually we don't bother with this. If you pass in null, you crash.
@@ +8201,5 @@ Flags() ; :SANDBOX_ FLAGS_SANDBOXED ) {
> + PRUint32 sandboxFlags = 0;
> + sandboxFlags = doc->GetSandbox
> + if (sandboxFlags & nsIDocShell:
> + return NS_ERROR_FAILURE;
> + }
Same comment as above about somebody who knows docshell looking at this.
@@ +8996,5 @@ :SetUpChannelOw ner(ownerPrinci pal, channel, aURI, true, true); :SetUpChannelOw ner(ownerPrinci pal, channel, aURI, true, false);
> + nsContentUtils:
> + }
> + else {
> + nsContentUtils:
> + }
I think this would be easier to follow with one callsite whose final parameter varies.
::: docshell/ base/nsIDocShel l.idl
@@ +561,5 @@
> + * They are only used when loading new content, sandbox flags are also immutably set on the document
> + * when it is loaded. The sandbox flags of a document depend on the sandbox flags on its docshell
> + * and of its parent document, if any.
> + */
> + attribute unsigned long sandboxFlags;
nsIDocShell needs an IID bump for this.
@@ +576,5 @@ FLAGS_ALLOW_ SAME_DOMAIN = 0x4;
> +
> + /**
> + * The content is sandboxed but allowed to have its natural domain.
> + */
> + const unsigned long SANDBOX_
please make this ALLOW_SAME_ORIGIN so that the terminology is consistent.
::: dom/interfaces/ html/nsIDOMHTML IFrameElement. idl leTokenList sandbox;
@@ +68,5 @@
> readonly attribute nsIDOMDocument contentDocument;
> readonly attribute nsIDOMWindow contentWindow;
> +
> + // HTML5 sandbox attribute
> + readonly attribute nsIDOMDOMSettab
Needs an IID bump.