Security
ClickNick is a Windows desktop tool that reads and edits CLICK projects and adds nickname autocomplete to CLICK Programming Software.
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.
This page describes its file access, network connections, code execution, and installation for IT and security review. ClickNick is open source (AGPL-3.0), written and maintained by one author.
Each release includes a trust report and dependency inventory, generated from the release source, built package, and dependency lock file. These are release checks, not a formal security audit. A static scan shows what the code contains; it cannot prove what it never does.
Software characteristics
ClickNick installs no Windows services, drivers, or scheduled tasks. It has no telemetry, analytics, or automatic update agent. Updates are initiated by the user.
ClickNick's own package is readable Python source, with no obfuscated or encrypted modules, packed executables, or compiled code. Its installation also includes a Python interpreter and dependencies with native binaries, identified in the release report. Source code for every dependency is publicly available.
The default uv installation stays under the user's profile. Project exports and durable workspaces are written to the folders the user chooses.
Runtime behavior
- Project database access. ClickNick reads and writes
SC_.mdbin the temporary folder CLICK creates when it opens a project. It uses Windows ODBC, or a 32-bit PowerShell worker using the Windows Jet engine when a 64-bit Access driver is unavailable. - Autocomplete. ClickNick reads and fills text fields in CLICK Programming Software
through standard Windows APIs, then sends Enter, Tab, or Escape after a nickname is
selected. It installs no keyboard hook and injects no code into
Click.exe. - Editor command listener. While ClickNick is running,
clicknick-clican connect to its local TCP port to read or stage address edits, check workspace code, and apply ladder proposals. This listener runs even when the offline console is closed. It binds tolocalhost, with the port chosen by Windows. Connections are unauthenticated, and ClickNick does not check the connecting process's user identity. Other local users and processes that can reach the port can connect. Address edits are staged and undoable; they reach the project when the user saves. - PLC connection. The Dataview editor connects over Modbus TCP (port 502 by default) after the user asks to go live, to the address they enter. It reads values and writes values when the user clicks Write.
- Generated Python. On project connection, ClickNick translates the ladder into Python and runs the generated code in-process to build the model behind Check Program. This step does not run files found in the project folder.
- Workspace Python. Check Program, applying a proposal, and the offline console run
the user's editable workspace (
src/plc,run.py,project_to_csv.py) in a child Python process. Thetag applycommand executes workspacetags.pyinside ClickNick to export its nickname changes. These are intentional code execution features, with the signed-in user's permissions. Treat a workspace received from outside like any other script folder. - Documentation links. Clicking a documentation link opens
github.comorpyrung.comin the default browser.
ClickNick has no background internet connection for telemetry or updates. Installation downloads are described below; workspace scripts can perform whatever file or network operations their code requests.
What endpoint monitoring will see
The paths below describe the default uv installation.
| Event | Cause |
|---|---|
Unsigned clicknick.exe in %USERPROFILE%\.local\bin starts Python from %APPDATA%\uv\tools\clicknick\ |
Normal launch. uv generates the small entry-point launcher; ClickNick runs as python.exe or pythonw.exe. |
Python starts SysWOW64\...\powershell.exe -EncodedCommand ... |
The Jet database worker, on machines without a 64-bit Access driver. The full command and script identity are below. |
Python listening on 127.0.0.1:<random port> |
The editor command listener for clicknick-cli; the offline console uses a separate pyrung live connection for simulation. |
| Python starts a child Python process | Check Program, applying a proposal, or the offline console running the user's workspace. |
Python connects to <PLC address>:502 |
Dataview editor, after the user asks to go live. |
Native .pyd, .dll, and .exe files appear under %APPDATA%\uv\ |
The Python interpreter and dependencies such as pywin32 and pyodbc. pywin32 includes Pythonwin.exe and pythonservice.exe; ClickNick does not run them. |
HKCU\Environment PATH changed |
The uv installer adds its executable directory to the user's PATH. |
The database worker's command line is:
%SystemRoot%\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -NonInteractive -EncodedCommand <base64>
The payload is the text of the shipped clicknick/resources/jet_sidecar.ps1 script,
with line endings normalized to LF, encoded as UTF-16LE and then Base64. Each release
report includes the shipped file's SHA256 for review. Project paths and values travel
separately as JSON on standard input; they are not inserted into PowerShell source.
The encoded invocation keeps the worker usable under Windows PowerShell's Restricted
execution policy, which permits commands but blocks script files invoked with -File.
It does not change execution policy or relax application-control rules. Endpoint tools
may flag the invocation; any exception depends on the controls in use. To use Access ODBC
without falling back to PowerShell, start clicknick --db-backend odbc. The
--db-backend none option uses CSV mode without either database backend.
Installation and updates
uv is an open-source Python package manager from Astral. For ClickNick, it downloads the package and dependencies from PyPI, installs them in an isolated environment, and creates the launcher. It also downloads a Python interpreter if needed. ClickNick does not call uv at runtime.
Installation and upgrades use these hosts:
| Purpose | Hosts |
|---|---|
| uv installer | astral.sh |
| Python builds from python-build-standalone | github.com, objects.githubusercontent.com |
| ClickNick and Python dependencies | pypi.org, files.pythonhosted.org |
uv checks package files against hashes published by PyPI and Python downloads against hashes built into uv. Installing ClickNick's wheel unpacks files; the wheel has no install-time scripts.
If a script piped into PowerShell is against policy, install uv with
winget install --id astral-sh.uv. If your policy prefers pip, install ClickNick into a
virtual environment using Python 3.11 or newer. See Install.
To update: uv tool upgrade clicknick.
ClickNick pins its whole dependency tree to exact versions, so installing a given ClickNick
version installs exactly the dependency versions in that release's report. Dependency
updates, including security fixes, arrive only through a new ClickNick release, and every
release runs uv audit before it ships.
The trust report
Each release includes clicknick-trust-report-<version>.html, a self-contained page with
no scripts or external resources, and clicknick-sbom-<version>.cyclonedx.json, the
dependency inventory in CycloneDX 1.5 format. Both are attached to
the GitHub release and mirrored under Release reports.
The report includes the security narrative from this page in the tagged source, followed by four generated sections. Updating this page updates future reports automatically; published reports retain the wording from their release. The narrative describes intended behavior, while the checks provide the specific evidence listed below:
- Release summary. Version, Python requirement, distribution counts, known
vulnerabilities from
uv audit, non-PyPI dependency count, unresolved license count, and SHA256 hashes of the SBOM, wheel, and PowerShell worker script. - Release checks. Mechanical checks over the lock file, built wheel, and ClickNick source: no HTTP client or telemetry dependency, no HTTP, FTP, or mail client imports, no download commands in shipped scripts, no Python decoded at runtime, no compiled code in the wheel, listeners bound to localhost, subprocesses limited to the same Python interpreter and built-in Windows PowerShell, and every dependency pinned to its locked version. A failed check fails the release.
- Runtime dependencies. Package, version, pin, source, license, which package uses it, native code, and purpose for the release's runtime dependency set.
- Source transparency. The source locations behind the checks, including URLs in
runtime string literals, subprocess launch sites, and
execcalls.
Verify it yourself
To install a specific ClickNick release: uv tool install clicknick==0.23.1.
The report can be regenerated from the tagged source:
git clone https://github.com/ssweber/clicknick
cd clicknick
git checkout v0.23.1 # the release under review
uv export --frozen --no-dev --format cyclonedx1.5 # the dependency list
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 the report into dist\trust
Compare the wheel hash with the
PyPI release page and with the report.
uv tool dir shows where the installed package's files live.
uv build reads the pinned build dependencies from pyproject.toml. Hatch uses stable
archive timestamps by default; leave SOURCE_DATE_EPOCH unset to use that default.
Git attributes select LF line endings for fresh checkouts. Compare the rebuilt wheel's
SHA256 with the release report to verify that its bytes match.
Use a clean checkout and the build recipe from the release tag being reviewed. Older tags retain their original build settings, including Windows line-ending conversion. Normalizing a new checkout does not change the bytes or hashes of those published packages.
Where things live on disk
Default locations for an installation through uv:
| Item | Location |
|---|---|
| uv itself | %USERPROFILE%\.local\bin\uv.exe |
| Python interpreter downloaded by uv | %APPDATA%\uv\python\ |
| ClickNick and its dependencies | %APPDATA%\uv\tools\clicknick\ |
| Launcher stub | %USERPROFILE%\.local\bin\clicknick.exe |
| uv download cache | %LOCALAPPDATA%\uv\cache\ |
| Live-session files | The CLICK temp folder for the open project, or %LOCALAPPDATA%\ClickNick\live\. CLICK does not read these files. |
| Generated engineering workspace | %TEMP%\clicknick_* while running, or the folder the user chooses for a durable workspace |
| Project data it edits | SC_.mdb in %LOCALAPPDATA%\Temp\CLICK (...)\. CLICK writes it back into the .ckp on save. |
Uninstall
This removes ClickNick's tool environment and launchers. User-saved workspaces and exports remain in their chosen folders.
uv, its downloaded Python interpreters, and its cache remain available for other tools.
Removing %APPDATA%\uv\ also removes other uv tool environments and shared Python builds.
Remove those shared directories only if you are retiring uv and all tools that use them;
the same applies to removing %USERPROFILE%\.local\bin from PATH, since other commands may
live there.
Reporting a problem
Report security issues through the repository's private vulnerability reporting form. For other problems, open an issue. Include the release version and its trust report.