PHP security analysis NullPointerException error when using sonar.modules

All our PHP files are being indexed, however whenever it tries to analyse them we get a error:

ERROR: Could not analyse <filename>
java.lang.NullPointerException: null

Using SonarCloud, CircleCI, and Bitbucket.

We have a monorepo and have configured the multiple services as SonarCloud modules.

The indexing logs:

INFO: Indexing files...
INFO: Project configuration:
INFO: Indexing files of module 'frontend'
INFO:   Base dir: /home/circleci/project/frontend
INFO:   Source paths: src
INFO: Indexing files of module 'api-gateway'
INFO:   Base dir: /home/circleci/project/services/api-gateway
INFO:   Source paths: app
INFO:   Test paths: tests
INFO: Indexing files of module 'module1'
INFO:   Base dir: /home/circleci/project/services/module1
INFO:   Source paths: app
INFO:   Test paths: tests
INFO: Indexing files of module 'module2'
INFO:   Base dir: /home/circleci/project/services/module2
INFO:   Source paths: app
INFO:   Test paths: tests
INFO: Indexing files of module 'module3'
INFO:   Base dir: /home/circleci/project/services/module3
INFO:   Source paths: app
INFO:   Test paths: tests
INFO: Indexing files of module 'module4'
INFO:   Base dir: /home/circleci/project/services/module4
INFO:   Source paths: app
INFO:   Test paths: tests
INFO: Indexing files of module 'module5'
INFO:   Base dir: /home/circleci/project/services/module5
INFO:   Source paths: app
INFO:   Test paths: tests
INFO: Indexing files of module 'app'
INFO:   Base dir: /home/circleci/project
INFO: 501 files indexed
INFO: 113 files ignored because of scm ignore settings
INFO: Quality profile for css: Sonar way
INFO: Quality profile for js: Sonar way
INFO: Quality profile for json: Sonar way
INFO: Quality profile for php: Sonar way
INFO: Quality profile for ts: Sonar way

Then when analysing the PHP modules, there’s the same error for every single PHP file.

Example errors:

ERROR: Could not analyse services/api-gateway/app/Exceptions/Handler.php
java.lang.NullPointerException: null
	at com.sonar.security.frontend.php.ucfg.H.visitCompilationUnit(na:798)
	at org.sonar.plugins.php.api.visitors.PHPVisitorCheck.analyze(PHPVisitorCheck.java:644)
	at com.sonar.security.frontend.php.rules.A.visitCompilationUnit(na:2003)
	at com.sonar.security.frontend.php.rules.SQLInjectionCheck.visitCompilationUnit(na:988)
	at org.sonar.plugins.php.api.visitors.PHPVisitorCheck.analyze(PHPVisitorCheck.java:644)
	at org.sonar.php.PHPAnalyzer.analyze(PHPAnalyzer.java:100)
	at org.sonar.plugins.php.PHPSensor$AnalysisScanner.scanFile(PHPSensor.java:193)
	at org.sonar.plugins.php.Scanner.processFile(Scanner.java:69)
	at org.sonar.plugins.php.Scanner.execute(Scanner.java:57)
	at org.sonar.plugins.php.Scanner.execute(Scanner.java:43)
	at org.sonar.plugins.php.PHPSensor.execute(PHPSensor.java:124)
	at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:45)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:75)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.lambda$execute$1(ModuleSensorsExecutor.java:48)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.withModuleStrategy(ModuleSensorsExecutor.java:66)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:48)
	at org.sonar.scanner.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:68)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:123)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:109)
	at org.sonar.scanner.scan.ProjectScanContainer.scan(ProjectScanContainer.java:445)
	at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:441)
	at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:438)
	at org.sonar.scanner.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:399)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:123)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:109)
	at org.sonar.scanner.bootstrap.GlobalContainer.doAfterStart(GlobalContainer.java:128)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:123)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:109)
	at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:58)
	at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:52)
	at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
	at com.sun.proxy.$Proxy0.execute(Unknown Source)
	at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:185)
	at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:137)
	at org.sonarsource.scanner.cli.Main.execute(Main.java:112)
	at org.sonarsource.scanner.cli.Main.execute(Main.java:75)
	at org.sonarsource.scanner.cli.Main.main(Main.java:61)

ERROR: Could not analyse services/api-gateway/app/Events/Event.php
java.lang.NullPointerException: null
	at com.sonar.security.frontend.php.ucfg.H.visitCompilationUnit(na:798)
	at org.sonar.plugins.php.api.visitors.PHPVisitorCheck.analyze(PHPVisitorCheck.java:644)
	at com.sonar.security.frontend.php.rules.A.visitCompilationUnit(na:2003)
	at com.sonar.security.frontend.php.rules.SQLInjectionCheck.visitCompilationUnit(na:988)
	at org.sonar.plugins.php.api.visitors.PHPVisitorCheck.analyze(PHPVisitorCheck.java:644)
	at org.sonar.php.PHPAnalyzer.analyze(PHPAnalyzer.java:100)
	at org.sonar.plugins.php.PHPSensor$AnalysisScanner.scanFile(PHPSensor.java:193)
	at org.sonar.plugins.php.Scanner.processFile(Scanner.java:69)
	at org.sonar.plugins.php.Scanner.execute(Scanner.java:57)
	at org.sonar.plugins.php.Scanner.execute(Scanner.java:43)
	at org.sonar.plugins.php.PHPSensor.execute(PHPSensor.java:124)
	at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:45)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:75)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.lambda$execute$1(ModuleSensorsExecutor.java:48)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.withModuleStrategy(ModuleSensorsExecutor.java:66)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:48)
	at org.sonar.scanner.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:68)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:123)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:109)
	at org.sonar.scanner.scan.ProjectScanContainer.scan(ProjectScanContainer.java:445)
	at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:441)
	at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:438)
	at org.sonar.scanner.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:399)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:123)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:109)
	at org.sonar.scanner.bootstrap.GlobalContainer.doAfterStart(GlobalContainer.java:128)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:123)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:109)
	at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:58)
	at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:52)
	at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
	at com.sun.proxy.$Proxy0.execute(Unknown Source)
	at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:185)
	at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:137)
	at org.sonarsource.scanner.cli.Main.execute(Main.java:112)
	at org.sonarsource.scanner.cli.Main.execute(Main.java:75)
	at org.sonarsource.scanner.cli.Main.main(Main.java:61)

Any help would be appreciated.

Hey @adric,

Welcome to the community, and thanks for the bug report!

We’ll have a look into this and get back to you as soon as we know the reason, or need additional information.

Best,
Karim.

1 Like

Hey @adric,

Can you elaborate this a bit more? How is your sonar-project.properties structured? Something similar to this?

sonar.modules=folder1,folder2

folder1.sonar.projectKey=...
folder1.sonar.sources=...

folder2.sonar.projectKey=...
folder2.sonar.sources=...

Thanks!

Hi @Karim_El_Ouerghemmi,

Thanks for looking into this for us.
Yes, you are correct.

The sonar-project.properties file is:

sonar.projectKey=<app>
sonar.organization=<organisation>

sonar.projectName=<app>
#sonar.project.monorepo.enabled=true

sonar.links.ci=https://app.circleci.com/pipelines/bitbucket/<organisation>/<app>
sonar.links.issue=https://<organisation>.atlassian.net/browse/<project>
sonar.links.scm=https://bitbucket.org/<organisation>/<app>

sonar.sources=./app
sonar.tests=./tests
sonar.php.tests.reportPath=phpunit.report.xml
sonar.php.coverage.reportPaths=phpunit.coverage.xml

sonar.modules=frontend,api-gateway,<module1>,<module2>,<module3>,<module4>,<module5>

frontend.sonar.projectName=<app>_frontend
frontend.sonar.projectBaseDir=frontend
frontend.sonar.language=js
frontend.sonar.sources=./src
#frontend.sonar.tests=./src/__tests__

api-gateway.sonar.projectName=<app>_api-gateway
api-gateway.sonar.projectBaseDir=services/api-gateway
api-gateway.sonar.language=php

<module1>.sonar.projectName=<app>_<module1>
<module1>.sonar.projectBaseDir=services/<module1>
<module1>.sonar.language=php

<module2>.sonar.projectName=<app>_<module2>
<module2>.sonar.projectBaseDir=services/<module2>
<module2>.sonar.language=php

<module3>.sonar.projectName=<app>_<module3>
<module3>.sonar.projectBaseDir=services/<module3>
<module3>.sonar.language=php

<module4>.sonar.projectName=<app>_<module4>
<module4>.sonar.projectBaseDir=services/<module4>
<module4>.sonar.language=php

<module5>.sonar.projectName=<app>_<module5>
<module5>.sonar.projectBaseDir=services/<module5>
<module5>.sonar.language=php

Any idea why we’re getting NullPointerExceptions when analysing any of our PHP files?

Note: most of our PHP services are using Laravel/Lumen.

Hey @adric,

Excuses for the delayed response, and thanks for confirming the properties file structure.

I was able to reproduce the problem. It seems that currently, having such a multi-module structure with PHP (i.e., using sonar.modules) will always lead to this NullPointerException when the scanner gets to the security analysis stage. There is nothing specific in your code that causes this: simple reproducer.

Tickets are created on our side to fix this, with no estimate yet. Unfortunately, until then, I see no solution apart from not using sonar.modules. Did you follow https://sonarcloud.io/documentation/analysis/setup-monorepo/? Is there a specific reason you need to use modules?

Update: we plan to work on the fix next week, and it will probably be on SonarCloud the week after. I’ll inform in this thread when it is the case.

Small sidenote: sonar.language used in your .properties file was dropped long time ago (link) and can safely be removed.

Thank you for prioritising this.

Actually we were originally planning on setting it up as a monorepo on SonarCloud, however we found that the documentation didn’t provide enough information to be able to get it set up.

I didn’t see anywhere in the documentation where it showed how to setup multiple sonar-project.properties files. Should they just go in the sub-directories where each of the sub projects exist in the repository?

Also the documentation mentioned:

In the build procedure for each monorepo project, make sure to specify the SonarCloud project key that you designated for it.

However the CircleCI SonarCloud orb documentation doesn’t provide any details on how to set the project key and appears to just use the project key defined in the sonar-project.properties file in the repository’s root directory.

Is there more comprehensive documentation on how to setup a monorepo’s sonar-project.propertes files and triggering the separate projects from within the CircleCI configuration?

Hey @adric,

Unfortunately, no.

I’m not an expert in monorepo setups (especially with CircleCI), but here is an idea of how this could be setup:

  • Setup a SonarCloud monorepo as in SonarCloud and a project for each of your services.
  • Have a sonar-project.properties in the root directory of each of your services’ root directory with the service-specific settings (the most important of which would be a specific sonar.projectKey and a specific sonar.sources)
  • In CircleCI have a specific job for each service that before the sonarcloud/scan step, copies the sonar-project.properties file of the service to the root directory. For example such a job could have the following steps:
      - checkout
      - run: cp services/api-gateway/sonar-project.properties sonar-project.properties
      - sonarcloud/scan
  • As an addition, you could then look into starting only the job related to the service in whose directory changes were made (a quick circleci monorepo example google search seems to yield interesting approaches for this).

I hope this helps.

1 Like

Ah, great, thanks @Karim_El_Ouerghemmi, that worked.

Nice!

We are going to fix the error you experienced anyway, as that shouldn’t happen. But I think it is better to rely on another solution than sonar.modules. Even though it should technically work. (Nowadays) it is more like an internal setting set by some scanners like the java maven scanner. It is also not in the analysis parameters documentation.

(I did change the title of the thread to make it reflect the identified problem better)

Update:

The fix to the problem leading to the NullPointerException reported in this thread was deployed some days ago on SonarCloud (and will be part of the next SonarQube release).

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.