A macOS build may keep passing while openssl silently resolves to a different default.
Fastest fix: audit every unversioned openssl call in your workflow and scripts, then test certificate, key, signing, TLS, and native dependency jobs; explicitly select OpenSSL 3 wherever your task requires it.
This change matters to IT and platform leads who maintain enterprise macOS CI images and toolchains.
If you own certificate, signing, or TLS scripts, focus on assumptions about default commands and output.
If your iOS or macOS builds compile native libraries, validate those dependencies in a representative workflow before changing production.
Last updated October 23, 2026. Schedule and scope checked against the GitHub runner-images change announcement.
OpenSSL 4 migration for GitHub Actions macOS CI: the announced scope
GitHub has announced a planned change, not a completed rollout. The announcement schedules a gradual switch from the default openssl command to OpenSSL 4 during November 2–8, 2026, for macOS 26 Intel and Arm64 images and Xcode 27 Arm64 images. It also says OpenSSL 3 will remain available through a versioned Homebrew prefix. The schedule may change as compatibility is checked. Confirm the current announcement and actual runner image before acting on those dates. (GitHub’s change notice)
That scope is narrower than “all macOS CI,” and it does not establish a change for Linux or Windows runners. Nor does a runner label alone prove which executable a particular job used. GitHub-hosted images can change over time, so use job logs and the image’s software inventory to confirm the environment your workflow actually received. GitHub describes the available hosted runner options in its runner reference, and explains how to inspect installed software in its hosted-runner documentation.
Do not treat the planned date as a deadline after which every build will fail. First establish whether an affected job runs an unversioned openssl, and whether the job depends on OpenSSL 3 behavior. Compatibility is a property of your commands, inputs, outputs, and downstream consumers—not of a runner label by itself.
Where an unversioned command can enter your build
A workflow can depend on the default without mentioning OpenSSL 3 anywhere. A step may call openssl directly; a shell script may call it indirectly; a build script or reusable action may invoke it after changing directories or adjusting PATH. Search workflow YAML, repository scripts, build tooling, and action inputs. Include scripts downloaded or invoked by the pipeline if your team controls or audits them.
For every relevant job, capture the command’s resolved path and version in the job log. For example, a diagnostic step can record the output of command -v openssl and openssl version -a. Those commands help show what the job sees at execution time; they do not prove that all later steps use the same executable if a script modifies PATH.
| Workflow evidence | Likely dependency | Risk rating | Decision |
|---|---|---|---|
An unqualified openssl call, with no version or path check |
The runner’s default command | High until verified | Run the job on the target image and record the resolved path and version |
| A versioned executable or explicit versioned Homebrew prefix | A selected OpenSSL installation | Lower, but still test the job | Confirm the selected path exists and that the linked libraries are the expected ones |
| No direct call found, but a build or reusable action may invoke OpenSSL | An indirect dependency | Unclear | Inspect the action or build logs; do not classify it as unaffected based only on a repository search |
| No OpenSSL use found in the job, its scripts, or its build dependencies | No known direct dependency | Lower | Keep the evidence with the runner image details and revisit if the workflow changes |
Treat “no direct call found” as a lead, not proof. A dependency installer or native build can invoke OpenSSL underneath a top-level command. Compare the workflow’s logs, script contents, and dependency build output before closing the review.
To inspect available runner software, use the image information associated with the job rather than inferring it from the runner label. For scheduled or long-lived workflows, retain the image details beside the diagnostic output. That makes it possible to distinguish a code change from a runner-image change during later incident review.
Does the workflow rely on OpenSSL 3 command behavior?
A script can select OpenSSL 3 implicitly even when it never checks the version. Look for branches that parse openssl version, commands that assume a particular default, and shell logic that depends on option handling or formatted output. A version comparison may be especially fragile if the script treats the full output as a fixed string rather than checking a defined property.
Also inspect command options and output parsing. OpenSSL documents command-line formatting options in its format-options reference. Use that documentation to identify behavior worth testing; do not infer from a documented difference that your project will fail. The practical question is whether your script’s inputs, options, exit-code handling, and output parsing match the version it will execute.
Classify each use by what it does:
- Version discovery: Does a script branch on a parsed version string or expect a particular format?
- Command options: Are options accepted and interpreted as the task expects?
- Output parsing: Does another command consume text whose formatting or defaults may differ?
- Error handling: Does the script check exit status, or does it assume that a non-empty output means success?
- Library selection: Does a compiler or package step link against an explicit library path, or resolve one from the environment?
Keep “potential incompatibility” separate from “confirmed failure.” The first tells you what to test. Only a reproducible workflow result establishes the second.
Certificate, signing, and TLS jobs need artifact-level checks
Find every job that uses OpenSSL to create or inspect certificates, handle private keys, validate signatures, or support TLS configuration. A command can complete successfully while a later stage rejects the result, so check the produced artifact and the system that consumes it. Confirm that existing tests and audit records cover the properties your release process depends on.
For Apple code signing, keep the checks tied to your actual distribution workflow. Apple explains certificate roles in its code-signing certificate technical note and describes the process for creating distribution-signed Mac code. Use those references to frame the checks, then validate your own signing output, verification results, and downstream delivery path.
A focused acceptance run should cover the following:
- Create or inspect a certificate with the same workflow inputs and secrets your pipeline uses.
- Verify the private-key handling path without exposing secret material in logs.
- Sign a representative build artifact, then run the project’s normal signature verification.
- Exercise the TLS-related job or integration test that consumes the generated certificate or configuration.
- Confirm that a downstream build, packaging, or release stage accepts the output.
- Retain the relevant logs, runner image details, and verification results in the team’s existing change record.
Do not use a generic command example as evidence of production compatibility. A successful local shell command does not verify the runner’s environment, CI secrets, signing identity, or downstream consumer.
Keep the evidence focused on behavior: the selected executable, the generated artifact, the verification result, and the consumer’s result. Avoid storing private keys or other secrets in diagnostic logs.
Native dependency builds can bind to a version or library path
An iOS or macOS job may not call openssl itself and still depend on it while building a native dependency. Check install scripts, compiler invocations, package configuration, and build logs for versioned paths, header locations, and library linkage. A build that finds headers from one installation but links libraries from another deserves investigation.
For a questionable dependency, isolate the build from release signing and production deployment. Use the same runner family and relevant build inputs, then record the resolved tool paths and compiler output. Check both the build result and the resulting application or test behavior. This is project-level validation: one public repository’s workaround does not prove that every team has the same dependency or failure mode.
If the dependency manager downloads prebuilt binaries, distinguish that path from a source build. The former may consume a packaged library; the latter may discover headers and libraries from the runner. Your logs should show which route the job took. If they do not, add enough diagnostic output to resolve that uncertainty before changing the production workflow.
A controlled verification gate beats a blanket migration
Use representative workflows to decide whether to pin a version, allow the planned default change, or hold the rollout for an affected job. Keep the test isolated from production release credentials where possible, and compare results against a retained baseline. The aim is not to prove that every runner behaves identically; it is to establish whether each critical workflow produces accepted artifacts with its intended OpenSSL selection.
A practical review can follow these checks:
- Map the runner scope. Identify which jobs use the announced macOS 26 Intel or Arm64 images and Xcode 27 Arm64 images. Confirm the image and installed software from job evidence.
- Search for direct calls. Find unqualified
opensslreferences in YAML, shell scripts, build scripts, and reusable actions. - Trace indirect use. Review dependency installation and native build logs for OpenSSL headers, libraries, or version-specific paths.
- Add diagnostics. Record the resolved executable, version output, and relevant image details in a non-secret-bearing job log.
- Test critical tasks. Run representative certificate, key, signing, TLS, and native dependency jobs. Check the output artifact and its normal consumer.
- Choose the control. If a job must use OpenSSL 3, select it explicitly using the versioned Homebrew prefix described in GitHub’s announcement and confirm the
openssl@3formula details in Homebrew’s formula reference. If the job is compatible with the new default, retain the test evidence rather than pinning without a need. - Define rollback evidence. If a test fails, isolate the affected job and use your existing rollback process. Preserve logs and image details so the team can reproduce the failure and decide whether to pin, patch, or defer.
If you add a versioned prefix to PATH, verify that the workflow uses the intended directory in the step where OpenSSL runs. GitHub documents how workflow commands can add a directory to PATH in its workflow-command reference. Confirm the resulting executable with the same diagnostic commands; do not assume that writing a path to the workflow environment file proves the next process resolved it as intended.
For a team-level review, record a status for each workflow rather than reporting a single “CI is ready” result:
- Ready: the image and executable are recorded, critical artifacts pass verification, and downstream consumers accept them.
- Needs review: the workflow has an indirect dependency, an untested output parser, or incomplete runner evidence.
- Blocked: a representative task fails or produces an artifact that does not meet the team’s acceptance checks.
This rating is an internal decision aid, not a claim about GitHub’s compatibility guarantee. Recheck the official announcement before the scheduled deployment and whenever GitHub updates the rollout status or image contents. The planned November 2–8 window is subject to change, so make the change record point to the announcement rather than treating the schedule as fixed. (GitHub runner-images announcement)
Choose the environment that fits the test, not the headline
GitHub-hosted runners are a reasonable place to validate the actual workflow that will run there. A separate Mac environment can help when you need to isolate a trial from production jobs, inspect a controlled build environment, or add temporary build capacity without changing the production pipeline. It does not replace evidence from the target GitHub runner, and it is not automatically the best choice for continuous, predictable heavy workloads or workflows requiring physical interfaces.
If you are comparing a self-managed Mac, a hosted runner, and a rented remote Mac, evaluate control, access, maintenance, and how closely the environment matches the job you need to test. The Mac environment comparison can help you assess the available approaches. If a separate remote Mac is a fit for an isolated trial, review zshmac’s Mac environment options: the service provides access to hosted physical Macs through VNC, SSH, or a web console, with root access and weekly, monthly, or quarterly plans. Confirm current availability and terms before planning a rollout.
For a short compatibility test, leasing can avoid buying a machine that may sit idle after the migration review. For a team that will run sustained, high-volume builds, compare recurring rental costs with hardware ownership and maintenance; for jobs that require physical peripherals, verify that the chosen environment supports them. Keep the production runner’s own logs as the final compatibility evidence, and use a separate Mac only where it adds useful isolation or capacity.
Further reading
Validate Your macOS CI on zshmac
Run your self-hosted CI runner on a dedicated physical Mac, not a virtual machine.
