ClickNick 0.23.1 trust report
Generated 2026-09-09 18:24 UTC from uv.lock at commit ffab841018b9.
This file is self-contained: no scripts, no external resources. Latest reports and the explanation of this
format: pyrung.com/clicknick/security.
All release checks passed.
For IT / security review
ClickNick is a Windows desktop tool for the CLICK PLC programming software. It is written in Python, installed
with uv tool install clicknick (or pip) from PyPI, and runs as the signed-in user with no elevation.
ClickNick was written with security in mind: keep dependencies limited, prefer pure Python where practical, run
without administrator rights, and make the software's behavior easy to inspect.
Software characteristics
- Runs as the signed-in user. No administrator rights are needed to install or run. The default uv installation stays under the user's profile; exports and durable workspaces use user-chosen folders.
- 0 obfuscated or encrypted Python modules. Everything ClickNick ships is readable source.
- 0 packed or self-extracting executables.
- 0 compiled code or executables in ClickNick's own package (checked against the wheel below). The install as a whole does place binaries in the user profile: a Python interpreter, and the native files in the packages marked in the table. pywin32 ships
Pythonwin.exeandpythonservice.exe; ClickNick never runs them. - 0 installed Windows services.
- 0 installed drivers.
- 0 scheduled tasks.
- 0 telemetry or analytics.
- 0 automatic update agent. Updates happen only when the user runs
uv tool upgrade clicknick. - 0 unsolicited outbound network connections. The only outbound connection in the code is Modbus TCP to the PLC address the user typed in.
- 0 embedded external network endpoints in runtime code.
- All runtime dependencies are listed below, pinned to exact versions. The list is generated from
uv.lock, and a fresh install gets exactly these versions. - Source code for ClickNick and every dependency is publicly available. All are open source; repository links are in the table.
What ClickNick does
- Reads and writes the CLICK project database (the
SC_.mdbfile in the temporary folder CLICK creates under%LOCALAPPDATA%\Temp\CLICK (...)\when it opens a project) through Windows ODBC. - Runs a PowerShell worker on machines without a 64-bit Access driver, which is most Windows x64 machines. ClickNick starts the 32-bit Windows PowerShell that ships with Windows and uses the Jet engine already present in Windows. The exact command line, launched from
python.exe, is%SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -NonInteractive -EncodedCommand <base64>. The Base64 is the UTF-16 encoding of the shipped fileclicknick/resources/jet_sidecar.ps1, unchanged; its SHA256 is in the release summary so it can be allowlisted. Expect endpoint tooling that flags encoded PowerShell to alert on the first project opened. - For autocomplete: reads and fills in text fields of the CLICK Programming Software window. It places the autocomplete box over the field and writes the memory address of the chosen nickname back into it. It uses the standard Windows API for this: enumerate windows, read a control's text (
WM_GETTEXT), set it (WM_SETTEXT), and send Enter, Tab or Escape to the CLICK dialog after the user picks a nickname. It installs no keyboard hook, injects nothing intoClick.exe, and reads no other application's windows. Process name in monitoring:python.exe(orpythonw.exe). - Editor command listener, localhost only. While ClickNick is running, and whether or not the offline console is open, it holds one TCP port bound to
localhost, with the port number chosen by Windows.clicknick-clion the same machine connects to it to read or stage address edits, check workspace code, and apply ladder proposals. The listener ispython.exe; the port number is written to a small file under%LOCALAPPDATA%. Connections are unauthenticated: other local users and processes that can reach the port can connect. Address edits arrive as staged, undoable changes in the running window and reach the project only when the user saves. - Offline console listener. The console starts pyrung's debug adapter in a child
python.exe, which opens its ownlocalhostport for thepyrung liveconnection. It closes with the console. - Connects to a CLICK PLC over Modbus TCP (port 502 by default) only when the user opens the Dataview editor and asks to go live, and only to the address the user typed in. In that mode it reads values, and it writes values the user types in and clicks Write for.
- Generates and runs Python from the ladder project. When a project is connected, ClickNick translates the ladder into Python with its own generator and runs that code in-process to build the model behind Check Program. The generator emits only names and values taken from the ladder; it does not run files found in the project folder. The user's editable workspace copy (
src/plc,run.py,project_to_csv.py) runs only when the user clicks Check Program, applies a proposal, or starts the offline console, each in a childpython.exewith the same interpreter. Treat a workspace received from outside like any other script folder: it runs with the signed-in user's permissions and can perform whatever file or network operations its code requests. - Opens documentation links (github.com, pyrung.com) in the default browser when the user clicks them.
- Writes small files into that same CLICK temp folder: the live-session port file, next to the project it belongs to. CLICK does not read these files.
- The
clicknick.exelauncher in%USERPROFILE%\.local\binis the standard entry-point stub that uv or pip generates at install time for any Python command-line tool. It is unsigned, under 100 KB, and only startspython.exewith ClickNick's entry point. - Installation copies files. Python wheels have no install-time scripts; installing ClickNick unpacks files into a private virtual environment under
%APPDATA%\uv\tools\clicknick. ClickNick writes nothing to the registry, services, drivers or scheduled tasks, and keeps no settings file of its own. The uv installer itself adds its own folder to the user's PATH, a write toHKCU\Environment.
This section is handwritten and kept stable across releases. Everything below is generated by
devtools/trust_report.py at release time from the lock file, the built wheel and the source tree,
and the source checks are exactly that: release checks, not a formal security audit.
Release summary
| Release | ClickNick 0.23.1 |
| Python | >=3.11,<4.0 |
| Runtime distributions | 11 |
| First-party | 4 |
| Third-party | 7 |
| Known vulnerabilities | 0 (10 dependencies audited against the advisory database; ClickNick itself is the package being built) |
| Non-PyPI third-party dependencies | 0 |
| Unresolved licenses | 0 |
| SBOM SHA256 (clicknick-sbom-0.23.1.cyclonedx.json) | 08512cd236794e5d2150a7352339709a1c10c88b41887e48544e8d9dae1dbd6d |
| Wheel SHA256 (clicknick-0.23.1-py3-none-any.whl) | 6d365e6c33bdfb58d554297cc069c546a17876070ea0f1e3a5cfdbb77cb67671 |
| PowerShell worker SHA256 (clicknick/resources/jet_sidecar.ps1) | 75512e4fe2674f0f4838ee23e900377cbd84501077ac7040cad8e37072b91da9 |
| Generated from | uv.lock, exported as CycloneDX 1.5 by uv 0.12.1 |
| Source commit | ffab841018b904258ec3f96a4906f444f397269e |
Release checks
- ✓ All third-party dependencies come from PyPI10 distributions, all from pypi.org
- ✓ Every runtime distribution has a resolved licenselicense expression or classifier found for each
- ✓ Every runtime distribution has a documented purposepurpose column filled from PURPOSES in devtools/trust_report.py
- ✓ Every runtime distribution is pinned exactly in pyproject.toml to its locked version10 distributions pinned with ==; a fresh install matches this table
- ✓ No known vulnerabilities (uv audit)advisory database reports none for the runtime set
- ✓ Wheel contains no compiled code or executables125 files: 4 (none), 3 .md, 6 .png, 1 .ps1, 109 .py, 1 .txt, 1 .typed
- ✓ No HTTP client dependency (requests, httpx, aiohttp, urllib3, ...)none of the known HTTP client packages in the runtime set
- ✓ No telemetry or analytics SDK dependencynone of the known telemetry SDKs in the runtime set
- ✓ No HTTP, FTP or mail client imports in runtime sourceno urllib.request, http.client, ftplib, smtplib or third-party HTTP imports
- ✓ No external runtime endpointsevery URL in runtime source points at github.com or pyrung.com (browser links, listed below)
- ✓ Local listeners bind to localhost onlysrc/clicknick/live/server.py:295 (localhost)
- ✓ Subprocesses launch only the same Python interpreter or the built-in Windows PowerShell4 launch sites, all sys.executable or powershell_path()
- ✓ No download commands in shipped scriptsno Invoke-WebRequest, WebClient, BitsTransfer, curl or wget
- ✓ No Python decoded at runtime (base64/zlib/marshal fed to exec/eval/compile)no module both decodes a blob and executes it; the PowerShell worker is Base64 of a shipped .ps1, hashed above
Runtime dependencies
Every distribution that uv tool install clicknick==0.23.1 installs. ClickNick pins its
whole runtime tree exactly (the "Pin" column), so a fresh install matches this table and the SBOM; a release check
below confirms the pins match uv.lock. "Used by" names the package that needs it. "First-party" means
written by the ClickNick author. "Native code" reflects the Windows x64 wheels installed in the build environment.
| Package | Version | Pin | Source | License | Used by | Native code | Purpose |
|---|---|---|---|---|---|---|---|
| clicknick | 0.23.1 | This release | AGPL-3.0 | no | Application | ||
| executing | 2.2.1 | ==2.2.1 | PyPI | MIT | pyrung | no | Python source introspection (used by pyrung) |
| laddercodec | 0.2.1 | ==0.2.1 | First-party | MPL-2.0 | ClickNick | no | Ladder diagram codec (read/write CLICK ladder) |
| pyclickplc | 0.4.0 | ==0.4.0 | First-party | MIT | ClickNick, pyrung | no | CLICK project formats, address model, Modbus access |
| pymodbus | 3.12.1 | ==3.12.1 | PyPI | BSD-3-Clause | pyclickplc | no | Modbus TCP protocol (used by pyclickplc) |
| pyodbc | 5.3.0 | ==5.3.0 | PyPI | MIT | ClickNick | yes (1 .pyd) | ODBC access to the CLICK project database |
| pyrsistent | 0.20.0 | ==0.20.0 | PyPI | MIT | pyrung | yes (1 .pyd) | Immutable data structures (used by pyrung) |
| pyrung | 0.15.0 | ==0.15.0 | First-party | MPL-2.0 | ClickNick | no | PLC program model: offline run and static checks |
| pywin32 | 311 | ==311 | PyPI | PSF | ClickNick | yes (6 .dll, 2 .exe, 49 .pyd) | Windows API (window detection, overlay placement) |
| tksheet | 7.6.0 | ==7.6.0 | PyPI | MIT | ClickNick | no | Spreadsheet widget for the Address Editor |
| tomlkit | 0.15.1 | ==0.15.1 | PyPI | MIT | pyrung | no | TOML editing that preserves formatting for check settings (used by pyrung) |
Dependency tree
clicknick 0.23.1
executing 2.2.1
laddercodec 0.2.1
pyclickplc 0.4.0
pymodbus 3.12.1
pymodbus 3.12.1
pyodbc 5.3.0
pyrsistent 0.20.0
pyrung 0.15.0
executing 2.2.1
pyclickplc 0.4.0
pyrsistent 0.20.0
tomlkit 0.15.1
pywin32 311
tksheet 7.6.0
tomlkit 0.15.1
Source transparency
Evidence behind the release checks, listed so a reviewer can look at the exact lines.
URLs in runtime source
Every URL found in a string literal of the runtime code (comments and docstrings excluded). All of these are opened in the user's browser on click or shown as help text. None is contacted by ClickNick.
| File | URL |
|---|---|
| src/clicknick/app.py:1713 | https://github.com/ssweber/clicknick |
| src/clicknick/app.py:1717 | https://github.com/ssweber/clicknick/issues |
| src/clicknick/views/dialogs.py:192 | https://github.com/ssweber/clicknick |
| src/clicknick/views/dialogs.py:199 | https://github.com/ssweber/clicknick/issues |
| src/clicknick/views/dialogs.py:397 | https://pyrung.com/clicknick/help/#database-connection |
| src/clicknick/views/dialogs.py:208 | https://pyrung.com/clicknick/help/#database-connection |
| src/clicknick/views/dialogs.py:272 | https://pyrung.com/clicknick/help/#database-connection |
Subprocess launch sites
| Location | Program |
|---|---|
| src/clicknick/live/rung_commands.py:815 | sys.executable |
| src/clicknick/services/dap_service.py:375 | sys.executable |
| src/clicknick/services/program_check.py:89 | sys.executable |
| src/clicknick/utils/jet_sidecar.py:137 | str(powershell_path()) |
Dynamic code execution
Every exec or eval call in runtime code. Each one runs Python that ClickNick
generated from the user's own ladder project, or files from the user's project workspace. Nothing downloaded,
nothing decoded.
| Location | Call |
|---|---|
| src/clicknick/live/tag_commands.py:318 | exec(compile(tags_source, 'src/plc/tags.py', 'exec'), ns) |
| src/clicknick/services/analysis_service.py:271 | exec(compile(code, '<analysis>', 'exec'), namespace) |
Verify it yourself
From a checkout of the tagged release. Wheel builds are reproducible: the same source bytes give the same wheel, so a rebuild from the tag gives the SHA256 above and the one PyPI shows. The release is built on Windows with Git's default line-ending conversion, so use a Windows checkout with default Git settings; a Linux or macOS checkout produces LF line endings and therefore a different hash.
git clone https://github.com/ssweber/clicknick cd clicknick git checkout v0.23.1 uv export --frozen --no-dev --format cyclonedx1.5 # the dependency list in this report uv audit --frozen --no-dev --no-group docs # the vulnerability check uv build certutil -hashfile dist\clicknick-0.23.1-py3-none-any.whl SHA256 uv run python devtools/trust_report.py # regenerate this page into dist/trust/
To check the copy that was installed: uv tool dir shows the install folder; the wheel's files are
unpacked there, and pip download clicknick==0.23.1 --no-deps fetches the exact wheel
from PyPI for hashing. To install this exact version rather than the latest:
uv tool install clicknick==0.23.1.