elharo opened a new issue, #380:
URL: https://github.com/apache/maven-help-plugin/issues/380

   ### Affected version
   
   HEAD
   
   ### Bug description
   
   Bug Analysis for maven-help-plugin
   
   HIGH Severity
   1. EffectivePomMojo.cleanModel() mutates the live project's Model in-place 
(EffectivePomMojo.java:210-213)
   private static void cleanModel(Model pom) {
       Properties properties = new SortedProperties();
       properties.putAll(pom.getProperties());
       pom.setProperties(properties);  // <-- modifies the real project model
   }
   Called from writeEffectivePom() at line 182 on project.getModel(). This 
permanently replaces the project's Properties object with a SortedProperties 
instance, altering property iteration order for the remainder of the build. If 
any subsequent mojo or plugin depends on insertion order or object identity of 
Properties, it will break. This is a data corruption side effect in what should 
be a read-only display operation.
   2. EffectiveSettingsMojo mutates the original Settings object when 
showPasswords=true (EffectiveSettingsMojo.java:87-94)
   
   ```
   if (showPasswords) {
       copySettings = settings;  // <-- uses original, not a copy
   } else {
       copySettings = copySettings(settings);
       ...
   }
   // ...
   writeEffectiveSettings(copySettings, writer); // calls cleanSettings() which 
modifies profiles
   ```
   
   When -DshowPasswords=true, the original Maven Settings object is used 
directly. writeEffectiveSettings -> cleanSettings() then replaces each 
profile's Properties with a SortedProperties instance (same pattern as bug #1). 
This mutates the global shared settings object, corrupting state for subsequent 
lifecycle steps.
   3. DescribeMojo.lookupPluginDescriptor() error message references null mojo 
fields instead of PluginInfo (DescribeMojo.java:333-338)
   throw new MojoExecutionException(
       "Error retrieving plugin descriptor for:" + LS + LS + "groupId: '"
           + groupId + "'" + LS + "artifactId: '" + artifactId + "'" + LS + 
"version: '" + version + "'" + LS + LS, e);
   When the plugin was specified by prefix (e.g., -Dplugin=help), the mojo 
fields groupId, artifactId, version are all null. The method parameter 
PluginInfo pi contains the actual values (pi.getGroupId(), etc.) but the error 
message ignores them. Output: groupId: 'null'\nartifactId: 'null'\nversion: 
'null' — a misleading error that defeats debugging.
   MEDIUM Severity
   4. AllProfilesMojo.addProjectPomProfiles() uses parent context for active 
profiles (AllProfilesMojo.java:153-156)
   if (project.getActiveProfiles() != null) {
       for (Profile profile : project.getActiveProfiles()) {
           activeProfiles.put(profile.getId(), profile);
       }
   }
   project = project.getParent();  // walks up to parent
   When the loop reaches a parent POM, project.getActiveProfiles() returns 
profiles active in the parent's build context. These may not be active for the 
child project (different JDK, OS, properties). The output will incorrectly mark 
parent profiles as active when they aren't applicable to the child.
   5. EffectiveSettingsMojo.copySettings() doesn't deep-copy profiles 
(EffectiveSettingsMojo.java:156-198)
   Only servers and proxies are manually deep-copied. The profiles list is 
shared with the original via SettingsUtils.copySettings(). While 
hidePasswords() only targets servers/proxies, profiles can also contain 
sensitive data (passwords in profile properties) that could be exposed if the 
original settings object is later queried expecting the copy to be isolated.
   6. ListDependencyTypesMojo, ListLifecyclePhasesMojo, ListPackagingMojo write 
to console AND file simultaneously (e.g., ListDependencyTypesMojo.java:95-96)
   getLog().info(LS + "Maven Dependency Types defined:" + LS + LS + 
descriptionBuffer);
   writeFile(output, descriptionBuffer);  // always called, even when output is 
null
   These three mojos always write to the log via getLog().info(...) and 
unconditionally call writeFile(output, ...) (which is a no-op when output is 
null). Every other mojo (ActiveProfilesMojo, AllProfilesMojo, DescribeMojo, 
SystemMojo) uses if (output != null) { ... } else { getLog().info(...); }. The 
dual-write is inconsistent and means content is always printed to console even 
when writing to a file. They also don't prepend the "Generated by Maven Help 
Plugin" header that ActiveProfilesMojo and SystemMojo add.
   LOW Severity
   7. DescribeMojo.toLines() delegates to generated HelpMojo via fragile 
reflection (DescribeMojo.java:747-778)
   Method m = HelpMojo.class.getDeclaredMethod("toLines", String.class, 
Integer.TYPE, Integer.TYPE, Integer.TYPE);
   m.setAccessible(true);
   List<String> output = (List<String>) m.invoke(HelpMojo.class, text, indent, 
indentSize, lineLength);
   HelpMojo is generated by maven-plugin-tools at compile time (in 
target/generated-sources/). It IS available at runtime, but this reflection is 
fragile: any change in the generated code's toLines signature silently breaks 
all describe output formatting. The HelpMojo.toLines internally calls repeat() 
with new StringBuilder(repeat * str.length()) — a classic integer overflow risk 
that could throw NegativeArraySizeException (caught, but still a brittle chain).
   8. AbstractHelpMojo.LS uses System.getProperty("line.separator") 
(AbstractHelpMojo.java:55)
   protected static final String LS = System.getProperty("line.separator");
   Should use System.lineSeparator() (Java 7+), which falls back to "\n" if the 
property is missing. Additionally, DescribeMojoTest inconsistently uses both 
System.getProperty("line.separator") (line 88) and System.lineSeparator() (line 
110).
   9. SortedProperties uses raw types (AbstractEffectiveMojo.java:147-148)
   List list = new ArrayList(keynames);
   Collections.sort(list);
   The @SuppressWarnings({"rawtypes", "unchecked"}) annotation masks the issue 
rather than using List<Object>.
   10. AbstractHelpMojo.getAetherArtifact() uses deprecated 
Artifact.LATEST_VERSION (AbstractHelpMojo.java:147)
   version = Artifact.LATEST_VERSION;
   Deprecated in favor of null (which means "latest") in the Aether API.
   11. EffectivePomMojo encoding fallback can return null 
(EffectivePomMojo.java:111)
   String encoding = output != null ? project.getModel().getModelEncoding() : 
System.getProperty("file.encoding");
   System.getProperty("file.encoding") can theoretically return null.
   12. AllProfilesMojo — settings profiles added to allProfilesByIds but never 
tracked for active status (AllProfilesMojo.java:167-173)
   addSettingsProfiles() only populates allProfilesByIds, never 
activeProfilesByIds. Active detection relies on project.getActiveProfiles() 
which may or may not include converted settings profiles depending on Maven 
version and activation mechanisms. This can under-report active settings 
profiles.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to