You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sj...@apache.org on 2026/09/30 21:47:26 UTC

(maven-enforcer) branch master updated: [MENFORCER-433] Add banPropertyPrefix rule to ban Maven properties by configured prefixes (#1039)

This is an automated email from the ASF dual-hosted git repository.

slawekjaranowski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-enforcer.git


The following commit(s) were added to refs/heads/master by this push:
     new d0c87664 [MENFORCER-433] Add banPropertyPrefix rule to ban Maven properties by configured prefixes (#1039)
d0c87664 is described below

commit d0c876646620ae769b7e57aa53d2078f01bc2757
Author: Julio Gómez Díaz <28...@users.noreply.github.com>
AuthorDate: Wed Sep 30 23:47:20 2026 +0200

    [MENFORCER-433] Add banPropertyPrefix rule to ban Maven properties by configured prefixes (#1039)
    
    * Add banPropertyPrefix rule (MENFORCER-433)
    
    New rule that fails the build when any Maven property starts with one
    of the configured banned prefixes. Prefixes are configured through a
    prefixes/prefix list; every entry may also hold several comma-separated
    prefixes. An optional custom message can be provided.
    
    https://issues.apache.org/jira/browse/MENFORCER-433
    
    * Add tests for banPropertyPrefix rule (MENFORCER-433)
    
    https://issues.apache.org/jira/browse/MENFORCER-433
    
    * Add documentation for banPropertyPrefix rule (MENFORCER-433)
    
    https://issues.apache.org/jira/browse/MENFORCER-433
    
    * Use neutral example prefixes in banPropertyPrefix tests and docs
    
    * Add integration tests for banPropertyPrefix rule (MENFORCER-433)
    
    * Use assertThrows and assertDoesNotThrow in TestBanPropertyPrefix
    
    Apply review feedback: replace try/fail/catch blocks with
    assertThrows when an exception is expected and assertDoesNotThrow
    when the rule should pass.
    
    * Fix author name in banPropertyPrefix documentation
    
    * Use ASCII-only author name in banPropertyPrefix docs
    
    * fix: do not log property values in banPropertyPrefix error message
    
    Listing matched property values in the build log can expose
    credentials or tokens when configurable prefixes match sensitive
    properties. Join only the offending property names instead.
    
    * Align ban-property-prefix-fail IT with value-free error message
    
    The IT verification script still asserted the property value in the
    build log while the rule no longer logs it. Check that the offending
    property key is present and that its value is not leaked.
---
 .../enforcer/rules/property/BanPropertyPrefix.java | 112 +++++++++++++++
 .../src/site/markdown/banPropertyPrefix.md.vm      |  77 +++++++++++
 enforcer-rules/src/site/markdown/index.md          |   1 +
 .../rules/property/TestBanPropertyPrefix.java      | 153 +++++++++++++++++++++
 .../ban-property-prefix-fail/invoker.properties    |  18 +++
 .../it/projects/ban-property-prefix-fail/pom.xml   |  63 +++++++++
 .../ban-property-prefix-fail/verify.groovy         |  23 ++++
 .../it/projects/ban-property-prefix-pass/pom.xml   |  63 +++++++++
 .../ban-property-prefix-pass/verify.groovy         |  20 +++
 9 files changed, 530 insertions(+)

diff --git a/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/property/BanPropertyPrefix.java b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/property/BanPropertyPrefix.java
new file mode 100644
index 00000000..82ba23e3
--- /dev/null
+++ b/enforcer-rules/src/main/java/org/apache/maven/enforcer/rules/property/BanPropertyPrefix.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.enforcer.rules.property;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+
+import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
+import org.apache.maven.enforcer.rules.AbstractStandardEnforcerRule;
+import org.apache.maven.project.MavenProject;
+
+/**
+ * This rule checks that no Maven property starts with any of the configured banned prefixes and fails the build if
+ * one or more offending properties are found. Each prefix entry may also contain several prefixes separated by
+ * commas. This is useful to forbid properties that are reserved for other tooling or no longer supported.
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/MENFORCER-433">MENFORCER-433</a>
+ * @since 3.7.0
+ */
+@Named("banPropertyPrefix")
+public final class BanPropertyPrefix extends AbstractStandardEnforcerRule {
+
+    private static final String PREFIX_SEPARATOR = ",";
+
+    private static final String MESSAGE_SEPARATOR = ", ";
+
+    /**
+     * List of prefixes that identify banned properties. Any project property whose name starts with one of these
+     * prefixes makes the rule fail. Each entry may also contain several prefixes separated by commas.
+     */
+    private List<String> prefixes;
+
+    private final MavenProject project;
+
+    @Inject
+    public BanPropertyPrefix(MavenProject project) {
+        this.project = Objects.requireNonNull(project);
+    }
+
+    public void setPrefixes(List<String> prefixes) {
+        this.prefixes = prefixes;
+    }
+
+    public List<String> getPrefixes() {
+        return prefixes;
+    }
+
+    @Override
+    public void execute() throws EnforcerRuleException {
+        Set<String> bannedPrefixes = normalizePrefixes(prefixes);
+        if (bannedPrefixes.isEmpty()) {
+            return;
+        }
+
+        Properties properties = project.getProperties();
+        Set<String> bannedPropertiesFound = properties.stringPropertyNames().stream()
+                .filter(property -> bannedPrefixes.stream().anyMatch(property::startsWith))
+                .collect(Collectors.toCollection(TreeSet::new));
+
+        if (!bannedPropertiesFound.isEmpty()) {
+            String message = getMessage();
+            if (message == null) {
+                message = "Banned properties found (prefixes: " + String.join(MESSAGE_SEPARATOR, bannedPrefixes)
+                        + "): "
+                        + String.join(MESSAGE_SEPARATOR, bannedPropertiesFound);
+            }
+            throw new EnforcerRuleException(message);
+        }
+    }
+
+    static Set<String> normalizePrefixes(List<String> prefixes) {
+        if (prefixes == null) {
+            return new LinkedHashSet<>();
+        }
+        return prefixes.stream()
+                .filter(Objects::nonNull)
+                .flatMap(entry -> Arrays.stream(entry.split(PREFIX_SEPARATOR)))
+                .map(String::trim)
+                .filter(prefix -> !prefix.isEmpty())
+                .collect(Collectors.toCollection(LinkedHashSet::new));
+    }
+
+    @Override
+    public String toString() {
+        return "BanPropertyPrefix[prefixes=" + String.join(MESSAGE_SEPARATOR, normalizePrefixes(prefixes)) + "]";
+    }
+}
diff --git a/enforcer-rules/src/site/markdown/banPropertyPrefix.md.vm b/enforcer-rules/src/site/markdown/banPropertyPrefix.md.vm
new file mode 100644
index 00000000..d0e83a92
--- /dev/null
+++ b/enforcer-rules/src/site/markdown/banPropertyPrefix.md.vm
@@ -0,0 +1,77 @@
+---
+title: Ban Property Prefix
+author:
+  - Julio Gomez Diaz
+date: 2026-09-28
+---
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+# Ban Property Prefix
+
+This rule can enforce that no Maven property starts with any of the configured banned prefixes. It is the
+counterpart of `requireProperty` and is useful to forbid properties that are reserved for other tooling or are no
+longer supported.
+
+The following parameters are supported by this rule:
+
+- **prefixes** - the list of banned property name prefixes. Each entry may also contain several prefixes separated by
+  commas.
+- **message** - an optional message to the user if the rule fails. Default is: "Banned properties found (prefixes:
+  ...): ...".
+
+The rule checks all properties of the current project and fails if any property name starts with one of the
+configured prefixes, listing every offending property.
+
+Sample Plugin Configuration:
+
+```xml
+<project>
+  [...]
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>${project.version}</version>
+        <executions>
+          <execution>
+            <id>ban-property-prefix</id>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <banPropertyPrefix>
+                  <prefixes>
+                    <prefix>secured.system</prefix>
+                    <prefix>internal.build</prefix>
+                  </prefixes>
+                </banPropertyPrefix>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+  [...]
+</project>
+```
diff --git a/enforcer-rules/src/site/markdown/index.md b/enforcer-rules/src/site/markdown/index.md
index da42100a..9cc9f841 100644
--- a/enforcer-rules/src/site/markdown/index.md
+++ b/enforcer-rules/src/site/markdown/index.md
@@ -34,6 +34,7 @@ The following built-in rules ship along with the enforcer plugin:
 - [banDistributionManagement](./banDistributionManagement.html) - enforces that project doesn't have distributionManagement.
 - [banDuplicatePomDependencyVersions](./banDuplicatePomDependencyVersions.html) - enforces that the project doesn't have duplicate declared dependencies.
 - [banDynamicVersions](./banDynamicVersions.html) - bans all dependencies requiring version resolution at build time (i.e. version ranges, placeholders `RELEASE`/`LATEST` or SNAPSHOT versions).
+- [banPropertyPrefix](./banPropertyPrefix.html) - bans properties that start with any of the configured prefixes.
 - [bannedDependencies](./bannedDependencies.html) - enforces that excluded dependencies aren't included.
 - [bannedPlugins](./bannedPlugins.html) - enforces that specific plugins aren't included in the build.
 - [bannedRepositories](./bannedRepositories.html) - enforces to not include banned repositories.
diff --git a/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/property/TestBanPropertyPrefix.java b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/property/TestBanPropertyPrefix.java
new file mode 100644
index 00000000..f171feff
--- /dev/null
+++ b/enforcer-rules/src/test/java/org/apache/maven/enforcer/rules/property/TestBanPropertyPrefix.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.maven.enforcer.rules.property;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Properties;
+
+import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
+import org.apache.maven.project.MavenProject;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.when;
+
+/**
+ * Test class for {@link BanPropertyPrefix}.
+ */
+@ExtendWith(MockitoExtension.class)
+class TestBanPropertyPrefix {
+
+    private static final String BANNED_PREFIX = "secured.system";
+
+    private static final String OTHER_PREFIX = "other.prefix";
+
+    @Mock
+    private MavenProject project;
+
+    @InjectMocks
+    private BanPropertyPrefix rule;
+
+    private Properties properties;
+
+    @Test
+    void shouldFailWhenPropertyWithBannedPrefixExists() {
+        properties.setProperty(BANNED_PREFIX + ".timeout", "5000");
+        when(project.getProperties()).thenReturn(properties);
+        rule.setPrefixes(Collections.singletonList(BANNED_PREFIX));
+
+        EnforcerRuleException e = assertThrows(EnforcerRuleException.class, rule::execute);
+        assertThat(e.getMessage()).contains(BANNED_PREFIX + ".timeout").contains(BANNED_PREFIX);
+    }
+
+    @Test
+    void shouldPassWhenNoPropertyWithBannedPrefixExists() {
+        properties.setProperty(OTHER_PREFIX + ".value", "x");
+        when(project.getProperties()).thenReturn(properties);
+        rule.setPrefixes(Collections.singletonList(BANNED_PREFIX));
+
+        assertDoesNotThrow(rule::execute);
+    }
+
+    @Test
+    void shouldPassWhenProjectHasNoProperties() {
+        when(project.getProperties()).thenReturn(properties);
+        rule.setPrefixes(Collections.singletonList(BANNED_PREFIX));
+
+        assertDoesNotThrow(rule::execute);
+    }
+
+    @Test
+    void shouldMatchAnyConfiguredPrefix() {
+        properties.setProperty(OTHER_PREFIX + ".value", "x");
+        when(project.getProperties()).thenReturn(properties);
+        rule.setPrefixes(Arrays.asList(BANNED_PREFIX, OTHER_PREFIX));
+
+        EnforcerRuleException e = assertThrows(EnforcerRuleException.class, rule::execute);
+        assertThat(e.getMessage()).contains(OTHER_PREFIX + ".value");
+    }
+
+    @Test
+    void shouldListAllOffendingPropertiesSorted() {
+        properties.setProperty(BANNED_PREFIX + ".two", "2");
+        properties.setProperty("keep.me", "ok");
+        properties.setProperty(BANNED_PREFIX + ".one", "1");
+        when(project.getProperties()).thenReturn(properties);
+        rule.setPrefixes(Collections.singletonList(BANNED_PREFIX));
+
+        EnforcerRuleException e = assertThrows(EnforcerRuleException.class, rule::execute);
+        assertThat(e.getMessage()).contains(BANNED_PREFIX + ".one", BANNED_PREFIX + ".two");
+        assertThat(e.getMessage()).containsSubsequence(BANNED_PREFIX + ".one", BANNED_PREFIX + ".two");
+        assertThat(e.getMessage()).doesNotContain("keep.me");
+        assertThat(e.getMessage()).doesNotContain("=1", "=2");
+    }
+
+    @Test
+    void shouldSupportCommaSeparatedEntry() {
+        properties.setProperty(BANNED_PREFIX + ".timeout", "5000");
+        when(project.getProperties()).thenReturn(properties);
+        rule.setPrefixes(Collections.singletonList(BANNED_PREFIX + "," + OTHER_PREFIX));
+
+        EnforcerRuleException e = assertThrows(EnforcerRuleException.class, rule::execute);
+        assertThat(e.getMessage()).contains(BANNED_PREFIX + ".timeout");
+    }
+
+    @Test
+    void shouldIgnoreBlankAndDuplicatePrefixes() {
+        properties.setProperty(OTHER_PREFIX + ".value", "x");
+        when(project.getProperties()).thenReturn(properties);
+        rule.setPrefixes(Arrays.asList(" " + BANNED_PREFIX + " ", " ", " " + BANNED_PREFIX));
+
+        assertDoesNotThrow(rule::execute);
+    }
+
+    @Test
+    void shouldUseCustomMessageWhenConfigured() {
+        properties.setProperty(BANNED_PREFIX + ".timeout", "5000");
+        when(project.getProperties()).thenReturn(properties);
+        rule.setPrefixes(Collections.singletonList(BANNED_PREFIX));
+        rule.setMessage("Custom failure message");
+
+        EnforcerRuleException e = assertThrows(EnforcerRuleException.class, rule::execute);
+        assertThat(e.getMessage()).isEqualTo("Custom failure message");
+    }
+
+    @Test
+    void shouldPassWhenNoPrefixesConfigured() {
+        assertDoesNotThrow(rule::execute);
+    }
+
+    @Test
+    void ruleShouldNotBeCached() {
+        assertThat(rule.getCacheId()).isNull();
+    }
+
+    @org.junit.jupiter.api.BeforeEach
+    void setUp() {
+        properties = new Properties();
+        rule = new BanPropertyPrefix(project);
+    }
+}
diff --git a/maven-enforcer-plugin/src/it/projects/ban-property-prefix-fail/invoker.properties b/maven-enforcer-plugin/src/it/projects/ban-property-prefix-fail/invoker.properties
new file mode 100644
index 00000000..58b6526e
--- /dev/null
+++ b/maven-enforcer-plugin/src/it/projects/ban-property-prefix-fail/invoker.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+invoker.buildResult = failure
diff --git a/maven-enforcer-plugin/src/it/projects/ban-property-prefix-fail/pom.xml b/maven-enforcer-plugin/src/it/projects/ban-property-prefix-fail/pom.xml
new file mode 100644
index 00000000..54d93fed
--- /dev/null
+++ b/maven-enforcer-plugin/src/it/projects/ban-property-prefix-fail/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<project>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.enforcer</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0</version>
+
+  <description>
+    Bans a property by its prefix, must fail because the property exists
+  </description>
+
+  <properties>
+    <secured.system.timeout>5000</secured.system.timeout>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>@project.version@</version>
+        <executions>
+          <execution>
+            <id>test</id>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <banPropertyPrefix>
+                  <prefixes>
+                    <prefix>secured.system</prefix>
+                  </prefixes>
+                </banPropertyPrefix>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/maven-enforcer-plugin/src/it/projects/ban-property-prefix-fail/verify.groovy b/maven-enforcer-plugin/src/it/projects/ban-property-prefix-fail/verify.groovy
new file mode 100644
index 00000000..0fb14753
--- /dev/null
+++ b/maven-enforcer-plugin/src/it/projects/ban-property-prefix-fail/verify.groovy
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+File buildLog = new File( basedir, 'build.log' )
+assert buildLog.text =~ /\[(INFO|ERROR)\] BUILD FAILURE/
+assert buildLog.text.contains( '[ERROR] Rule 0: org.apache.maven.enforcer.rules.property.BanPropertyPrefix failed with message' )
+assert buildLog.text.contains( 'secured.system.timeout' )
+assert !buildLog.text.contains( 'secured.system.timeout=5000' )
diff --git a/maven-enforcer-plugin/src/it/projects/ban-property-prefix-pass/pom.xml b/maven-enforcer-plugin/src/it/projects/ban-property-prefix-pass/pom.xml
new file mode 100644
index 00000000..80157717
--- /dev/null
+++ b/maven-enforcer-plugin/src/it/projects/ban-property-prefix-pass/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<project>
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.maven.its.enforcer</groupId>
+  <artifactId>test</artifactId>
+  <version>1.0</version>
+
+  <description>
+    Bans a property by its prefix, must pass because no property matches
+  </description>
+
+  <properties>
+    <other.prefix.value>ok</other.prefix.value>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>@project.version@</version>
+        <executions>
+          <execution>
+            <id>test</id>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <banPropertyPrefix>
+                  <prefixes>
+                    <prefix>secured.system</prefix>
+                  </prefixes>
+                </banPropertyPrefix>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/maven-enforcer-plugin/src/it/projects/ban-property-prefix-pass/verify.groovy b/maven-enforcer-plugin/src/it/projects/ban-property-prefix-pass/verify.groovy
new file mode 100644
index 00000000..bcbd6ab7
--- /dev/null
+++ b/maven-enforcer-plugin/src/it/projects/ban-property-prefix-pass/verify.groovy
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+File buildLog = new File( basedir, 'build.log' )
+assert buildLog.text.contains( '[INFO] Rule 0: org.apache.maven.enforcer.rules.property.BanPropertyPrefix passed' )