---
title: "Every Gate Was Green"
description: "Windows refused 40 consecutive Foxl updates, Intel Macs had no image features, and v0.7.1 shipped unable to start. Every automated check passed for all of it."
author: "Foxl Team"
date_published: "2026-09-04"
date_modified: "2026-09-04"
canonical_url: "https://foxl.ai/blog/v0-7-every-gate-was-green"
markdown_url: "https://foxl.ai/blog/v0-7-every-gate-was-green/index.md"
image: "https://foxl.ai/blog/v0-7-release-cover.png"
social_image: "https://foxl.ai/blog/social/v0-7-every-gate-was-green.png"
content_type: "Deep dive"
topics: ["Windows updates","Code signing","Content Security Policy","Release engineering","Measurement"]
products: ["Foxl Agent","Foxl Notes","Foxl Code"]
---

<!-- Generated by scripts/blog-publishing.mjs; do not edit. -->

# Every Gate Was Green

> Foxl v0.7.0 and v0.7.1 closed about ninety fixes. Four of them had been true for months while every automated check passed: Windows had refused forty consecutive updates because our certificate is self-signed and the check only compares a publisher name when Windows calls the signature fully valid; Intel Macs had no image features at all, silently, because the universal build only ever carried the Apple silicon copy of the image library; every Windows build stamped its own version 0.0.0. Then v0.7.1 shipped unable to start - the new window security policy refused the app's own start-up script - and was withdrawn. This is what each of them looked like, and why a check that asserts a spelling is worse than no check.

- Author: Foxl Team
- Published: 2026-09-04
- Last reviewed: 2026-09-04
- Reading time: 9 minutes
- Canonical HTML: [https://foxl.ai/blog/v0-7-every-gate-was-green](<https://foxl.ai/blog/v0-7-every-gate-was-green>)

![Four readings from Foxl v0.7.0 to v0.7.2 that exposed failures no internal check could see: Windows reporting Status UnknownError for forty releases of refused updates, a Content Security Policy blocking the app's own start-up script at chat line 86, a universal Mac build carrying only the arm64 image library so Intel Macs had no image features, and every Windows build stamping its server bundle version 0.0.0.](<https://foxl.ai/blog/v0-7-release-cover.png>)

Foxl v0.7.0 shipped on September 3 and v0.7.1 on September 4. Between them they closed about ninety fixes. This post is about four of them, and about one release that had to be taken back.

The thing the four have in common is not their subject. It is that every automated check we had was green while each of them was true, and in three cases had been true for months. None was found by reading our own code more carefully. Each was found by asking the other side what it saw.

## Windows had not accepted an update since July

Foxl updates itself. On Windows it had not done so since v0.5.7, released on July 30. **Forty releases were downloaded, checked, and thrown away.**

The updater is configured to verify that an update was signed by us before running it, which is the right setting. The library implementing that check asks Windows to inspect the signature, and it compares the publisher name only when Windows reports the signature *fully valid*. Our certificate is self-signed, so Windows never reports that. It reports this instead, and this is the real output from a real Windows machine inspecting the installer we published:

```
Status        : UnknownError
StatusMessage : A certificate chain processed, but terminated in a root
                certificate which is not trusted by the trust provider
Subject       : CN=Foxl AI, O=Foxl AI, L=San Francisco, S=CA, C=US
```

The comparison that would have accepted our own name was never reached. The installer was correct, the signature was correct, the setting was correct, and the update was discarded every time.

Nothing said so. The refusal wrote one line into a log file inside the user's AppData folder and nothing appeared on screen. Our release checks asserted that the setting was present and the publisher name was right, which is exactly the state that refuses everything. A Windows user who installed Foxl in July was still running the July build, and both they and we would have described the app as up to date.

Foxl now performs that check itself. It still refuses an unsigned installer, one altered after signing, and one signed by anybody other than us, and a refusal now appears in the notification bell rather than only in a file. **This one update has to be installed by hand:** the fix travels inside the new build, so the build you are running still cannot fetch it. Download it once from foxl.ai and automatic updates work from then on.

The underlying cause is not solved, only handled. A certificate that Windows trusts without being told costs money and has to accumulate reputation, and until we buy one Windows will keep showing a warning the first time somebody runs the installer. That is a separate, still-open item.

## Intel Macs had no image features at all

Show Foxl a picture and it reads it. Ask it to generate one and it shows you a preview. Both need a compiled image library, and that library ships as a separate small binary per processor type.

The Mac download is a universal app: one file that runs on both Apple silicon and Intel. **It only ever contained the Apple silicon copy of that library.** On an Intel Mac those features did nothing whatsoever, and showed no error, because the app is written to carry on quietly when the library is unavailable - which is correct behaviour for an optional dependency and exactly wrong when the dependency is missing by accident.

This is the failure mode we keep finding: the app did not crash, no message was logged as an error, and there was no red anything. A user on an Intel Mac would have concluded the feature did not exist.

The build now stages both copies, checks that each one is genuinely for the processor it claims, and *stops* rather than publishing a Mac app that is missing one. The check is in the build rather than in a test because it is a property of the artifact, not of the source.

## Every Windows build stamped its own version 0.0.0

Foxl's background service records which version is serving, so the app can tell you when the two disagree. That number is read out of a file during the build.

On Windows the build runs under a Unix-like shell whose file paths the JavaScript runtime cannot resolve. The read failed, silently, and fell back to a default. Here are three builds of the same commit:

```
macOS    bundle version: 0.7.1
Linux    bundle version: 0.7.1
Windows  bundle version: 0.0.0
```

It had been doing that for as long as the line existed. What exposed it was an unrelated change in the same release that made a *different* read of the same file fail loudly instead of guessing - the version of the image library to install. That read refused to continue, the Windows build stopped, and the 0.0.0 was sitting right above it in the log.

This is the argument for loud failures in one line. Two reads, same bug, same file, same shell. The one that guessed hid for months. The one that stopped was found in an afternoon, and it found the other.

## And then v0.7.1 could not start, and was withdrawn

v0.7.0 added a security policy to the desktop window. That window holds your sign-in tokens and every bridge between the page and your machine, so a single injected script in it is not a page-level bug - it is access to your computer. Locking it down was the right thing to want.

The policy forbade inline scripts. The app ships one: the local server hands the page a key it needs to make any request at all, and it hands it over as an inline script. **The policy refused the app's own start-up script.**

The result, from a user's log, repeating roughly twelve times a second:

```
[renderer] Executing inline script violates the following Content Security
Policy directive "script-src 'self' ...". (chat:86)
[renderer] Failed to fetch providers: TypeError: Failed to fetch
```

The window flickered and never loaded. No error card appeared, because the code that would have drawn one needed the same key. Quitting produced a modal reading "A JavaScript error occurred in the main process" - a second, unrelated bug in the same release, where three pieces of start-up work ran up to two seconds after the window appeared without checking whether the window was still there.

v0.7.1 was withdrawn. Its release was deleted, the download link went back to v0.7.0, and v0.7.2 replaces it. **If you installed v0.7.1 it updates itself to v0.7.2** - measured on a machine running the broken build, which moved from 0.7.1 to 0.7.2 on its own.

That last sentence is a correction, and it is worth keeping rather than quietly fixing: our first note for this release said the broken build could not update itself. It can. The policy governs the WINDOW, and the updater runs in the main process, which was never blocked - so the app that could not show you anything was still checking for and installing updates the whole time. We wrote the pessimistic version because it sounded safe, and then a machine did the opposite in front of us.

Two things about the shape of this, since it is the most expensive mistake in the three releases.

**The policy could never have worked, and the reason is arithmetic.** A policy can permit a specific inline script by listing a fingerprint of its exact text. The key in that script is freshly random every time the app starts, so its fingerprint is different every time. There was no value that could have been listed. This was not a wrong constant; it was a mechanism that cannot apply.

**Our own check asserted the broken policy was correct.** There is a test whose job is to guard that policy, and it passed - because it compared the policy against what the policy was intended to be, and never asked whether the app could start under it. There is also a probe that launches a real app window. It exists, and it was not in the set that had to pass. So the release went out with a green board.

That check now asserts the opposite: inline scripts must be permitted, and a fingerprint must *not* be present. The second half matters more than it looks. In this policy language, listing any fingerprint silently cancels permission for inline scripts - so the obvious repair, adding the permission next to the fingerprint that was already there, would have changed nothing while looking like a fix. Both mistakes now fail the check, and both were tested by making them on purpose.

The hardening is not finished and the code says so where somebody will read it. The right fix is to stop shipping that key in a script at all. Everything else v0.7.0 added to the window is still there: it will not evaluate code from a string, will not let itself be framed, and will not load a script from anywhere but itself.

## What we changed about how we check

Four fixes, one withdrawal, and a pattern worth naming. Every one of these was invisible from inside the repository. What found them was asking the destination: what does Windows say about this installer, what is actually in this Mac app, what version did this build stamp, does the app start.

The concrete change is that a check may no longer assert a spelling. Four separate guards in this release went red on *correct* code because they pinned the exact text of an implementation rather than the property it was protecting - and one of them, had we satisfied it the easy way, would have argued us into replacing a constant-time security comparison with a weaker one. A guard whose cheapest repair makes the code worse is worse than no guard.

The rest of v0.7 is in the [changelog](<https://foxl.ai/changelog>): a sign-in link that needs a press before it signs you in, the long-lived credential on iPhone moved into the Keychain, mobile sign-in no longer carrying a session in a URL, a ceiling on shared workspace storage, and a safety code you can read to confirm a remote connection is really your own machine.

## References and further reading

1. [Foxl changelog](<https://foxl.ai/changelog>) - Release
2. [Download Foxl](<https://foxl.ai/#download>) - Reference