[BUG] Claude Code's macOS sandbox blocks URLSession / CFNetwork
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Claude Code's native binary runs inside a macOS seatbelt sandbox. This sandbox blocks IPC to nsurlsessiond (& com.apple.nsurlsessiond, cfnetworkd), the system daemon that handles all NSURLSession and CFNetwork requests. Any child process launched from Claude Code inherits this restriction.
This means if you use Claude Code to build and run a macOS app or CLI tool that uses URLSession, networking silently fails with a timeout. Raw POSIX sockets (e.g. curl via posix_spawn) work fine since they bypass nsurlsessiond.
Impact
Any Apple-platform app or tool that relies on URLSession/CFNetwprl (macos: swift or objc) cannot be tested/controlled end-to-end from within Claude Code.
Running it to show the issue
clang -framework Foundation -o nsurl_test main.m && ./nsurl_test
[ccode attached below]
From Claude Code:
[curl] HTTP 200
[URLSession] TIMED OUT (35s)
From iTerm:
[curl] HTTP 200
[URLSession] HTTP 200
Root cause
The sandbox applied via sandbox_init() blocks Mach IPC to com.apple.nsurlsessiond. URLSession doesn't open
sockets directly — it delegates to this daemon via XPC. The sandbox allows raw socket operations, which is why curl works.
Idea?!
Add a mach-lookup rule to the sandbox profile, or provide a user-facing opt-out for the seatbelt sandbox.
What Should Happen?
we should be able to use URLSession from within claude without timeout
Error Messages/Logs
Steps to Reproduce
Running it to show the issue
clang -framework Foundation -o nsurl_test main.m && ./nsurl_test
[ccode attached below]
From Claude Code:
[curl] HTTP 200
[URLSession] TIMED OUT (35s)
From iTerm:
[curl] HTTP 200
[URLSession] HTTP 200
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.78
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
iTerm2
Additional Information
// Minimal repro: Claude Code's macOS sandbox blocks URLSession but not raw sockets.
// Build: clang -framework Foundation -o nsurl_test main.m
// Run from Claude Code to see URLSession time out while curl succeeds.
// Run from a real terminal (iTerm) to see both succeed.
#include <spawn.h>
#include <sys/wait.h>
#import <Foundation/Foundation.h>
extern char **environ;
int main(int argc, const char *argv[])
{
@autoreleasepool {
NSString *url = @"https://graph.facebook.com/v2.10/auth/login"; // some url you can POST to
fprintf(stderr, "\n=== NETWORK TEST (macOS app) ===\n");
// Test 1: URLSession
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
__block NSInteger urlSessionStatus = -1;
__block NSString *urlSessionError = nil;
NSURL *nsurl = [NSURL URLWithString:url];
NSURLRequest *request = [NSURLRequest requestWithURL:nsurl];
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
urlSessionError = error.localizedDescription;
} else {
urlSessionStatus = ((NSHTTPURLResponse *)response).statusCode;
}
dispatch_semaphore_signal(sem);
}];
[task resume];
// Test 2: curl via posix_spawn (in parallel)
int pipefd[2];
pipe(pipefd);
posix_spawn_file_actions_t actions;
posix_spawn_file_actions_init(&actions);
posix_spawn_file_actions_addclose(&actions, pipefd[0]);
posix_spawn_file_actions_adddup2(&actions, pipefd[1], STDOUT_FILENO);
posix_spawn_file_actions_addclose(&actions, pipefd[1]);
const char *curlArgs[] = {
"/usr/bin/curl", "-s", "-o", "/dev/null", "-w", "%{http_code}",
"--max-time", "10", "-X", "POST", url.UTF8String, NULL
};
pid_t pid;
int spawnErr = posix_spawn(&pid, "/usr/bin/curl", &actions, NULL, (char *const *)curlArgs, environ);
posix_spawn_file_actions_destroy(&actions);
close(pipefd[1]);
// Read curl output
char curlBuf[32] = {0};
if (spawnErr == 0) {
read(pipefd[0], curlBuf, sizeof(curlBuf) - 1);
int status;
waitpid(pid, &status, 0);
}
close(pipefd[0]);
// Wait for URLSession (max 35s)
long timedOut = dispatch_semaphore_wait(sem, dispatch_time(DISPATCH_TIME_NOW, 35 * NSEC_PER_SEC));
// Print results
fprintf(stderr, "[curl/posix_spawn] HTTP %s\n", spawnErr == 0 ? curlBuf : "SPAWN_FAILED");
if (timedOut) {
fprintf(stderr, "[URLSession] TIMED OUT (35s)\n");
[task cancel];
} else if (urlSessionError) {
fprintf(stderr, "[URLSession] ERROR: %s\n", urlSessionError.UTF8String);
} else {
fprintf(stderr, "[URLSession] HTTP %ld\n", (long)urlSessionStatus);
}
fprintf(stderr, "=== END NETWORK TEST ===\n\n");
}
return 0;
}This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗