diff --git a/apps/desktop/desktop_native/Cargo.lock b/apps/desktop/desktop_native/Cargo.lock
index 8b498f2c65e..d96e0642fad 100644
--- a/apps/desktop/desktop_native/Cargo.lock
+++ b/apps/desktop/desktop_native/Cargo.lock
@@ -555,6 +555,7 @@ version = "0.0.0"
dependencies = [
"anyhow",
"desktop_core",
+ "embed_plist",
"futures",
"log",
"simplelog",
@@ -614,6 +615,12 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
+[[package]]
+name = "embed_plist"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7"
+
[[package]]
name = "endi"
version = "1.1.0"
diff --git a/apps/desktop/desktop_native/proxy/Cargo.toml b/apps/desktop/desktop_native/proxy/Cargo.toml
index b15b07a78d3..681c34c8eab 100644
--- a/apps/desktop/desktop_native/proxy/Cargo.toml
+++ b/apps/desktop/desktop_native/proxy/Cargo.toml
@@ -14,3 +14,6 @@ log = "0.4.21"
simplelog = "0.12.2"
tokio = { version = "1.38.0", features = ["io-std", "io-util", "macros", "rt"] }
tokio-util = { version = "0.7.11", features = ["codec"] }
+
+[target.'cfg(target_os = "macos")'.dependencies]
+embed_plist = "1.2.2"
diff --git a/apps/desktop/desktop_native/proxy/src/main.rs b/apps/desktop/desktop_native/proxy/src/main.rs
index d4467c3f1cc..776b363598a 100644
--- a/apps/desktop/desktop_native/proxy/src/main.rs
+++ b/apps/desktop/desktop_native/proxy/src/main.rs
@@ -5,6 +5,9 @@ use futures::{SinkExt, StreamExt};
use log::*;
use tokio_util::codec::LengthDelimitedCodec;
+#[cfg(target_os = "macos")]
+embed_plist::embed_info_plist!("../../../resources/info.desktop_proxy.plist");
+
fn init_logging(log_path: &Path, level: log::LevelFilter) {
use simplelog::{ColorChoice, CombinedLogger, Config, SharedLogger, TermLogger, TerminalMode};
diff --git a/apps/desktop/resources/entitlements.desktop_proxy.plist b/apps/desktop/resources/entitlements.desktop_proxy.plist
index 774e274cf73..0bf3cc2c2f4 100644
--- a/apps/desktop/resources/entitlements.desktop_proxy.plist
+++ b/apps/desktop/resources/entitlements.desktop_proxy.plist
@@ -6,6 +6,8 @@
LTZ2PFU5D6.com.bitwarden.desktop
com.apple.developer.team-identifier
LTZ2PFU5D6
+ com.apple.security.app-sandbox
+
com.apple.security.application-groups
LTZ2PFU5D6.com.bitwarden.desktop
diff --git a/apps/desktop/resources/info.desktop_proxy.plist b/apps/desktop/resources/info.desktop_proxy.plist
new file mode 100644
index 00000000000..d0825217f15
--- /dev/null
+++ b/apps/desktop/resources/info.desktop_proxy.plist
@@ -0,0 +1,10 @@
+
+
+
+
+ CFBundleIdentifier
+ com.bitwarden.desktop
+ LSMinimumSystemVersion
+ 10.15
+
+
diff --git a/apps/desktop/scripts/after-pack.js b/apps/desktop/scripts/after-pack.js
index 7d588988155..08cff76e858 100644
--- a/apps/desktop/scripts/after-pack.js
+++ b/apps/desktop/scripts/after-pack.js
@@ -33,13 +33,32 @@ async function run(context) {
}
if (["darwin", "mas"].includes(context.electronPlatformName)) {
- const identities = getIdentities(process.env.CSC_NAME ?? "");
- if (identities.length === 0) {
- throw new Error("No valid identities found");
- }
- const id = identities[0].id;
+ const is_mas = context.electronPlatformName === "mas";
+ const is_mas_dev = context.targets.some((e) => e.name === "mas-dev");
- console.log("Signing proxy binary before the main bundle, using identity", id);
+ let id;
+
+ // Only use the Bitwarden Identities on CI
+ if (process.env.GITHUB_ACTIONS === "true") {
+ if (is_mas) {
+ id = is_mas_dev
+ ? "E7C9978F6FBCE0553429185C405E61F5380BE8EB"
+ : "3rd Party Mac Developer Application: Bitwarden Inc";
+ } else {
+ id = "Developer ID Application: 8bit Solutions LLC";
+ }
+ // Locally, use the first valid code signing identity, unless CSC_NAME is set
+ } else if (process.env.CSC_NAME) {
+ id = process.env.CSC_NAME;
+ } else {
+ const identities = getIdentities();
+ if (identities.length === 0) {
+ throw new Error("No valid identities found");
+ }
+ id = identities[0].id;
+ }
+
+ console.log(`Signing proxy binary before the main bundle, using identity '${id}'`);
const appName = context.packager.appInfo.productFilename;
const appPath = `${context.appOutDir}/${appName}.app`;
@@ -49,7 +68,7 @@ async function run(context) {
const entitlementsName = "entitlements.desktop_proxy.plist";
const entitlementsPath = path.join(__dirname, "..", "resources", entitlementsName);
child_process.execSync(
- `codesign -s ${id} -i ${packageId} -f --timestamp --options runtime --entitlements ${entitlementsPath} ${proxyPath}`,
+ `codesign -s '${id}' -i ${packageId} -f --timestamp --options runtime --entitlements ${entitlementsPath} ${proxyPath}`,
);
}
}
@@ -66,7 +85,7 @@ const appleCertificatePrefixes = [
"Apple Development:",
];
-function getIdentities(csc_name) {
+function getIdentities() {
const ids = child_process
.execSync("/usr/bin/security find-identity -v -p codesigning")
.toString();
@@ -81,7 +100,6 @@ function getIdentities(csc_name) {
}
return false;
})
- .filter((line) => line.includes(csc_name))
.map((line) => {
const split = line.trim().split(" ");
const id = split[1];