Browse Source

Adds protection/detection for bare clones

- Adds protection from bare clones in untrusted workspaces
 - Adds detection for bare clones in trusted workspaces
main
Eric Amodio 1 year ago
parent
commit
4ba10d3ca2
1 changed files with 44 additions and 6 deletions
  1. +44
    -6
      src/env/node/git/git.ts

+ 44
- 6
src/env/node/git/git.ts View File

@ -1,5 +1,6 @@
import type { ChildProcess, SpawnOptions } from 'child_process';
import { spawn } from 'child_process';
import { accessSync } from 'fs';
import * as process from 'process';
import type { CancellationToken, OutputChannel } from 'vscode';
import { Uri, window, workspace } from 'vscode';
@ -1577,17 +1578,54 @@ export class Git {
}
async rev_parse__show_toplevel(cwd: string): Promise<string | undefined> {
let data;
if (!workspace.isTrusted) {
// Check if the folder is a bare clone: if it has a file named HEAD && `rev-parse --show-cdup` is empty
try {
accessSync(joinPaths(cwd, 'HEAD'));
data = await this.git<string>(
{ cwd: cwd, errors: GitErrorHandling.Throw, configs: ['-C', cwd] },
'rev-parse',
'--show-cdup',
);
if (data.trim() === '') {
Logger.log(`Skipping (untrusted workspace); bare clone repository detected in '${cwd}'`);
return undefined;
}
} catch {
// If this throw, we should be good to open the repo (e.g. HEAD doesn't exist)
}
}
try {
const data = await this.git<string>(
{ cwd: cwd, errors: GitErrorHandling.Throw },
'rev-parse',
'--show-toplevel',
);
data = await this.git<string>({ cwd: cwd, errors: GitErrorHandling.Throw }, 'rev-parse', '--show-toplevel');
// Make sure to normalize: https://github.com/git-for-windows/git/issues/2478
// Keep trailing spaces which are part of the directory name
return data.length === 0 ? undefined : normalizePath(data.trimLeft().replace(/[\r|\n]+$/, ''));
return data.length === 0 ? undefined : normalizePath(data.trimStart().replace(/[\r|\n]+$/, ''));
} catch (ex) {
const inDotGit = /this operation must be run in a work tree/.test(ex.stderr);
// Check if we are in a bare clone
if (inDotGit && workspace.isTrusted) {
data = await this.git<string>(
{ cwd: cwd, errors: GitErrorHandling.Ignore },
'rev-parse',
'--is-bare-repository',
);
if (data.trim() === 'true') {
// If we are in a bare clone, then the common dir is the git dir
data = await this.git<string>(
{ cwd: cwd, errors: GitErrorHandling.Ignore },
'rev-parse',
'--git-common-dir',
);
data = data.trim();
if (data.length) {
return normalizePath((data === '.' ? cwd : data).trimStart().replace(/[\r|\n]+$/, ''));
}
}
}
if (inDotGit || ex.code === 'ENOENT') {
// If the `cwd` doesn't exist, walk backward to see if any parent folder exists
let exists = inDotGit ? false : await fsExists(cwd);

Loading…
Cancel
Save