2 Commits

Author SHA1 Message Date
trifatale
511c486a5e fix: add macOS DNS redirect preload for MITM
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-18 13:22:59 -09:00
trifatale
7982aebcd7 fix: improve macOS LS path detection
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-02-18 13:22:50 -09:00
3 changed files with 39 additions and 21 deletions

View File

@@ -58,7 +58,11 @@ impl Platform {
let ca_cert_path = env_or("SSL_CERT_FILE", default_ca_cert_path); let ca_cert_path = env_or("SSL_CERT_FILE", default_ca_cert_path);
let ls_user = env_or("ZEROGRAVITY_LS_USER", || "zerogravity-ls".into()); let ls_user = env_or("ZEROGRAVITY_LS_USER", || "zerogravity-ls".into());
let state_db_path = env_or("ZEROGRAVITY_STATE_DB", || default_state_db_path(&home)); let state_db_path = env_or("ZEROGRAVITY_STATE_DB", || default_state_db_path(&home));
let dns_redirect_so_path = format!("{}/dns-redirect.so", &data_dir); let dns_redirect_so_path = if cfg!(target_os = "macos") {
format!("{}/dns-redirect.dylib", &data_dir)
} else {
format!("{}/dns-redirect.so", &data_dir)
};
let config_dir = PathBuf::from(&config_dir); let config_dir = PathBuf::from(&config_dir);
let token_path = config_dir.join("token"); let token_path = config_dir.join("token");
@@ -104,18 +108,19 @@ fn default_ls_binary_path() -> String {
fn default_ls_binary_path() -> String { fn default_ls_binary_path() -> String {
let home = home_dir(); let home = home_dir();
// Check both /Applications and ~/Applications // Check both /Applications and ~/Applications
let candidates = ["language_server_macos_arm", "language_server_darwin_arm64"];
for base in &[ for base in &[
"/Applications/Antigravity.app", "/Applications/Antigravity.app",
&format!("{home}/Applications/Antigravity.app"), &format!("{home}/Applications/Antigravity.app"),
] { ] {
let path = format!( for name in candidates {
"{base}/Contents/Resources/app/extensions/antigravity/bin/language_server_darwin_arm64" let path = format!("{base}/Contents/Resources/app/extensions/antigravity/bin/{name}");
);
if std::path::Path::new(&path).exists() { if std::path::Path::new(&path).exists() {
return path; return path;
} }
} }
"/Applications/Antigravity.app/Contents/Resources/app/extensions/antigravity/bin/language_server_darwin_arm64".into() }
"/Applications/Antigravity.app/Contents/Resources/app/extensions/antigravity/bin/language_server_macos_arm".into()
} }
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
@@ -295,9 +300,9 @@ pub fn supports_uid_isolation() -> bool {
} }
} }
/// Returns true if LD_PRELOAD DNS redirect is supported (Linux only). /// Returns true if DNS redirect preload is supported (Linux/macOS).
pub fn supports_ld_preload() -> bool { pub fn supports_ld_preload() -> bool {
cfg!(target_os = "linux") cfg!(any(target_os = "linux", target_os = "macos"))
} }
#[cfg(test)] #[cfg(test)]

View File

@@ -65,12 +65,12 @@ pub fn discover_main_ls_config() -> Result<MainLSConfig, String> {
discovery::discover_main_ls_config() discovery::discover_main_ls_config()
} }
/// Build the dns_redirect.so preload library if it doesn't already exist. /// Build the dns_redirect preload library if it doesn't already exist.
/// ///
/// Linux only — hooks `getaddrinfo()` via LD_PRELOAD to redirect Google API /// Linux/macOS — hooks `getaddrinfo()` via LD_PRELOAD/DYLD_INSERT_LIBRARIES
/// domain lookups to 127.0.0.1. /// to redirect Google API domain lookups to 127.0.0.1.
/// ///
/// Returns the path to the .so on success, None on failure. /// Returns the path to the shared library on success, None on failure.
fn build_dns_redirect_so() -> Option<String> { fn build_dns_redirect_so() -> Option<String> {
if !platform::supports_ld_preload() { if !platform::supports_ld_preload() {
return None; return None;
@@ -91,10 +91,15 @@ fn build_dns_redirect_so() -> Option<String> {
return None; return None;
} }
// Compile: gcc -shared -fPIC -o dns_redirect.so dns_redirect.c -ldl let output = if cfg!(target_os = "macos") {
let output = Command::new("gcc") Command::new("cc")
.args(["-dynamiclib", "-o", so_path.as_str(), &c_path])
.output()
} else {
Command::new("gcc")
.args(["-shared", "-fPIC", "-o", so_path.as_str(), &c_path, "-ldl"]) .args(["-shared", "-fPIC", "-o", so_path.as_str(), &c_path, "-ldl"])
.output(); .output()
};
match output { match output {
Ok(out) if out.status.success() => { Ok(out) if out.status.success() => {

View File

@@ -281,15 +281,23 @@ impl StandaloneLS {
// even the CodeAssistClient which has Proxy:nil hardcoded. // even the CodeAssistClient which has Proxy:nil hardcoded.
let so_path = build_dns_redirect_so(); let so_path = build_dns_redirect_so();
if let Some(ref so) = so_path { if let Some(ref so) = so_path {
info!(path = %so, "Enabling LD_PRELOAD DNS redirect for headless MITM"); info!(path = %so, "Enabling DNS redirect preload for headless MITM");
#[cfg(target_os = "macos")]
{
env_vars.push(("DYLD_INSERT_LIBRARIES".into(), so.clone()));
env_vars.push(("DYLD_FORCE_FLAT_NAMESPACE".into(), "1".into()));
}
#[cfg(not(target_os = "macos"))]
{
env_vars.push(("LD_PRELOAD".into(), so.clone())); env_vars.push(("LD_PRELOAD".into(), so.clone()));
}
env_vars.push(( env_vars.push((
"DNS_REDIRECT_LOG".into(), "DNS_REDIRECT_LOG".into(),
format!("{data_dir}/dns-redirect.log"), format!("{data_dir}/dns-redirect.log"),
)); ));
// Force Go binaries to use cgo (libc) DNS resolver instead of // Force Go binaries to use cgo (libc) DNS resolver instead of
// the pure-Go resolver. Without this, LD_PRELOAD getaddrinfo() // the pure-Go resolver. Without this, getaddrinfo hooks are
// hooks are bypassed because Go resolves DNS internally. // bypassed because Go resolves DNS internally.
env_vars.push(("GODEBUG".into(), "netdns=cgo".into())); env_vars.push(("GODEBUG".into(), "netdns=cgo".into()));
} }