Request: installation of shutdown, mount-control, block-devices and custom-device for infonet-kiosk

Hello,

infonet-kiosk was rejected at manual review on 14 July 2026 for the shutdown plug (review request 2757021) and I was pointed here. I am requesting installation permission for the four super-privileged interfaces the snap plugs. I am not requesting auto-connection for any of them: every connection is made explicitly, either by our own gadget in the image or by a one-shot provisioning script run once per device.

name: infonet-kiosk
description: Device agent and bundled Chromium for our own fleet of Ubuntu Core
  digital-signage appliances. Runs a Node supervision agent plus Chromium
  rendered on ubuntu-frame. Unlisted, published by Odytek, used only on
  hardware we own, image and provision ourselves (custom gadget + model
  assertion) in the schools we operate. Not intended for public use.
snapcraft: PRIVATE (the plugs section is reproduced verbatim below; happy to
  share the full file with the reviewers on request)
upstream: PRIVATE
upstream-relation: publisher and sole maintainer — the snap, the agent and the
  gadget are all our own in-house software
plugs:
  shutdown:
    request-type: installation
    reasoning: logind reboot over D-Bus, for three appliance-lifecycle
      functions — (1) remote reboot triggered by an operator from our
      management dashboard, (2) a scheduled weekly maintenance reboot, and
      (3) the agent's self-heal escalation, where a device wedged past a
      threshold (no server contact, frozen compositor, renderer crash loop)
      reboots itself as a last resort. On unattended screens in school
      hallways this is the difference between a device that recovers on its
      own and one that needs a technician on site. We only ever reboot; we do
      not need snapd-control or any broader system control.
  usb-mount:
    interface: mount-control
    attributes:
      mount:
        - what: /dev/sd*
          where: $SNAP_COMMON/usb-import
          type: [vfat]
          options: [ro, nodev, nosuid, noexec]
    request-type: installation
    reasoning: devices are provisioned by inserting a signed USB key holding
      config.json and our organisation CA certificate. The snap's wrapper
      mounts the key itself, imports the data and unmounts. The mount is
      read-only, nodev/nosuid/noexec, vfat only, and lands at a fixed path
      inside $SNAP_COMMON. Only signed *data* is ever read from the key,
      never code. We first tried udisks2 — on Ubuntu Core there is no
      automount, and the mounts it created were not visible in the snap's
      mount namespace, so the import never saw the files.
  block-devices:
    request-type: installation
    reasoning: required to make the mount-control plug above actually work.
      The snap's device cgroup only admits nodes belonging to connected
      interfaces, so mount(2) on /dev/sda1 fails EPERM with no AppArmor and
      no seccomp denial at all, even though the mount-control rule is present
      in the generated profile. block-devices is what puts the node in the
      cgroup. We do not read or write block devices directly; the only access
      is the read-only mount described above.
  cec0:
    interface: custom-device
    attributes:
      custom-device: cec-dev
    request-type: installation
    reasoning: HDMI-CEC on our Raspberry Pi models. The slot is declared by
      our own gadget and exposes only /dev/cec[0-9]. The agent uses it to
      power the attached TV panel on and off on schedule so screens are not
      left burning overnight. Access is confined to the CEC character device;
      no other device node is exposed.

For reference, the matching slot in our gadget:

slots:
  cec-dev:
    interface: custom-device
    custom-device: cec-dev
    devices:
      - /dev/cec[0-9]

The snap is unlisted and strictly confined. Connections are made explicitly at image build or provisioning time, never automatically. In each case we asked for the narrowest capability that does the job: reboot rather than full system control, a read-only noexec vfat mount at a fixed path rather than general filesystem access, and a single CEC character device rather than raw device access.

Happy to answer any questions,

Thank you, Cedric (Odytek)

This request has been added to the queue for review by the @reviewers team.

Hi @Odytek,

Can you please confirm whether this snap is supposed to be published to the global store or brand store?

Hi @shishirsub10 ,

This is supposed to be published to the global store. I know it should be in a brand store, but this is for a few schools and we wanted a way to keep our devices up to date using a monitoring scripts and chromium in Ubuntu Core.

If this isn’t possible, do you have any recommendations for us.

Thank you and a great day!

Hi @Odytek,

Thank you for the clarification. I am okay with granting manual connection to the requested interfaces. Since, we have to do publisher vetting, can you please confirm whether this is a commercial product distributed by a company?

Hello @shishirsub10 ,

Thank you for your help. No, this isn’t a commercial product. Odytek is a French high school technology club located in New Brunswick, Canada. I’m the teacher supervising the projects.

We installed these devices in our school to remotely control digital signage as part of an advanced programming project for a few students. A few other schools have now shown interest in the project, so we’ll be distributing some of these devices to them.

We thought it would be easier to maintain the devices through Snapcraft rather than having to flash all the devices whenever we push an update.

Thanks again,

Cedric

Hey folks!

I’m also inclined to cast a +1 for granting manual connection. I would still like to do some sort of publisher vetting. I think proving ownership of the high school email account may be enough in this case for manual connection.

@jnsgruk I wonder if we want to consider alternative methods for obtaining verified account status so that these kinds of entities can opt in.

+1 from me as well to grant manual-connection to the requested interfaces. I have initiated the vetting process.

+2 votes for, 0 votes against. Publisher is vetted. Granting manual-connection to the requested interfaces.

There is still one warning to resolve before the snap can be published.

(NEEDS REVIEW) 'daemon' should not be used with 'browser-support' security-snap-v2_daemon_with_browser-support (agent)

The Snap Store automatically blocks pairing a daemon directly with browser-support because combining background runtime execution with broad browser-sandbox privileges can be used to break out of the confinement that snap provides.

To help determine the best path forward, could you clarify a couple of details about your architecture?

  • Is it possible to drop one of the interfaces?
  • Does the daemon execute a full browser engine(chromium) or is it simply making standard HTTP/REST API calls?
  • If both of them are needed, is it possible to create a separate app to run as a daemon and another app with browser-support for rendering?

Thank you for the review and for granting the interface declarations. I’m sorry for the delay. I had to do some research on your questions before sending a reply. Thank you for your patience.

Our snap, Infonet-kiosk is a digital-signage snap (school hallway screens; unlisted, single publisher, managed fleet). The agent app is a Node.js daemon that spawns a bundled Chromium as a child process and supervises it over the Chrome DevTools Protocol on 127.0.0.1 (health, navigation, relaunch on renderer crash). The agent’s own network use is HTTPS/Socket.IO to our server.

Q1 – can one interface be dropped? Unfortunately no. daemon is required because there’s no user session or display manager. The kiosk must start unattended at boot and recover from power loss with nobody on site. browser-support is required for Chromium’s multi-process model. Without it the renderer processes are AppArmor-killed at launch (observed on our tests). We use the default “allow-sandbox: false” variant only.

Q2 – full engine or REST? A full Chromium engine. It is locked down by managed policy “URLBlocklist: [“*”]” with an allowlist of our own server domain and localhost only, kiosk mode, no extensions, no downloads, crash reporter disabled. It never renders arbitrary web content.

Q3 – separate apps? I believe on Ubuntu Core a rendering app would have to be a daemon (there is no session to launch a non-daemon app, and a confined daemon cannot launch a sibling app under a different profile), so the split would still pair daemon with browser-support and trigger the same check. We are willing to do it if it helps your assessment, since it would isolate browser-support from the more privileged interfaces (mount-control, block-devices, shutdown), but it does not remove the need for the exception, I believe.

This is the same pattern as chromium-mir-kiosk, dashkiosk-client-browser, screencloudplayer, krellian-kiosk and pcds-kiosk. Could infonet-kiosk be added to sec_browser_support_overrides? Happy to provide any further detail.

Thank you again for your time and help with this.

Cedric (odytek)