Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deny git access to nested server root #1278

Merged
merged 14 commits into from
Dec 5, 2023
9 changes: 7 additions & 2 deletions jupyterlab_git/git.py
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ async def show_top_level(self, path):
"message": my_error,
}

async def show_prefix(self, path):
async def show_prefix(self, path, contents_manager):
"""
Execute git --show-prefix command & return the result.
"""
Expand All @@ -955,8 +955,13 @@ async def show_prefix(self, path):
cmd,
cwd=path,
)

if code == 0:
result = {"code": code, "path": my_output.strip("\n")}
result = {
"code": code,
"path": my_output.strip("\n"),
"relative_path": os.path.relpath(path, contents_manager.root_dir),
}
Zxun2 marked this conversation as resolved.
Show resolved Hide resolved
return result
else:
# Handle special case where cwd not inside a git repo
Expand Down
3 changes: 2 additions & 1 deletion jupyterlab_git/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ async def post(self, path: str = ""):
POST request handler, displays the prefix path of a directory in a repository,
with respect to the root directory.
"""
result = await self.git.show_prefix(self.url2localpath(path))
local_path, cm = self.url2localpath(path, with_contents_manager=True)
result = await self.git.show_prefix(local_path, cm)

if result["code"] != 0:
self.set_status(500)
Expand Down
17 changes: 15 additions & 2 deletions src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ISignal, Signal } from '@lumino/signaling';
import { AUTH_ERROR_MESSAGES, requestAPI } from './git';
import { TaskHandler } from './taskhandler';
import { Git, IGitExtension } from './tokens';
import { decodeStage } from './utils';
import { arraysAreEqual, decodeStage } from './utils';

// Default refresh interval (in milliseconds) for polling the current Git status (NOTE: this value should be the same value as in the plugin settings schema):
const DEFAULT_REFRESH_INTERVAL = 3000; // ms
Expand Down Expand Up @@ -1473,6 +1473,20 @@ export class GitExtension implements IGitExtension {
);
}
);
if (data?.relative_path && data?.path) {
if (data?.relative_path === '.' && data.path !== '') {
return null;
} else {
if (
!arraysAreEqual(
data.relative_path.split('\\'),
data.path.split('/').slice(0, -1) // slicing accounts for additional "/" at end of path
)
) {
return null;
}
}
}
return data.path ?? null;
} catch (error) {
if (
Expand Down Expand Up @@ -1793,7 +1807,6 @@ export class GitExtension implements IGitExtension {
* @throws {ServerConnection.NetworkError} If the request cannot be made
*/
async tags(): Promise<Git.ITagResult> {
const path = await this._getPathRepository();
Zxun2 marked this conversation as resolved.
Show resolved Hide resolved
return await this._taskHandler.execute<Git.ITagResult>(
'git:tag:list',
async () => {
Expand Down
4 changes: 4 additions & 0 deletions src/tokens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,10 @@ export namespace Git {
* Relative path of the current folder within its Git repository
*/
path?: string;
/**
* Relative path of the root folder
*/
relative_path?: string;
}

/**
Expand Down
13 changes: 13 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,16 @@ export const openFileDiff =
}
}
};

/** Shallow comparison of two arrays */
export function arraysAreEqual(array1: string[], array2: string[]) {
if (array1.length !== array2.length) {
return false;
}
for (let i = 0; i < array1.length; i++) {
if (array1[i] !== array2[i]) {
return false;
}
}
return true;
}