Merge pull request #694 from abogaart/fix/macos-chmod-absolute-path

fix: spawn Apple /bin/chmod by absolute path when hardening credentials
This commit is contained in:
Sameh Khamis authored and GitHub committed 2026-09-24 22:06:27 -07:00
commit d508a406dc
3 files changed
+25 -1

No files matched your search

+5
View File
@@ -1,5 +1,10 @@
# Changelog
- Saving a key from Provider Settings works again on Macs where Nix or
Homebrew coreutils sit ahead of `/bin` on `PATH`. The credential hardener
now spawns Apple's `/bin/chmod -N` by absolute path; GNU `chmod` has no `-N`,
so the ACL strip failed closed and every save was refused (Arthur Bogaart, #694).
- Render on iPad and iPhone instead of stopping with "An error occurred while
rendering." Cesium's per-vertex model atmosphere binds shader `out`
parameters directly to varyings, which Apple's Metal/ANGLE backend cannot
+5 -1
View File
@@ -123,7 +123,11 @@ export function hardenCredentialFile(
if (platform !== 'win32') {
try {
if (platform === 'darwin') {
const aclRemoval = spawn('chmod', ['-N', filepath], {
// `-N` (strip the ACL) is Apple-only. Spawn /bin/chmod by absolute
// path, never by name: a Nix/Homebrew coreutils profile puts GNU chmod
// first on PATH, and GNU chmod rejects `-N` — which was treated as a
// hardening failure and refused every save on such machines.
const aclRemoval = spawn('/bin/chmod', ['-N', filepath], {
stdio: 'ignore',
});
if (!commandCompletedSuccessfully(aclRemoval)) return false;
+15
View File
@@ -55,6 +55,21 @@ test('macOS ACL removal failure stops before chmod and fails closed', () => {
assert.deepEqual(fileSystem.calls, [], 'mode bits must not disguise an ACL-removal failure');
});
test('macOS ACL removal spawns Apple /bin/chmod by absolute path, not via PATH', () => {
const spawned = [];
hardenCredentialFile(FILE, {
platform: 'darwin',
fileSystem: fileSystemWithMode(0o100600),
spawn(command, args) {
spawned.push([command, args]);
return { status: 0, signal: null };
},
});
// A coreutils-first PATH (Nix home-manager, Homebrew) resolves bare `chmod`
// to GNU chmod, which has no `-N` and would fail every save.
assert.deepEqual(spawned, [['/bin/chmod', ['-N', FILE]]]);
});
test('POSIX hardening verifies the resulting 0600 mode', () => {
const goodFs = fileSystemWithMode(0o100600);
assert.equal(hardenCredentialFile(FILE, {