Rule in wrong profile/language after SQ 7.9 to 8.9 and plugin upgrade

Hello,

The SpotBugs plugin has been modified to remove (among other things) the usage of the deprecated org.sonar.api.profiles.ProfileDefinition to make it compatible with SonarQube 9.

So for instance:

public class FindbugsSecurityJspProfile extends ProfileDefinition

Was changed to:

public class FindbugsSecurityJspProfile implements BuiltInQualityProfilesDefinition

The changes are here

Now we’ve got an error report from a user upgrading from SonarQube 7.9.5 (SpotBugs plugin 3.11.1) to 8.9.2 (plugin 4.0.4):

2021.09.10 08:31:38 INFO  web[][o.s.s.q.RegisterQualityProfiles] Update profile jsp/FindBugs Security JSP
2021.09.10 08:31:38 ERROR web[][o.s.s.p.Platform] Background initialization failed. Stopping SonarQube
org.sonar.server.exceptions.BadRequestException: java rule findsecbugs:XSS_JSP_PRINT cannot be activated on jsp profile FindBugs Security JSP
        at org.sonar.server.exceptions.BadRequestException.create(BadRequestException.java:57)
        at org.sonar.server.exceptions.BadRequestException.create(BadRequestException.java:61)
        at org.sonar.server.exceptions.BadRequestException.checkRequest(BadRequestException.java:44)
        at org.sonar.server.qualityprofile.RuleActivationContext.doSwitch(RuleActivationContext.java:227)
        at org.sonar.server.qualityprofile.RuleActivationContext.reset(RuleActivationContext.java:208)
        at org.sonar.server.qualityprofile.RuleActivator.activate(RuleActivator.java:76)
        at org.sonar.server.qualityprofile.BuiltInQProfileUpdateImpl.update(BuiltInQProfileUpdateImpl.java:73)
        at org.sonar.server.qualityprofile.RegisterQualityProfiles.update(RegisterQualityProfiles.java:132)
        at org.sonar.server.qualityprofile.RegisterQualityProfiles.lambda$start$1(RegisterQualityProfiles.java:93)
        at com.google.common.collect.ImmutableList.forEach(ImmutableList.java:405)
        at org.sonar.server.qualityprofile.RegisterQualityProfiles.start(RegisterQualityProfiles.java:88)
        at org.sonar.core.platform.StartableCloseableSafeLifecyleStrategy.start(StartableCloseableSafeLifecyleStrategy.java:40)
        at org.picocontainer.injectors.AbstractInjectionFactory$LifecycleAdapter.start(AbstractInjectionFactory.java:84)
        at org.picocontainer.behaviors.AbstractBehavior.start(AbstractBehavior.java:169)
        at org.picocontainer.behaviors.Stored$RealComponentLifecycle.start(Stored.java:132)
        at org.picocontainer.behaviors.Stored.start(Stored.java:110)
        at org.picocontainer.DefaultPicoContainer.potentiallyStartAdapter(DefaultPicoContainer.java:1016)
        at org.picocontainer.DefaultPicoContainer.startAdapters(DefaultPicoContainer.java:1009)
        at org.picocontainer.DefaultPicoContainer.start(DefaultPicoContainer.java:767)
        at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)
        at org.sonar.server.platform.platformlevel.PlatformLevel.start(PlatformLevel.java:90)
        at org.sonar.server.platform.platformlevel.PlatformLevelStartup.access$001(PlatformLevelStartup.java:49)
        at org.sonar.server.platform.platformlevel.PlatformLevelStartup$1.doPrivileged(PlatformLevelStartup.java:87)
        at org.sonar.server.user.DoPrivileged.execute(DoPrivileged.java:45)
        at org.sonar.server.platform.platformlevel.PlatformLevelStartup.start(PlatformLevelStartup.java:84)
        at org.sonar.server.platform.PlatformImpl.executeStartupTasks(PlatformImpl.java:198)
        at org.sonar.server.platform.PlatformImpl.access$400(PlatformImpl.java:46)
        at org.sonar.server.platform.PlatformImpl$1.lambda$doRun$1(PlatformImpl.java:122)
        at org.sonar.server.platform.PlatformImpl$AutoStarterRunnable.runIfNotAborted(PlatformImpl.java:370)
        at org.sonar.server.platform.PlatformImpl$1.doRun(PlatformImpl.java:122)
        at org.sonar.server.platform.PlatformImpl$AutoStarterRunnable.run(PlatformImpl.java:354)
        at java.base/java.lang.Thread.run(Thread.java:834)

So if I understand correctly, at startup SonarQube reconciles the built-in profiles/rules saved in the database with the profiles/rules exposed by plugin. When processing the FindBugs Security JSP profile it encounters a Java rule findsecbugs:XSS_JSP_PRINT and throws an error because a Java rule cannot be part of a JSP profile.

What I don’t understand is findsecbugs:XSS_JSP_PRINT should be in the findsecbugs-jsp profile (not findsecbugs) so how come it’s loading XSS_JSP_PRINT from the database with the wrong profile and language? I tried looking into the SonarQube source code and the incorrect profile and language seem to be loaded by UUID into a RuleDefinitionDto

There is a dash in the findsecbugs-jsp profile key, could it be the issue?
The new version of the plugin seems to work on a fresh SQ 8.9 or SQ 9 install, the issue seems to be when upgrading.

Could someone please help us understand what is the problem here?
Side question: is there a way to simulate a server upgrade with Orchestrator?

@dmeneses sorry for the ping but I see that you worked on SONAR-15240 - Startup fails if rule is moved to a different language
Could you please confirm that this is the same problem here?

For SonarQube 8.9 users, is there a workaround besides reverting to the old API for profiles ( ProfileDefinition) ?

Hi,

SONAR-15240 is specifically about renaming keys by using the attribute “deprecated key” in rules. As far as I can tell, SpotBugs is not using that.

I tried to do the upgrade from SQ 7.9+SpotBugs 3.11.1 to SQ 8.9 + SpotBugs 4.0.4 and I could not reproduce the problem.
I also checked the database before and after the upgrade and the declaration of the rule and quality profiles look correct.

What I don’t understand is findsecbugs:XSS_JSP_PRINT should be in the findsecbugs-jsp profile (not findsecbugs ) so how come it’s loading XSS_JSP_PRINT from the database with the wrong profile and language?

findsecbugs is the name of the rule repository. I agree that it’s strange that it’s not findsecbugs-jsp. I couldn’t find a rule with key findsecbugs:XSS_JSP_PRINT before or after the upgrade. In my test

I’m afraid it will be hard to figure it out without a reproducer.

Thank you very much for looking into it.
I did a bit more archeology in the git history of the plugin and here’s the explanation I have:

  • Version 3.3 of the plugin had a Java rules repository with key findsecbugs (see here)
  • That repository had a XSS_JSP_PRINT rule (see here)
  • Then in version 3.4 of the plugin that rule was moved to JSP rules repository with key findsecbugs-jsp (see here)

Does it make sense that in the database rule XSS_JSP_PRINT rule ID would have remained in the findsecbugs JSP repository?
In that case we could narrow down the issue to users who had version 3.3 (or earlier) of the plugin.

What would be the proper way to move the rule from a JSP repository to a Java repository?

If findsecbugs:XSS_JSP_PRINT is no longer declared by plugins, it would be kept in the DB with the status set to REMOVED and it shouldn’t be part of any quality profile.
I still don’t see why it would later try to activate it in a quality profile, causing the error.

The best way to change the key of a rule is to declare the old key using NewActiveRule.setDeprecatedKeys, when activating the rule in a quality profile. This will allow SonarQube to know what was the previous key used by the same rule, keeping the quality profiles and all issues associated with it unchanged.

If you find a way to reproduce the error (as simple as possible) let me know and I can take a look at it.