[BUG] Claude Code's macOS sandbox blocks URLSession / CFNetwork

Resolved 💬 3 comments Opened Mar 23, 2026 by Daij-Djan Closed Mar 23, 2026

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;
}

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗