Qt reads hw.optional.neon to detect NEON. Under srt that read is denied, Qt takes the missing answer for "no NEON", and aborts before reaching main():
Incompatible processor. This Qt build requires the following features:
neon
Process killed by signal: SIGABRT
We hit this running Houdini's hython in a sandboxed process. Houdini 21.0.729 bundles Qt 6.5.3, and the string above comes from its QtCore. Nothing about the failure is Houdini specific.
The ask is one name added to an allowlist that already permits its siblings by prefix, not a change to the default-deny policy.
Reproduce without Qt
probe.py:
import ctypes, ctypes.util
libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True)
def probe(name):
size = ctypes.c_size_t(8)
buf = ctypes.create_string_buffer(8)
if libc.sysctlbyname(name.encode(), buf, ctypes.byref(size), None, 0) == 0:
return "ok (value=%d)" % int.from_bytes(buf.raw[: size.value], "little")
return "DENIED errno=%d" % ctypes.get_errno()
for name in ("hw.optional.neon", "hw.optional.armv8_crc32",
"hw.logicalcpu", "hw.optional.this_does_not_exist"):
print(" %-32s %s" % (name, probe(name)))
settings.json, granting read access to the whole filesystem:
{
"network": {
"allowedDomains": [],
"deniedDomains": [],
"allowLocalBinding": true,
"allowUnixSockets": []
},
"filesystem": {
"denyRead": [],
"allowRead": ["/"],
"allowWrite": ["/tmp"],
"denyWrite": []
},
"enableWeakerNestedSandbox": false,
"enableWeakerNetworkIsolation": false,
"allowAppleEvents": false
}
/usr/bin/python3 probe.py # normal: all real names ok
srt --settings settings.json -- /usr/bin/python3 probe.py # sandboxed
Sandboxed:
hw.optional.neon DENIED errno=1
hw.optional.armv8_crc32 ok (value=1)
hw.logicalcpu ok (value=10)
hw.optional.this_does_not_exist DENIED errno=2
errno=1 is EPERM, so the name exists and the read was refused. The deliberately fake name gets errno=2, ENOENT, in both runs. Note the policy grants read access to the whole filesystem and the value is still blocked, because a sysctl read is a separate Seatbelt operation class from file reads.
Cause
dist/sandbox/macos-sandbox-utils.js allows CPU feature names with three prefix rules:
(sysctl-name-prefix "hw.optional.arm")
(sysctl-name-prefix "hw.optional.arm.")
(sysctl-name-prefix "hw.optional.armv8_")
hw.optional.neon begins with none of them, so it falls through to the default deny.
The same fact is already readable inside the sandbox under a different name. hw.optional.arm.AdvSIMD also reports NEON support and returns 1 sandboxed, because it matches the hw.optional.arm. prefix:
hw.optional.neon DENIED errno=1
hw.optional.arm.AdvSIMD ok (value=1)
So this is a naming gap rather than a boundary. Qt 6.5.3 happens to ask for the spelling that is not covered.
Qt 6.5.3, src/corelib/global/qsimd.cpp, Darwin ARM branch of detectProcessorFeatures():
if (sysctlbyname("hw.optional.neon", &feature, &len, nullptr, 0) == 0)
features |= feature ? CpuFeatureNEON : 0;
A denied read skips the branch and the bit is never set, so Qt cannot tell "this CPU has no NEON" from "something refused to let me ask".
Qt removed this read in commit aeeb11841b3e (September 2024, "Clean and assert our ARM extensions on Apple hardware"), replacing it with a compile-time assumption. Current Qt queries only hw.optional.armv8_crc32, hw.optional.arm.FEAT_AES and hw.optional.arm.FEAT_SVE, all of which match your existing prefixes. So this affects Qt 6.5 era builds rather than trunk, which is likely why it has not surfaced before. That fix does not help anyone running already-shipped software built against those versions, which cannot be repointed at Qt trunk.
Suggested fix
Add hw.optional.neon.
Adding it discloses nothing new, since hw.optional.arm.AdvSIMD already reports the same capability through your existing prefix.
Widening to the whole hw.optional. prefix may also be worth considering, since naming values one at a time mainly defers the next instance of this. The obvious objection is fingerprinting of exploit mitigations, but on this machine every such flag (FEAT_BTI, FEAT_MTE*, FEAT_CSV2, FEAT_CSV3, FEAT_FPAC) sits under hw.optional.arm.FEAT_* and is already permitted. You are better placed than us to weigh that.
Related here: #287 asks for the sysctl allowlist to be exposed in the JSON policy, which would let people unblock themselves without a release. #78 is the same shape for kern.memorystatus_level.
Seen elsewhere too, so this is not specific to srt: openai/codex#7099 reports the same blocked sysctl breaking Qt, and openscad/openscad#6712 is a downstream sighting of the same message.
Environment
@anthropic-ai/sandbox-runtime 0.0.67, macOS 26.5.2, Apple M2 Pro, Node v25.8.1.
Qt reads
hw.optional.neonto detect NEON. Undersrtthat read is denied, Qt takes the missing answer for "no NEON", and aborts before reachingmain():We hit this running Houdini's
hythonin a sandboxed process. Houdini 21.0.729 bundles Qt 6.5.3, and the string above comes from itsQtCore. Nothing about the failure is Houdini specific.The ask is one name added to an allowlist that already permits its siblings by prefix, not a change to the default-deny policy.
Reproduce without Qt
probe.py:settings.json, granting read access to the whole filesystem:{ "network": { "allowedDomains": [], "deniedDomains": [], "allowLocalBinding": true, "allowUnixSockets": [] }, "filesystem": { "denyRead": [], "allowRead": ["/"], "allowWrite": ["/tmp"], "denyWrite": [] }, "enableWeakerNestedSandbox": false, "enableWeakerNetworkIsolation": false, "allowAppleEvents": false }Sandboxed:
errno=1is EPERM, so the name exists and the read was refused. The deliberately fake name getserrno=2, ENOENT, in both runs. Note the policy grants read access to the whole filesystem and the value is still blocked, because a sysctl read is a separate Seatbelt operation class from file reads.Cause
dist/sandbox/macos-sandbox-utils.jsallows CPU feature names with three prefix rules:hw.optional.neonbegins with none of them, so it falls through to the default deny.The same fact is already readable inside the sandbox under a different name.
hw.optional.arm.AdvSIMDalso reports NEON support and returns1sandboxed, because it matches thehw.optional.arm.prefix:So this is a naming gap rather than a boundary. Qt 6.5.3 happens to ask for the spelling that is not covered.
Qt 6.5.3,
src/corelib/global/qsimd.cpp, Darwin ARM branch ofdetectProcessorFeatures():A denied read skips the branch and the bit is never set, so Qt cannot tell "this CPU has no NEON" from "something refused to let me ask".
Qt removed this read in commit
aeeb11841b3e(September 2024, "Clean and assert our ARM extensions on Apple hardware"), replacing it with a compile-time assumption. Current Qt queries onlyhw.optional.armv8_crc32,hw.optional.arm.FEAT_AESandhw.optional.arm.FEAT_SVE, all of which match your existing prefixes. So this affects Qt 6.5 era builds rather than trunk, which is likely why it has not surfaced before. That fix does not help anyone running already-shipped software built against those versions, which cannot be repointed at Qt trunk.Suggested fix
Add
hw.optional.neon.Adding it discloses nothing new, since
hw.optional.arm.AdvSIMDalready reports the same capability through your existing prefix.Widening to the whole
hw.optional.prefix may also be worth considering, since naming values one at a time mainly defers the next instance of this. The obvious objection is fingerprinting of exploit mitigations, but on this machine every such flag (FEAT_BTI,FEAT_MTE*,FEAT_CSV2,FEAT_CSV3,FEAT_FPAC) sits underhw.optional.arm.FEAT_*and is already permitted. You are better placed than us to weigh that.Related here: #287 asks for the sysctl allowlist to be exposed in the JSON policy, which would let people unblock themselves without a release. #78 is the same shape for
kern.memorystatus_level.Seen elsewhere too, so this is not specific to
srt: openai/codex#7099 reports the same blocked sysctl breaking Qt, and openscad/openscad#6712 is a downstream sighting of the same message.Environment
@anthropic-ai/sandbox-runtime0.0.67, macOS 26.5.2, Apple M2 Pro, Node v25.8.1.