diff --git a/content/xul/templates/src/Makefile.in b/content/xul/templates/src/Makefile.in
--- a/content/xul/templates/src/Makefile.in
+++ b/content/xul/templates/src/Makefile.in
@@ -77,12 +77,13 @@ CPPSRCS		= \
 		$(NULL)
 
 # we don't want the shared lib, but we want to force the creation of a static lib.
 FORCE_STATIC_LIB = 1
 
 include $(topsrcdir)/config/rules.mk
 
 LOCAL_INCLUDES	= -I$(srcdir)/../../../base/src \
-		   -I$(srcdir)/../../content/src \
-		   $(NULL)
+		  -I$(srcdir)/../../content/src \
+		  -I$(srcdir)/../../../../layout/xul/base/src/tree/src \
+		  $(NULL)
 
 DEFINES += -D_IMPL_NS_LAYOUT
diff --git a/content/xul/templates/src/nsXULTreeBuilder.cpp b/content/xul/templates/src/nsXULTreeBuilder.cpp
--- a/content/xul/templates/src/nsXULTreeBuilder.cpp
+++ b/content/xul/templates/src/nsXULTreeBuilder.cpp
@@ -60,16 +60,17 @@
 #include "nsXULContentUtils.h"
 #include "nsXULTemplateBuilder.h"
 #include "nsIXULSortService.h"
 #include "nsTArray.h"
 #include "nsUnicharUtils.h"
 #include "nsINameSpaceManager.h"
 #include "nsIDOMClassInfo.h"
 #include "nsWhitespaceTokenizer.h"
+#include "nsTreeContentView.h"
 
 // For security check
 #include "nsIDocument.h"
 
 /**
  * A XUL template builder that serves as an tree view, allowing
  * (pretty much) arbitrary RDF to be presented in an tree.
  */
@@ -462,16 +463,19 @@ nsXULTreeBuilder::GetSelection(nsITreeSe
 {
     NS_IF_ADDREF(*aSelection = mSelection.get());
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::SetSelection(nsITreeSelection* aSelection)
 {
+    NS_ENSURE_TRUE(!aSelection ||
+                   nsTreeContentView::CanTrustTreeSelection(aSelection),
+                   NS_ERROR_DOM_SECURITY_ERR);
     mSelection = aSelection;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsXULTreeBuilder::GetRowProperties(PRInt32 aIndex, nsISupportsArray* aProperties)
 {
     NS_ENSURE_ARG_POINTER(aProperties);
diff --git a/layout/xul/base/src/tree/public/nsITreeSelection.idl b/layout/xul/base/src/tree/public/nsITreeSelection.idl
--- a/layout/xul/base/src/tree/public/nsITreeSelection.idl
+++ b/layout/xul/base/src/tree/public/nsITreeSelection.idl
@@ -147,8 +147,19 @@ interface nsITreeSelection : nsISupports
   attribute nsITreeColumn currentColumn;
 
   /**
    * The selection "pivot".  This is the first item the user selected as
    * part of a ranged select.
    */
   readonly attribute long shiftSelectPivot;
 };
+
+/**
+ * The following interface is not scriptable and MUST NEVER BE MADE scriptable.
+ * Native treeselections implement it, and we use this to check whether a
+ * treeselection is native (and therefore suitable for use by untrusted content).
+ */
+[uuid(1bd59678-5cb3-4316-b246-31a91b19aabe)]
+interface nsINativeTreeSelection : nsITreeSelection
+{
+  [noscript] void ensureNative();
+};
diff --git a/layout/xul/base/src/tree/src/nsTreeContentView.cpp b/layout/xul/base/src/tree/src/nsTreeContentView.cpp
--- a/layout/xul/base/src/tree/src/nsTreeContentView.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeContentView.cpp
@@ -42,16 +42,17 @@
 #include "nsTreeContentView.h"
 #include "nsChildIterator.h"
 #include "nsIDOMHTMLOptionElement.h"
 #include "nsIDOMHTMLOptGroupElement.h"
 #include "nsIDOMClassInfo.h"
 #include "nsIEventStateManager.h"
 #include "nsINodeInfo.h"
 #include "nsIXULSortService.h"
+#include "nsContentUtils.h"
 
 // A content model view implementation for the tree.
 
 #define ROW_FLAG_CONTAINER      0x01
 #define ROW_FLAG_OPEN           0x02
 #define ROW_FLAG_EMPTY          0x04
 #define ROW_FLAG_SEPARATOR      0x08
 
@@ -189,19 +190,32 @@ nsTreeContentView::GetRowCount(PRInt32* 
 NS_IMETHODIMP
 nsTreeContentView::GetSelection(nsITreeSelection** aSelection)
 {
   NS_IF_ADDREF(*aSelection = mSelection);
 
   return NS_OK;
 }
 
+PRBool
+nsTreeContentView::CanTrustTreeSelection(nsISupports* aValue)
+{
+  // Untrusted content is only allowed to specify known-good views
+  if (nsContentUtils::IsCallerTrustedForWrite())
+    return PR_TRUE;
+  nsCOMPtr<nsINativeTreeSelection> nativeTreeSel = do_QueryInterface(aValue);
+  return nativeTreeSel && NS_SUCCEEDED(nativeTreeSel->EnsureNative());
+}
+
 NS_IMETHODIMP
 nsTreeContentView::SetSelection(nsITreeSelection* aSelection)
 {
+  NS_ENSURE_TRUE(!aSelection || CanTrustTreeSelection(aSelection),
+                 NS_ERROR_DOM_SECURITY_ERR);
+
   mSelection = aSelection;
   if (!mSelection || !mUpdateSelection)
     return NS_OK;
 
   mUpdateSelection = PR_FALSE;
 
   mSelection->SetSelectEventsSuppressed(PR_TRUE);
   for (PRUint32 i = 0; i < mRows.Length(); ++i) {
diff --git a/layout/xul/base/src/tree/src/nsTreeContentView.h b/layout/xul/base/src/tree/src/nsTreeContentView.h
--- a/layout/xul/base/src/tree/src/nsTreeContentView.h
+++ b/layout/xul/base/src/tree/src/nsTreeContentView.h
@@ -77,16 +77,18 @@ class nsTreeContentView : public nsINati
                                       nsIContent* aContent2,
                                       PRInt32 aStateMask);
     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
     NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
 
+    static PRBool CanTrustTreeSelection(nsISupports* aValue);
+
   protected:
     // Recursive methods which deal with serializing of nested content.
     void Serialize(nsIContent* aContent, PRInt32 aParentIndex, PRInt32* aIndex,
                    nsTArray<Row*>& aRows);
 
     void SerializeItem(nsIContent* aContent, PRInt32 aParentIndex,
                        PRInt32* aIndex, nsTArray<Row*>& aRows);
 
diff --git a/layout/xul/base/src/tree/src/nsTreeSelection.cpp b/layout/xul/base/src/tree/src/nsTreeSelection.cpp
--- a/layout/xul/base/src/tree/src/nsTreeSelection.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeSelection.cpp
@@ -275,16 +275,17 @@ NS_IMPL_CYCLE_COLLECTION_2(nsTreeSelecti
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsTreeSelection)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsTreeSelection)
 
 DOMCI_DATA(TreeSelection, nsTreeSelection)
 
 // QueryInterface implementation for nsBoxObject
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsTreeSelection)
   NS_INTERFACE_MAP_ENTRY(nsITreeSelection)
+  NS_INTERFACE_MAP_ENTRY(nsINativeTreeSelection)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(TreeSelection)
 NS_INTERFACE_MAP_END
 
 NS_IMETHODIMP nsTreeSelection::GetTree(nsITreeBoxObject * *aTree)
 {
   NS_IF_ADDREF(*aTree = mTree);
   return NS_OK;
diff --git a/layout/xul/base/src/tree/src/nsTreeSelection.h b/layout/xul/base/src/tree/src/nsTreeSelection.h
--- a/layout/xul/base/src/tree/src/nsTreeSelection.h
+++ b/layout/xul/base/src/tree/src/nsTreeSelection.h
@@ -45,26 +45,29 @@
 #include "nsITreeSelection.h"
 #include "nsITreeColumns.h"
 #include "nsITimer.h"
 #include "nsCycleCollectionParticipant.h"
 
 class nsITreeBoxObject;
 struct nsTreeRange;
 
-class nsTreeSelection : public nsITreeSelection
+class nsTreeSelection : public nsINativeTreeSelection
 {
 public:
   nsTreeSelection(nsITreeBoxObject* aTree);
   ~nsTreeSelection();
    
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_CLASS(nsTreeSelection)
   NS_DECL_NSITREESELECTION
 
+  // nsINativeTreeSelection: Untrusted code can use us
+  NS_IMETHOD EnsureNative() { return NS_OK; }
+
   friend struct nsTreeRange;
 
 protected:
   nsresult FireOnSelectHandler();
   static void SelectCallback(nsITimer *aTimer, void *aClosure);
 
 protected:
   // Members
