diff --git a/pkg/apis/policy/v1alpha1/propagation_types.go b/pkg/apis/policy/v1alpha1/propagation_types.go
index fe9316f72ca3..9e9245dca344 100644
--- a/pkg/apis/policy/v1alpha1/propagation_types.go
+++ b/pkg/apis/policy/v1alpha1/propagation_types.go
@@ -68,6 +68,10 @@ type PropagationSpec struct {
 	// +kubebuilder:validation:MinItems=1
 	ResourceSelectors []ResourceSelector `json:"resourceSelectors"`
 
+	// NamespaceSelectors used to select resources.
+	// +optional
+	NamespaceSelectors []NamespaceSelector `json:"namespaceSelectors"`
+
 	// Association tells if relevant resources should be selected automatically.
 	// e.g. a ConfigMap referred by a Deployment.
 	// default false.
@@ -228,6 +232,13 @@ type ResourceSelector struct {
 	LabelSelector *metav1.LabelSelector `json:"labelSelector,omitempty"`
 }
 
+// NamespaceSelector the resource namespace will be selected.
+type NamespaceSelector struct {
+	// A label query over a set of namespaces.
+	// +required
+	LabelSelector *metav1.LabelSelector `json:"labelSelector,omitempty"`
+}
+
 // FieldSelector is a field filter.
 type FieldSelector struct {
 	// A list of field selector requirements.
diff --git a/pkg/detector/compare.go b/pkg/detector/compare.go
index 80c30b239456..4aee6759a211 100644
--- a/pkg/detector/compare.go
+++ b/pkg/detector/compare.go
@@ -33,12 +33,26 @@ func getHighestPriorityPropagationPolicy(policies []*policyv1alpha1.PropagationP
 	var matchedPolicy *policyv1alpha1.PropagationPolicy
 
 	for _, policy := range policies {
+		// any namespace selector matches ?
+		if len(policy.Spec.NamespaceSelectors) != 0 {
+			matched := false
+			for _, ns := range policy.Spec.NamespaceSelectors {
+				if !util.MatchesSelector(GetNamespace(resource.GetNamespace()), ns.LabelSelector) {
+					matched = true
+				}
+			}
+			if !matched {
+				continue
+			}
+		}
+
+		// any resource selector matches ?
 		implicitPriority := util.ResourceMatchSelectorsPriority(resource, policy.Spec.ResourceSelectors...)
 		if implicitPriority <= util.PriorityMisMatch {
 			continue
 		}
-		explicitPriority := policy.ExplicitPriority()
 
+		explicitPriority := policy.ExplicitPriority()
 		if matchedPolicyExplicitPriority < explicitPriority {
 			matchedPolicyImplicitPriority = implicitPriority
 			matchedPolicyExplicitPriority = explicitPriority
diff --git a/pkg/util/selector.go b/pkg/util/selector.go
index 83a15274748f..00c114de0ff8 100644
--- a/pkg/util/selector.go
+++ b/pkg/util/selector.go
@@ -79,17 +79,22 @@ func ResourceSelectorPriority(resource *unstructured.Unstructured, rs policyv1al
 	}
 
 	// case 3: matches with selector
-	var s labels.Selector
-	var err error
-	if s, err = metav1.LabelSelectorAsSelector(rs.LabelSelector); err != nil {
-		// should not happen because all resource selector should be fully validated by webhook.
-		return PriorityMisMatch
+	if MatchesSelector(resource, rs.LabelSelector) {
+		return PriorityMatchLabelSelector
 	}
+	return PriorityMisMatch
+}
 
+func MatchesSelector(resource *unstructured.Unstructured, ls *metav1.LabelSelector) bool {
+	s, err := metav1.LabelSelectorAsSelector(ls)
+	if err != nil {
+		// should not happen because all resource selector should be fully validated by webhook.
+		return false
+	}
 	if s.Matches(labels.Set(resource.GetLabels())) {
-		return PriorityMatchLabelSelector
+		return true
 	}
-	return PriorityMisMatch
+	return false
 }
 
 // ClusterMatches tells if specific cluster matches the affinity.