@@ -15,6 +15,8 @@ import { IShellLaunchConfig, ITerminalEnvironment, ITerminalProcessOptions } fro
15
15
import { EnvironmentVariableMutatorType } from '../common/environmentVariable.js' ;
16
16
import { deserializeEnvironmentVariableCollections } from '../common/environmentVariableShared.js' ;
17
17
import { MergedEnvironmentVariableCollection } from '../common/environmentVariableCollection.js' ;
18
+ import { chmod , realpathSync } from 'fs' ;
19
+ import { promisify } from 'util' ;
18
20
19
21
export function getWindowsBuildNumber ( ) : number {
20
22
const osVersion = ( / ( \d + ) \. ( \d + ) \. ( \d + ) / g) . exec ( os . release ( ) ) ;
@@ -49,13 +51,14 @@ export interface IShellIntegrationConfigInjection {
49
51
* that creates the process to ensure accuracy. Returns undefined if shell integration cannot be
50
52
* enabled.
51
53
*/
52
- export function getShellIntegrationInjection (
54
+ export async function getShellIntegrationInjection (
53
55
shellLaunchConfig : IShellLaunchConfig ,
54
56
options : ITerminalProcessOptions ,
55
57
env : ITerminalEnvironment | undefined ,
56
58
logService : ILogService ,
57
- productService : IProductService
58
- ) : IShellIntegrationConfigInjection | undefined {
59
+ productService : IProductService ,
60
+ skipStickyBit : boolean = false
61
+ ) : Promise < IShellIntegrationConfigInjection | undefined > {
59
62
// Conditionally disable shell integration arg injection
60
63
// - The global setting is disabled
61
64
// - There is no executable (not sure what script to run)
@@ -212,7 +215,27 @@ export function getShellIntegrationInjection(
212
215
} catch {
213
216
username = 'unknown' ;
214
217
}
215
- const zdotdir = path . join ( os . tmpdir ( ) , `${ username } -${ productService . applicationName } -zsh` ) ;
218
+
219
+ // Resolve the actual tmp directory so we can set the sticky bit
220
+ const realTmpDir = realpathSync ( os . tmpdir ( ) ) ;
221
+ const zdotdir = path . join ( realTmpDir , `${ username } -${ productService . applicationName } -zsh` ) ;
222
+
223
+ // Set directory permissions using octal notation:
224
+ // - 0o1700:
225
+ // - Sticky bit is set, preventing non-owners from deleting or renaming files within this directory (1)
226
+ // - Owner has full read (4), write (2), execute (1) permissions
227
+ // - Group has no permissions (0)
228
+ // - Others have no permissions (0)
229
+ if ( ! skipStickyBit ) {
230
+ // skip for tests
231
+ try {
232
+ const chmodAsync = promisify ( chmod ) ;
233
+ await chmodAsync ( zdotdir , 0o1700 ) ;
234
+ } catch ( err ) {
235
+ logService . error ( `Failed to set sticky bit on ${ zdotdir } : ${ err } ` ) ;
236
+ return undefined ;
237
+ }
238
+ }
216
239
envMixin [ 'ZDOTDIR' ] = zdotdir ;
217
240
const userZdotdir = env ?. ZDOTDIR ?? os . homedir ( ) ?? `~` ;
218
241
envMixin [ 'USER_ZDOTDIR' ] = userZdotdir ;
0 commit comments