microsoft/typescript-go · error

Signed file has no macOS entitlements

Error message

Signed file has no macOS entitlements: ${filePath}

What it means

verifyTypeScriptMacEntitlements runs `go tool quill describe --output json` on a signed darwin binary and expects an entitlements blob (details[0].superBlob.entitlements.entitlements as a string). If the binary carries no entitlements at all (unsigned, or signed without an entitlements plist), verification throws.

Solutions

  1. Sign macOS binaries with the standard entitlements plist before running verification
  2. Run `go tool quill describe <file>` manually and confirm an entitlements blob is present
  3. Pin or update quill to the version whose JSON schema the script parses
Defensive patterns

Strategy: validation

Validate before calling

import { $ } from "execa";
const { stdout } = await $`go tool quill describe --quiet --output json ${filePath}`;
const hasEntitlements = typeof JSON.parse(stdout)[0]?.superBlob?.entitlements?.entitlements === "string";
if (!hasEntitlements) throw new Error(`Re-sign ${filePath} with entitlements before continuing release.`);

Type guard

/** @param {unknown} d @returns {boolean} */
function hasEntitlementsBlob(d) {
  return typeof d?.[0]?.superBlob?.entitlements?.entitlements === "string";
}

Prevention

When it happens

Trigger: The macOS signing step was skipped or ran without entitlements before verification; quill's JSON schema changed so the entitlements field is absent.

Common situations: Release tasks reordered so verification precedes entitlement-signing; quill version drift changing the describe output; ad-hoc signing without entitlements.

Related errors


AI-assisted analysis of microsoft/typescript-go@1bcfa18d79 (2026-08-16). Data as JSON: /api/errors/9ed88b9976866914. Report an issue: GitHub.

Appendix: source

Thrown at Herebyfile.mjs:1513

    return `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
${entries}
</dict>
</plist>
`;
}

/**
 * @param {string} filePath
 */
async function verifyTypeScriptMacEntitlements(filePath) {
    const { stdout } = await $pipe`go tool quill describe --quiet --output json ${filePath}`;
    const details = JSON.parse(stdout);
    const entitlements = details[0]?.superBlob?.entitlements?.entitlements;
    if (typeof entitlements !== "string") {
        throw new Error(`Signed file has no macOS entitlements: ${filePath}`);
    }
    for (const entitlement of typescriptMacEntitlements) {
        const escapedEntitlement = entitlement.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
        if (!new RegExp(`<key>\\s*${escapedEntitlement}\\s*</key>\\s*<true\\s*/>`).test(entitlements)) {
            throw new Error(`Signed file is missing macOS entitlement '${entitlement}': ${filePath}`);
        }
    }
}

/**
 * @typedef {"win32" | "linux" | "darwin" | "aix" | "android" | "freebsd" | "netbsd" | "openbsd" | "sunos"} OS
 * @typedef {"x64" | "arm" | "arm64" | "ia32" | "ppc64" | "loong64" | "mips64el" | "riscv64" | "s390x"} Arch
 * @typedef {"Microsoft400" | "LinuxSign" | "MacDeveloperHarden" | "8020" | "VSCodePublisher"} Cert
 * @typedef {`${OS | "alpine"}-${Exclude<Arch, "arm"> | "armhf"}`} VSCodeTarget
 * @typedef {{ name: string; sourceDir: string }} VsixExtensionPackage
 * @typedef {{ nodeOs: string; vscodeTarget: string; sourceDir: string; extensionDir: string; vsixPath: string; vsixManifestPath: string; vsixSignaturePath: string }} VsixExtension
 * @typedef {{ GOOS: string; GOARCH: string }} GoDistTarget
 * @typedef {{ os: OS; arch: Arch; cert?: Cert; vsix?: boolean; alpine?: boolean }} Platform

View on GitHub (pinned to 1bcfa18d79)