Files
rea/scripts/verify/apple/code-signature.mjs
T
Kaoru0822andClaude Opus 5.5 57e91187cf Merge origin/main into feat/signature-posture
Follow #952's layout: the code-signature lane moves to
scripts/verify/apple/code-signature.mjs and uses the relocated bundle
fixture builder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:37:22 +00:00

193 lines
6.1 KiB
JavaScript

import assert from "node:assert/strict";
import { execFile } from "node:child_process";
import {
copyFile,
mkdir,
mkdtemp,
realpath,
rm,
writeFile,
} from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { promisify } from "node:util";
import {
artifactCli,
artifactMcpResult,
withArtifactMcp,
} from "../../lib/artifact-e2e.mjs";
import {
buildMacosBundleFixture,
preflightMacosBundleFixture,
} from "../../fixtures/apple/macos-bundle.mjs";
const exec = promisify(execFile);
await preflightMacosBundleFixture();
const root = await mkdtemp(join(tmpdir(), "rea-code-signature-"));
const facets = (signature) =>
Object.fromEntries(
signature.security_facets.map(({ facet, state }) => [facet, state]),
);
/** Re-sign a copy of one fixture executable ad hoc with the given options. */
const signedCopy = async (source, name, options) => {
const path = join(root, name);
await copyFile(source, path);
await exec("/usr/bin/xcrun", [
"codesign",
"--force",
"--sign",
"-",
...options,
path,
]);
return path;
};
const ENTITLEMENTS = `<?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>
<key>com.apple.security.cs.disable-library-validation</key><true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key><true/>
<key>com.apple.security.get-task-allow</key><true/>
<key>com.apple.security.cs.allow-jit</key><true/>
</dict></plist>
`;
try {
const { app } = await buildMacosBundleFixture(root);
const plain = await artifactCli("inspect-signature", app);
assert.deepEqual(plain.code_directory.flags.names, ["adhoc"]);
assert.equal(plain.verification.status, "valid");
// The opened bundle is reported by its canonical path.
assert.equal(plain.verification.path, await realpath(app));
assert.equal(plain.stapled_ticket.status, "absent");
assert.equal(plain.sealed_resources.status, "sealed");
assert.deepEqual(facets(plain), {
"library-validation": "not-enforced",
"dyld-environment-variables": "honored",
"debugger-attach": "allowed",
"executable-memory": "unrestricted",
"app-sandbox": "not-sandboxed",
});
// Deep verification reports the fixture's real nested code, all on disk.
assert.ok(plain.verification.validated_nested_code.length > 0);
assert.ok(
!plain.limitations.some((limitation) =>
limitation.includes("which does not exist"),
),
);
await withArtifactMcp(app, async (client) => {
const viaMcp = await artifactMcpResult(client, "inspect_signature");
assert.deepEqual(
{ ...viaMcp, provenance: [] },
{ ...plain, provenance: [] },
);
});
const tool = join(app, "Contents/Helpers/rea-tool");
const hardened = await artifactCli(
"inspect-signature",
await signedCopy(tool, "hardened", ["--options", "runtime"]),
);
assert.deepEqual(hardened.code_directory.flags.names, ["adhoc", "runtime"]);
assert.equal(hardened.stapled_ticket.status, "not-applicable");
assert.deepEqual(facets(hardened), {
"library-validation": "enforced",
"dyld-environment-variables": "ignored",
"debugger-attach": "blocked",
"executable-memory": "restricted",
"app-sandbox": "not-sandboxed",
});
const entitlements = join(root, "relaxed.entitlements");
await writeFile(entitlements, ENTITLEMENTS);
const relaxed = await artifactCli(
"inspect-signature",
await signedCopy(tool, "relaxed", [
"--options",
"runtime",
"--entitlements",
entitlements,
]),
);
assert.deepEqual(facets(relaxed), {
"library-validation": "disabled",
"dyld-environment-variables": "honored",
"debugger-attach": "allowed",
"executable-memory": "jit-allowed",
"app-sandbox": "not-sandboxed",
});
const flagged = await artifactCli(
"inspect-signature",
await signedCopy(tool, "flagged", ["--options", "library,restrict"]),
);
assert.deepEqual(flagged.code_directory.flags.names, [
"adhoc",
"restrict",
"library-validation",
]);
assert.equal(facets(flagged)["library-validation"], "enforced");
assert.equal(facets(flagged)["dyld-environment-variables"], "ignored");
const platform = await artifactCli("inspect-signature", "/usr/bin/true");
assert.notEqual(platform.code_directory.platform_identifier, null);
assert.equal(platform.verification.status, "valid");
assert.equal(facets(platform)["library-validation"], "enforced");
// The platform rules rest on a real `anchor apple` requirement check.
assert.ok(
platform.provenance.some(({ command }) =>
command.includes("-R=anchor apple"),
),
);
// Only deep verification sees a file added inside nested code.
const nested = join(root, "Nested.app");
await exec("/usr/bin/ditto", [app, nested]);
await writeFile(
join(nested, "Contents/XPCServices/Svc.xpc/Contents/added.txt"),
"unsealed",
);
const nestedTamper = await artifactCli("inspect-signature", nested);
assert.equal(nestedTamper.verification.status, "invalid");
assert.ok(
nestedTamper.verification.diagnostics.some((line) =>
line.includes("Svc.xpc"),
),
JSON.stringify(nestedTamper.verification),
);
await mkdir(join(app, "Contents/Resources"), { recursive: true });
await writeFile(join(app, "Contents/Resources/added.txt"), "unsealed");
const tampered = await artifactCli("inspect-signature", app);
assert.equal(tampered.verification.status, "invalid");
assert.ok(
tampered.verification.diagnostics.some((line) => line.includes("added")),
JSON.stringify(tampered.verification),
);
process.stdout.write(
`${JSON.stringify({
ok: true,
mocked: false,
cli: true,
stdio_mcp: true,
variants: [
"adhoc",
"runtime",
"runtime+entitlements",
"library,restrict",
],
platform_identifier: platform.code_directory.platform_identifier,
tampered_verification: tampered.verification.status,
nested_tamper_verification: nestedTamper.verification.status,
})}\n`,
);
} finally {
await rm(root, { recursive: true, force: true });
}