CommonCompute
Get startedDownload the Mac app
← All posts
May 14, 2026·8 min·Common Compute

How we sign and audit every task

The trust model behind running customer code on someone else's Mac.

The trickiest part of running a compute marketplace isn't dispatch — it's trust. When a customer submits a task and a provider runs it, three different parties need to believe the same thing about what happened:

  • The customer needs to know the task ran the way they asked, on hardware they didn't pick, with outputs they didn't see produced in real time.
  • The provider needs to know what they ran isn't going to compromise their Mac, exhaust their disk, or burn their network.
  • We need to know neither party is lying to the other before we settle billing.

This post walks through the trust model and the specific bits of code that enforce it.

The threat model

We don't trust ourselves. The coordinator is one bug or one breach away from sending a malicious task to a provider, so the provider's runtime treats every assignment as untrusted until proven signed. We don't trust the customer. The task payload — model name, parameters, input URL — could be crafted to escalate, exfiltrate, or denial-of-service the runner. We don't trust the provider. A misbehaving runner can lie about completion, claim partial work it didn't do, or sit on a task forever.

Each of those is a separate enforcement layer. The rest of this post is what each one looks like in the codebase.

Signed task assignments

The router (apps/router, written in TypeScript on Cloudflare Workers) signs every task assignment with an Ed25519 key it holds in Workers Secrets. The Mac app pins the corresponding public key in `Security/RouterPubkey.swift`.

When a provider's Mac receives a task_assignment frame over the WebSocket, the first thing it does is verify the signature against that pinned key, with two extra guards:

  • 5-minute clock-skew window. A signed assignment that's older than five minutes is rejected. Stops replay attacks even if the WebSocket is somehow MITM-able (it isn't — TLS 1.2+ and ATS enforce that — but defense-in-depth).
  • Replay protection via a nonce cache. Each signed envelope carries a nonce that is recorded *after* verification and refused if seen again, with a nonce TTL deliberately longer than the skew window so an expired-but-replayable envelope can't slip between the two. (An earlier version of this post described this as deduplication on task ID; the task-ID map is not a replay control — the real mechanism is the nonce cache in Security/Envelope.swift.)

The signature scheme is implemented in `Security/Envelope.swift`. If the verification fails, the assignment is dropped silently and a structured log line is emitted to the ai.commoncompute.app subsystem (visible via Console.app or the log show CLI).

Hash-pinned model downloads

A naïve compute marketplace ships customer-supplied model bundles to provider machines. That's a great way to ship malware to a thousand Macs at once. We solve it by publishing a manifest of allowed models — served from GET /v1/system/model-manifest — that maps model_id → SHA-256 + download URL.

The Mac app's ModelManager only downloads from URLs in the manifest, only fetches over HTTPS, and SHA-256s every byte before allowing a runner to load the bundle — refusing to load at all if the manifest carries no hash for that model, rather than falling back to unverified bytes. So a compromised *mirror* cannot serve a backdoored model: the per-file hash fails. Two limits we should state plainly, because an earlier version of this post overstated them: the manifest itself is not yet signature-verified on-device (the unsigned path is still accepted during alpha), so a compromised *manifest source* is a different and currently-open threat; and several runners load weights through their own framework's downloader rather than ModelManager, so those bytes are not hash-pinned at all. Both are tracked work.

This sounds paranoid until you see the surface area: ANE inference needs mlpackage bundles, Whisper needs Core ML conversions of OpenAI's checkpoints, image upscale needs Real-ESRGAN weights, and each of those is hundreds of megabytes of trusted binary that runs in-process on the provider's Mac.

Trusted URL gating

The other vector is task inputs. A customer submits "transcribe this audio file" with a URL. The naïve implementation fetches that URL on the provider's Mac and pipes the bytes to Whisper. That URL is attacker-controlled.

We added a single chokepoint in `Networking/TrustedDownload.swift` for every job input. It refuses anything except HTTPS to public hosts. Loopback (127.0.0.0/8, ::1), RFC1918 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), AWS metadata (169.254.169.254), and link-local addresses are all rejected — including via HTTP redirect, which is the part naive implementations miss.

Magic-byte checks confirm the downloaded content matches what the runner asked for. A Whisper runner that requested an audio file will refuse to operate on a payload whose first eight bytes don't match a known audio container. That blocks the variant of the attack where the URL serves audio to your validator and a Python script to your runner.

Hardened runtime and entitlements

The Mac app ships with Apple's hardened runtime enabled. It declares one capability entitlement: com.apple.security.network.client, so it can make outbound HTTPS calls. (An earlier version of this post also listed com.apple.security.keychain.access-groups; that entitlement was removed in July 2026 — the app doesn't share Keychain items with anything else, so the OS falls back to its own Team-scoped bundle ID.) The full list lives in `CommonCompute.entitlements`.

What we deliberately don't declare:

  • com.apple.security.network.server — no inbound listeners. The app cannot be reached on a port by anything on your network.
  • com.apple.security.device.camera / microphone — no AV access. Even if a runner crashed in a creative way, it can't grab your webcam.
  • com.apple.security.files.* — we declare no file-access entitlements. Being straight with you about what that does and doesn't buy: the app is not App-Sandboxed today, so this is the absence of a request rather than an OS-enforced boundary. Job inputs land in an app-managed working directory under ~/Library/Caches, and containment there rests on the input gate above plus the runner's own behavior — not on a kernel sandbox. The same caveat applies to the two bullets above: no network.server and no camera/microphone entitlement means we never ask for those, which is meaningful, but without App Sandbox it is not the OS stopping us. Turning on App Sandbox is real, multi-week work we still owe you, and we would rather say so than imply a container that isn't there.

The one entitlement that does raise an eyebrow on a security audit is com.apple.security.cs.disable-library-validation — but it's there for Sparkle. Sparkle's update flow requires it because Sparkle's helper binaries are signed by Sparkle, not by our team. The compensating control is EdDSA signature verification on every update: even if library validation is off, an unsigned update binary cannot replace the running app.

Receipts: who signed what

Today, the coordinator signs every task *assignment* (above) and records the result that comes back on completion; billing settles against that record. The piece we're still building is the customer-facing receipt: a per-task artifact carrying the input hash, output hash, model hash, and price, signed so you can verify it offline against our published key — no API call.

We're shipping that in two honest steps, and we'd rather describe each as it lands than claim the finished picture now:

1. Platform-signed receipts (shipped). Every completed job gets a receipt carrying the input hash, output hash and price, retrievable from GET /v1/jobs/:id/receipt. To be precise about what it is: the signature is HMAC-SHA256 with a key we hold — not the Ed25519 assignment key, as an earlier version of this post said. That means it proves the record came from us and hasn't been altered, but because HMAC is symmetric it is *not* something a third party can verify independently. 2. Provider co-signature (after that). The provider's Mac generates a Secure-Enclave-bound key at enrollment and signs the output hash, so the receipt is co-signed by the device that ran the work. To be precise about what that proves: it binds the result to the *same physical Mac that enrolled*, not to an un-tampered app — Apple's App Attest doesn't run on macOS, so we don't claim hardware attestation we can't deliver. Output *correctness* is handled separately, by the golden-task and replication checks that gate payouts.

Until co-signature lands, the receipt simply carries no device signature field at all — the per-device signing work exists on a branch but is not shipped, and we would rather the artifact be plainly platform-only than imply a device attestation that isn't there.

Crash and diagnostics: opt-out, no third-party SDK

The Mac app subscribes to Apple's MetricKit for crash and performance diagnostics. MetricKit delivers payloads ~24 hours after the event, which we forward to /v1/diag/crash after running them through a PII redactor that strips email addresses, API keys, AWS credentials, and Bearer tokens before persisting.

The whole diagnostics pipeline is gated on a Settings → Advanced toggle. It defaults to on, but a click turns it off and the MetricKit subscription is removed live without an app restart. The implementation is in `DiagnosticsReporter.swift`. We don't embed any third-party crash SDK — no Sentry, no Bugsnag, no Crashlytics — both because we want to keep the binary minimal and because the supply-chain risk of a third-party crash reporter on machines running customer workloads isn't a tradeoff we're willing to make.

What we haven't done yet

In the spirit of being honest about this, the things you'd reasonably expect a serious shop to have that we don't yet:

  • External penetration test. Scoped for after v1.7. Results will be posted in summary form on /security once remediation lands.
  • SOC 2 Type II. Targeting Q1 2027. We won't sell a certification we don't have; we'll roadmap it transparently.
  • Bug bounty program. No paid bounty yet. The disclosure process is documented in SECURITY.md and we publish a researcher hall of fame for valid reports.

The trust posture is built brick by brick. If you find a brick out of place, email security@commoncompute.ai — we acknowledge within 7 days.

Common Compute is a marketplace for AI workloads on Apple Silicon Macs. Provider payouts use Stripe Connect and quote customers a locked per-task price. Sign up — every job is quoted before it runs, billed only on success.
More from the blog