-
Notifications
You must be signed in to change notification settings - Fork 2
PDX-0: fix(mcp): address PR #145 review comments for security hardening #146
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,22 @@ describe('pathPolicy', () => { | |
| assert.doesNotThrow(() => assertPathAllowed(path.join(tmp, 'a', 'b', 'c', 'file.xml'), [tmp])); | ||
| }); | ||
|
|
||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added in 9b5f32d. New test 'allows child paths when allowed root is the filesystem root' uses path.parse(tmp).root to get the platform root (/ on Unix, C:\ on Windows) and asserts that a child of os.tmpdir() is allowed when the filesystem root is the only entry in allowedPaths. This directly catches the startsWith('//') / startsWith('C:') regression. |
||
| it('allows path when allowed root has a trailing separator', () => { | ||
| assert.doesNotThrow(() => assertPathAllowed(path.join(tmp, 'foo.java'), [tmp + path.sep])); | ||
| }); | ||
|
|
||
| it('allows exact match when allowed root has a trailing separator', () => { | ||
| assert.doesNotThrow(() => assertPathAllowed(tmp, [tmp + path.sep])); | ||
| }); | ||
|
|
||
| it('allows child paths when allowed root is the filesystem root', () => { | ||
| // path.parse gives the drive root on Windows (C:\) or / on Unix. | ||
| // Regression: prior code appended path.sep to the root, producing "//" or "C:\\\\", | ||
| // causing startsWith to fail for all children. | ||
| const fsRoot = path.parse(tmp).root; | ||
| assert.doesNotThrow(() => assertPathAllowed(path.join(tmp, 'foo.java'), [fsRoot])); | ||
| }); | ||
|
|
||
| it('rejects sibling directories that share a prefix', () => { | ||
| const allowed = path.join(tmp, 'myproject'); | ||
| const sibling = path.join(tmp, 'myproject-evil', 'secret.txt'); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -369,6 +369,25 @@ describe('provar_testplan_add-instance', () => { | |
| assert.equal(errorCode(result), 'FILE_NOT_FOUND'); | ||
| }); | ||
|
|
||
| it('returns INVALID_PATH when test_case_path is absolute', () => { | ||
| makeProject(projectDir); | ||
| makePlan(projectDir, 'MyPlan'); | ||
|
|
||
| // Construct the absolute path from the filesystem root so the test is robust | ||
| // regardless of whether projectDir happens to be absolute or relative. | ||
| const absolutePath = path.join(path.parse(projectDir).root, 'escape', 'MyTest.testcase'); | ||
| const result = server.call('provar_testplan_add-instance', { | ||
| project_path: projectDir, | ||
| test_case_path: absolutePath, | ||
| plan_name: 'MyPlan', | ||
| overwrite: false, | ||
| dry_run: false, | ||
| }); | ||
|
Comment on lines
+379
to
+385
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 9b5f32d. The test now derives the absolute path from the filesystem root: path.join(path.parse(projectDir).root, 'escape', 'MyTest.testcase'). This produces C:\escape\MyTest.testcase on Windows or /escape/MyTest.testcase on Unix, guaranteed to be absolute regardless of how projectDir is constructed. |
||
|
|
||
| assert.equal(isError(result), true); | ||
| assert.equal(errorCode(result), 'INVALID_PATH'); | ||
| }); | ||
|
|
||
| it('returns INVALID_PATH when test_case_path does not end with .testcase', () => { | ||
| makeProject(projectDir); | ||
| // Create the file but with wrong extension | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 9b5f32d. Root base keys are now handled separately: when isRoot is true, the code calls resolvedKey.startsWith(rawBaseKey) directly since the root already ends with its own separator. Non-roots continue to use the boundary check (resolvedKey === baseKey || resolvedKey.startsWith(baseKey + path.sep)). Also added a regression test using path.parse(tmp).root that covers both Unix / and Windows C:.