Describe the bug
If an ExApp declares an environment variable with an empty <default> element, the variable is deployed to the container with the literal string Array as its value, and PHP logs an Array to string conversion warning.
An empty XML element is parsed into an empty array, not an empty string, so it slips past the filter that is meant to drop empty values.
Steps/Code to Reproduce
appinfo/info.xml:
<external-app>
<docker-install>
<registry>example.local</registry>
<image>minimal_exapp</image>
<image-tag>1.0.0</image-tag>
</docker-install>
<environment-variables>
<variable>
<name>EMPTY_ELEM</name>
<display-name>Empty</display-name>
<description>d</description>
<default></default>
</variable>
</environment-variables>
</external-app>
occ app_api:app:register <appid> <harp-daemon> --info-xml /tmp/info.xml --wait-finish
docker inspect nc_app_<appid> --format '{{range .Config.Env}}{{println .}}{{end}}' | grep EMPTY_ELEM
Expected Results
The variable is not passed to the container at all, which is what happens for the two neighbouring cases (both verified):
- a
<variable> with no <default> element at all,
- a declared variable overridden with an empty value,
--env EMPTY_ELEM=.
Actual Results
and in nextcloud.log (level 2):
Array to string conversion at /var/www/html/apps-extra/app_api/lib/DeployActions/DockerActions.php#1279
<default/> behaves identically to <default></default>.
Cause
info.xml is parsed with json_decode(json_encode((array)simplexml_load_string(...)), true), so an empty element becomes [] rather than ''.
lib/Service/ExAppService.php#L305-L306 assigns that array to default and value.
- the filter at
lib/Service/ExAppService.php#L318 ($envVar['value'] !== '') therefore keeps the entry, since [] !== ''.
lib/DeployActions/DockerActions.php#L1189 then does sprintf('%s=%s', $envKey, ...['value']), producing Array. lib/DeployActions/KubernetesActions.php#L709 is the same code, so Kubernetes deployments are affected too.
App Store installs go through the same XML path, so a published ExApp with this in its manifest would ship Array to every installation.
The same code is present in main, stable34 and stable33.
Suggested fix
Normalise the parsed value to a string where it is read, which keeps the existing empty-value filter working for every shape:
$default = $envVar['default'] ?? '';
if (!is_scalar($default)) {
$default = '';
}
Setup configuration
- Nextcloud: 35.0.0 dev
- AppAPI: 35.0.0-dev.1 (
main)
- HaRP: 0.4.3,
docker-install daemon
- Reproduced with a minimal framework-free ExApp; line numbers above are from
main, the log line number is from the checkout used for the test.
Describe the bug
If an ExApp declares an environment variable with an empty
<default>element, the variable is deployed to the container with the literal stringArrayas its value, and PHP logs anArray to string conversionwarning.An empty XML element is parsed into an empty array, not an empty string, so it slips past the filter that is meant to drop empty values.
Steps/Code to Reproduce
appinfo/info.xml:Expected Results
The variable is not passed to the container at all, which is what happens for the two neighbouring cases (both verified):
<variable>with no<default>element at all,--env EMPTY_ELEM=.Actual Results
and in
nextcloud.log(level 2):<default/>behaves identically to<default></default>.Cause
info.xmlis parsed withjson_decode(json_encode((array)simplexml_load_string(...)), true), so an empty element becomes[]rather than''.lib/Service/ExAppService.php#L305-L306assigns that array todefaultandvalue.lib/Service/ExAppService.php#L318($envVar['value'] !== '') therefore keeps the entry, since[] !== ''.lib/DeployActions/DockerActions.php#L1189then doessprintf('%s=%s', $envKey, ...['value']), producingArray.lib/DeployActions/KubernetesActions.php#L709is the same code, so Kubernetes deployments are affected too.App Store installs go through the same XML path, so a published ExApp with this in its manifest would ship
Arrayto every installation.The same code is present in
main,stable34andstable33.Suggested fix
Normalise the parsed value to a string where it is read, which keeps the existing empty-value filter working for every shape:
Setup configuration
main)docker-installdaemonmain, the log line number is from the checkout used for the test.