@@ -38,12 +38,26 @@ const expression = `(() => {
3838 const path = process.getBuiltinModule('path');
3939 const os = process.getBuiltinModule('os');
4040 const home = ${ JSON . stringify ( home ) } ;
41+ // Compare real paths so a symlink alias of a live directory cannot pass; a missing
42+ // destination resolves through its nearest existing ancestor.
43+ const canonical = (value) => {
44+ const rest = [];
45+ for (let dir = path.resolve(value); ; dir = path.dirname(dir)) {
46+ try {
47+ return path.join(fs.realpathSync.native(dir), ...rest);
48+ } catch (error) {
49+ if (error.code !== 'ENOENT' || fs.lstatSync(dir, { throwIfNoEntry: false }) || dir === path.dirname(dir)) throw error;
50+ rest.unshift(path.basename(dir));
51+ }
52+ }
53+ };
4154 // Desktop config trims XDG values and falls back to the real defaults when blank.
4255 const isolated = (name, fallback) => {
4356 const value = process.env[name] || '';
44- return value === value.trim() && path.isAbsolute(value) && path.resolve (value) !== path.join(os.homedir(), fallback);
57+ return value === value.trim() && path.isAbsolute(value) && canonical (value) !== canonical( path.join(os.homedir(), fallback) );
4558 };
46- if (path.resolve(process.env.T3CODE_HOME || '') !== home || home === path.join(os.homedir(), '.t3') || !isolated('XDG_CONFIG_HOME', '.config') || !isolated('XDG_DATA_HOME', '.local/share')) {
59+ const t3Home = process.env.T3CODE_HOME || '';
60+ if (!t3Home || canonical(t3Home) !== canonical(home) || canonical(home) === canonical(path.join(os.homedir(), '.t3')) || !isolated('XDG_CONFIG_HOME', '.config') || !isolated('XDG_DATA_HOME', '.local/share')) {
4761 throw new Error('Requires matching isolated T3CODE_HOME and isolated XDG directories');
4862 }
4963 const E = process.getBuiltinModule('module').createRequire(process.cwd() + '/fixture.cjs')('electron');
0 commit comments