Review exception request: kimidoc (daemon + browser-support)

Hello,

I’m requesting a manual review / snap declaration for kimidoc so the automated review can pass for the daemon + browser-support combination.

kimidoc is a self-hosted HTML-to-PDF rendering service (REST API) built on Qt WebEngine. The combination being flagged is required for how the application works.

  • browser-support is needed so the embedded Chromium can keep its sandbox enabled while rendering user-supplied HTML templates. We intentionally do not use --no-sandbox because rendering untrusted content is exactly the security model this application is designed for.

  • daemon: simple is used because the application runs as a headless server (Qt offscreen platform, no graphical UI). Before launching Chromium, the wrapper drops privileges to the snap_daemon user using setpriv, so Chromium is never executed as root.

In addition to Snap confinement, the application includes a few extra security measures:

  • Remote subresource fetching is disabled by default.

  • An SSRF interceptor blocks loopback, link-local, and private network ranges.

  • API key authentication is required.

  • Chromium is started with --disable-gpu.

Please let me know if you need any additional information.

Thanks!

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

Hello @reviewers, below is the relevant snapcraft.yaml content that can help in review:

name: kimidoc
base: core24
version: '0.1.0'

summary: HTML template to PDF rendering service

description: |
  Self-hosted document rendering API. Store HTML templates with
  mustache-style placeholders and render PDFs (invoices, reports, resumes,
  certificates, cards) via REST. Chromium-quality output including complex
  scripts/RTL, custom fonts, charts, and real page numbering.

grade: devel
confinement: strict

# Chromium cannot run as root with its sandbox enabled, while snap daemons
# start as root. The launcher drops privileges to snap_daemon before exec.
system-usernames:
  snap_daemon: shared

plugs:
  kf6-core24:
    interface: content
    content: kf6-core24-all
    target: $SNAP/kf6
    default-provider: kf6-core24

  gpu-2404:
    interface: content
    target: $SNAP/gpu-2404
    default-provider: mesa-2404

apps:
  kimidoc:
    command: bin/kimidoc-launch
    daemon: simple
    restart-condition: on-failure

    plugs:
      - network
      - network-bind
      - browser-support
      - opengl

    environment:
      QT_QPA_PLATFORM: offscreen

      # Headless service: Chromium is forced into software rendering.
      QTWEBENGINE_CHROMIUM_FLAGS: --disable-gpu

      HOME: $SNAP_DATA
      XDG_CACHE_HOME: $SNAP_DATA/.cache

      LD_LIBRARY_PATH: $SNAP/kf6/usr/lib/x86_64-linux-gnu:$SNAP/kf6/usr/lib/x86_64-linux-gnu/libproxy:$SNAP/gpu-2404/x86_64-linux-gnu
      QT_PLUGIN_PATH: $SNAP/kf6/usr/lib/x86_64-linux-gnu/qt6/plugins
      QTWEBENGINEPROCESS_PATH: $SNAP/kf6/usr/lib/qt6/libexec/QtWebEngineProcess
      QTWEBENGINE_RESOURCES_PATH: $SNAP/kf6/usr/share/qt6/resources

      KIMIDOC_PAGEDJS: $SNAP/usr/share/kimidoc/paged.polyfill.js
      KIMIDOC_WEBUI: $SNAP/usr/share/kimidoc/webui
      KIMIDOC_TEMPLATES: $SNAP/usr/share/kimidoc/templates

parts:
  kimidoc:
    plugin: cmake
    source: .

    cmake-parameters:
      - -DCMAKE_BUILD_TYPE=Release
      - -DCMAKE_INSTALL_PREFIX=/usr
      - -DCMAKE_EXE_LINKER_FLAGS=-Wl,-rpath-link,/snap/kde-qt6-core24-sdk/current/usr/lib/x86_64-linux-gnu,--allow-shlib-undefined

    build-snaps:
      - kde-qt6-core24-sdk

    build-environment:
      - CMAKE_PREFIX_PATH: /snap/kde-qt6-core24-sdk/current/usr
      - LD_LIBRARY_PATH: /snap/kde-qt6-core24-sdk/current/usr/lib/x86_64-linux-gnu

    stage-packages:
      - fonts-noto-core
      - fonts-noto-cjk
      - fonts-noto-color-emoji

  launcher:
    plugin: dump
    source: packaging

    organize:
      kimidoc-launch: bin/kimidoc-launch

    stage:
      - bin/kimidoc-launch

Let me know if you need clarification on anything.

Thanks

Hello @keshavnrj,

Thank you for the detailed request. I notice that in your request that you intend to use chromium’s sandbox, but you do not have allow-sandbox: true defined in your snapcraft.yaml. Is this intentional, I do not believe chromium’s sandbox will work without this being defined. Please expand on this before I can proceed further with the review.

In addition, due to the elevated level of privileges the combination of daemon and browser-support provide, if accepted, granting this will require publisher vetting akin to classic requests. If kimidoc is an open-source project, please provide links to the upstream repository to help with this process, or let me know if it is closed-source.

Thank you!

Hello @elisehdy, thank you for the careful review - you caught a real omission.

On allow-sandbox: using Chromium’s sandbox is intentional, the missing allow-sandbox: true was an oversight, not a decision, and is now fixed in the snapcraft.yaml (it will be included in the next upload):

plugs:
  browser-sandbox:
    interface: browser-support
    allow-sandbox: true

For context on how the snap is built to keep the sandbox active:

You are also correct that without allow-sandbox: true the sandbox would not survive full AppArmor confinement.

Our development host runs snapd in partial confinement (Arch Linux), which masked the issue. In that environment we verified that:

  • the sandboxed zygote runs in a separate user namespace,
  • NoNewPrivs is enabled,
  • and no --no-sandbox flag is present on any Chromium child process.

Under enforcing AppArmor, however, user namespace creation would be denied without the allow-sandbox: true attribute. That is why this change is necessary and has now been made.

Regarding the source code: kimidoc is closed-source (proprietary).

I understand that the combination of a daemon and browser-support warrants publisher vetting similar to classic confinement requests, and I’m happy to go through that process. Please let me know what additional information or verification you need from me.

Thanks

Hello @reviewers, any update on this? Let me know if you need any clarification. The latest revision contains all the adjustments @elisehdy pointed out and i verified that the service now runs and behave as expected on Ubuntu (strict confinement), specially the sandbox support for chromium/Qt Webengine is working correctly.

Hi, just a gentle follow-up on this request - it’s been in the review queue since 27 July.

Is there anything further I can provide to help the review along (detail on how the interfaces are used, latest snapcraft.yaml ) Happy to adjust the snap if the current approach isn’t the preferred one.

Rectly we managed to deploy the snap with manual connection to browser-sandbox using snap connect kimidoc:browser-sandbox, and it is running on the production infrastructure at kimidoc.com :smiling_face_with_sunglasses:

Apologies for the silence since @elisehdy’s review, and thanks for the thorough follow-ups. The technical side is in good shape: allow-sandbox: true is the correct fix, your explanation of the user-namespace denial under enforcing AppArmor is right and keeping the Chromium sandbox on with a setpriv drop to snap_daemon before exec is exactly the right solution. No further technical changes needed there.

The remaining gate is publisher vetting rather than anything in the yaml. As @elisehdy noted, daemon plus browser-support is a classic-equivalent privilege level and since kimidoc is proprietary we can’t lean on public source for that, so please follow the instructions in this forum post to begin the vetting process and let us know here once it is complete.

In a meantime, +1 from me to auto-connect browser-sandbox (browser-support with allow-sandbox: true) for the kimidoc daemon

1 Like

Hi @0xnishit , thank you for taking time and providing way forward.

On publisher vetting: I tried to publish the kimidoc snap under the keshavnrj account, which already holds Star Developer status (keshavbhatt (keshavnrj) published snaps in the Snap Store), granted through the process in the Verified Accounts post. The account has published and maintained its snap catalog continuously since 2017.

If the classic-equivalent privilege level here calls for org-level Verified Account status rather than Star Developer, tell me and I will start that process for Ktechpit (ktechpit.com).

Hello @keshavnrj,

Apologies again for the wait on this request and for missing the Star Developer status! Given the updates and provided technical reasoning, this request is now also a +1 from me for granting browser-sandbox requested permissions and the publisher is vetted. I will begin the process to grant this request.

1 Like

Hey folks!

browser-support (with allow-sandbox: true) + daemon is almost as powerful as classic, with the downside that the user does not need to specify --classic at installation time, shadowing the high level of privilege granted to the snap.

Whilst start developer acknowledges an extraordinary trajectory, I’m not sure it carries the same level of trust as Verified accounts (as of now). For this concrete case I believe that Verified Account status for Ktechpit would possibly be the right call in this case.

@jnsgruk what are your thoughts?

1 Like

Yes, I think particularly due to the closed source nature of the app, we should pursue some more diligent ID verification under the Verified Publisher process please.

1 Like

Hi @jslarraz @jnsgruk , Thank you for taking time and reviewing my request.

To get ktechpit verified i think i need to do the following:

  • create ktechpit account in snapcraft.io
  • request transfer of kimidoc from keshavnrj to ktechpit
  • once kimidoc moved, open verified request for ktechpit

or is it possible to:

  • rename keshavnrj directly to ktechpit?

thank you for your guidance.

cc @elisehdy @0xnishit

Hey @keshavnrj

or is it possible to: rename keshavnrj directly to ktechpit?

I’m not entirely sure, perhaps @store folks know. I feel opening a new account for ktechpit sounds better anyway.

To get ktechpit verified i think i need to do the following:

I would say create ktechpit account in [snapcraft.io](http://snapcraft.io) and open both requests, transfer of kimidoc from keshavnrj to ktechpit and verified account request for ktechpit, in parallel.

On the verified account request for ktechpit, make sure to reference this topic and the transfer of kimidoc from keshavnrj to ktechpit so policy-reviewers don’t miss any context.

1 Like

Hi @jslarraz , I just created both requests in appropriate categories in this forum. Here are links to them:

Thanks! Please let us know once both requests are done so we can create the exception for the use of browser-support + daemon.

Hi @jslarraz the kimidoc snap has been transfered to ktechpit( new org account ).

Only the verified account request for ktechpit is pending. There is no update on this topic until now.

Here is my forum post: Verified Account request for ktechpit let me know if i need to add more details or provide anything else on that post from my end.

Thanks

1 Like

Hey,

Its been almost a month now, my post to get verified status for my ktechpit org account got no attention/update from @reviewers I dont know if it is normal.

@jslarraz @jnsgruk I don’t know if I should wait further, if you guys can help me on getting my request a review i would be thankful.

I would also like to thank @0xnishit @elisehdy for engaging in this post and providing directions.

Hi @jslarraz

Both requests:

Transfer kimidoc to the ktechpit account and Verified Account request for ktechpit are done.

Hello @keshavnrj :slight_smile:

I have manually approved the change for version 22. This is now live!

Thank you for your patience!

1 Like