The VisionAppster Engine consists of a bunch of software modules that are available to all apps. The va-engine service that runs on the background is actually a VisionAppster app itself. It is started through va-run as any app could.

The app is called init.qml and stored in the init directory under the VisionAppster installation root. There is also an alternative app called api-init.qml that is intended for running a fixed set of apps and to publish their APIs. To configure the va-engine service, the easiest way is to modify the init.qml script.

The location of the VisionAppster installation and thus the init.qml script varies depending on platform.

  • Windows: C:\Program Files\VisionAppster\init

  • Generic Linux: /opt/visionappster/init

  • Flatpak: Typing flatpak info -l com.visionappster.Builder will give you the root of the installed Flatpak. The init app can be found in files/opt/visionappster/init under the Flatpak root.

Since the Engine lets one to install and run new components through the HTTP interface, it is extremely important to set up access control correctly. A failure in doing so will easily lead into a remote code execution vulnerability.

Network interface🔗

The default behavior of the init.qml app is to bind the web server to the loopback interface only. This blocks out all external connection attempts. api-init.qml binds to all available interfaces by default.

The web server can be bound to a specific interface or to all available interfaces. For example:

  • - Bind to IPv4 loopback only.

  • [::1]:2015 - Bind to IPv6 loopback only.

  • - Bind to all IPv4 interfaces.

  • [::]:2015 - Bind to all IPv6 interfaces.

  • - Bind to a specific IPv4 address.

The port number (2015) could be anything else, but some client software may assume the standard port.

// Listen port 2015 on all IPv4 interfaces

IP-based access control🔗

The web server supports IP subnet based access control. If no access control rules have been specified, requests from any IP will be accepted. Once a single rule has been set up, the default behavior changes to deny requests. The access control rules work on the TCP layer, blocking the connection before HTTP has a chance to parse the request.

The access control mechanism maintains a list of rules that either allow or deny access based on the client’s IP address. The first matching rule will determine the fate of the client. The following example denies access from a certain evil IP subnet.

// Block evil IPs.
// An empty address means "everybody". Allow everybody else.

The allowFrom and denyFrom functions accept IPv4 and IPv6 addresses and subnets. Examples:

webServer.allowFrom(''); // IPv4 address/netmask
webServer.denyFrom(''); // Same in CIDR notation
webServer.allowFrom(''); // IPv4 host address
webServer.denyFrom('fe80::a65d:36ff:fec8:aced'); // IPv6 host address
webServer.allowFrom('fe80::/64'); // IPv6 subnet
webServer.denyFrom(''); // Any IP address (v4 or v6)


CORS is a technique implemented by browsers to allow web pages to make requests to servers they did not originate from. Since this is generally unsafe, the target server must be explicitly configured to accept the requests.

The Engine’s web server disallows CORS requests by default. That is, scripts loaded from a web server other than the Engine’s own will not be able to make requests to it. Note however that this only applies to browsers. A malicious Node.js script run locally can still make requests to the server. The api-init.qml app does not expose unsafe features to the web server and therefore enables CORS:

  id: webServer
  corsEnabled: true

This allows CORS requests made by any script independent of its origin. For a more fine-grained control one can specify which domains are allowed to make CORS requests:

  id: webServer
  corsEnabled: true
  corsOrigins: ['', '']