From 050973e35bdc872bac5f9e911d760f1a15cd2ed2 Mon Sep 17 00:00:00 2001 From: Lucy Gramley Date: Thu, 21 May 2026 11:36:10 -0700 Subject: [PATCH] Harden iOS device ID validation and idb command execution - Validate extracted iOS device UDID format before use - Refactor idb push/pull commands to use execFile with argument arrays instead of string concatenation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/extension/ios/iOSContainerUtility.ts | 30 +++++++++++++++---- .../networkInspector/certificateProvider.ts | 6 +++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/extension/ios/iOSContainerUtility.ts b/src/extension/ios/iOSContainerUtility.ts index c302af642..ef8417504 100644 --- a/src/extension/ios/iOSContainerUtility.ts +++ b/src/extension/ios/iOSContainerUtility.ts @@ -182,9 +182,18 @@ async function push( await checkIdbIsInstalled(); return wrapWithErrorMessage( cp - .execToString( - `${idbPath} --log ${idbLogLevel} file push --udid ${udid} --bundle-id ${bundleId} '${src}' '${dst}'`, - ) + .execFileToString(idbPath, [ + "--log", + idbLogLevel, + "file", + "push", + "--udid", + udid, + "--bundle-id", + bundleId, + src, + dst, + ]) .then(() => { return; }) @@ -204,9 +213,18 @@ async function pull( await checkIdbIsInstalled(); return wrapWithErrorMessage( cp - .execToString( - `${idbPath} --log ${idbLogLevel} file pull --udid ${udid} --bundle-id ${bundleId} '${src}' '${dst}'`, - ) + .execFileToString(idbPath, [ + "--log", + idbLogLevel, + "file", + "pull", + "--udid", + udid, + "--bundle-id", + bundleId, + src, + dst, + ]) .then(() => { return; }) diff --git a/src/extension/networkInspector/certificateProvider.ts b/src/extension/networkInspector/certificateProvider.ts index bd0ce2f6e..87f9ae609 100644 --- a/src/extension/networkInspector/certificateProvider.ts +++ b/src/extension/networkInspector/certificateProvider.ts @@ -405,8 +405,12 @@ export class CertificateProvider { ): Promise { const matches = /\/Devices\/([^/]+)\//.exec(deviceCsrFilePath); if (matches && matches.length == 2) { + const udid = matches[1]; + if (!/^[A-F0-9-]{25,40}$/i.test(udid)) { + return Promise.reject(new Error(`Invalid iOS device UDID: ${udid}`)); + } // It's a simulator, the deviceId is in the filepath. - return Promise.resolve(matches[1]); + return Promise.resolve(udid); } return iosUtil.targets().then(targets => { if (targets.length === 0) {