v1.1.1 — security hardening, an MIT license, and one-tag releases.

Four CodeQL alerts closed, the project relicensed under MIT, and a GitHub Actions pipeline that turns a v* tag into a draft release with macOS and Windows artifacts attached. No behaviour changes for end users — same v1.1 app, sturdier underneath.

Path-traversal defense

CodeQL flagged two "Uncontrolled data used in path expression" alerts in the server's filename handling. Both are now closed.

resolveOutputPath() and the /api/download/:filename handler now apply a defensive path.basename() and verify the resolved path stays inside the configured output directory. Filenames containing traversal sequences — .., absolute paths, OS-specific separator tricks — either land safely inside the output folder or are rejected outright.

The server still binds to 127.0.0.1, so this was never reachable from the public internet. The fix raises the bar for the one realistic threat: a malicious local webpage that has discovered the loopback port.

Rate limiting on the loopback API

express-rate-limit now guards two endpoints: 100 requests/minute on conversion and 300 requests/minute on download. Standard RateLimit response headers are emitted so anything legitimate sees its budget.

Same threat model as above — the server is loopback-only. The cap is generous enough that real batch conversions never bump into it while still bounding what a hostile local page can do. Closes the two CodeQL "Missing rate limiting" alerts.

MIT license

LocalPix is now formally MIT-licensed. A LICENSE file ships in the repo root, with matching license and author fields in package.json. Nothing changes for end users; the move just makes the existing intent (use it, fork it, do what you like) legally legible to anyone who asks.

GitHub Actions release pipeline

A new .github/workflows/release.yml takes over what used to be a two-machine manual ritual. Pushing a tag matching v* triggers parallel macOS and Windows builds, then drafts a GitHub Release with both artifacts attached and the release body auto-extracted from CHANGELOG.md.

The practical effect: the gap between "I tagged a version" and "users can download it" is now measured in CI-runner minutes rather than whichever laptop I happen to be near.

scripts/build-icns.sh

A small reusable shell script that turns any 1024×1024 PNG into a macOS .icns bundle. Used to build both the light and dark icon variants — committed mostly so the next icon refresh doesn't require re-deriving the iconutil incantation from memory.

Notes

Three CodeQL "DOM text reinterpreted as HTML" alerts in public/index.html remain open as won't-fix for this release. All interpolated values flow through escHtml() before reaching the DOM, so none of them are reachable XSS. The honest fix is a full DOM-API refactor — replacing the string-built HTML with createElement and textContent — which is on the docket for v1.2.

How to upgrade

Download the v1.1.1 .dmg or .exe from the downloads page and replace your existing install. WebP output remains byte-identical to every prior LocalPix and LocalConvert release; hashed pipelines don't need to change anything.

← All posts · Previous: v1.1 →