-
Notifications
You must be signed in to change notification settings - Fork 20
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
Refuse to overwrite any directory containing the home directory or the profile directory #68
Changes from 4 commits
42ac15d
2f8ccda
09f6cef
a4fd675
f607110
9955a8d
029a6b7
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 |
---|---|---|
|
@@ -4,6 +4,7 @@ import joplin from "api"; | |
import * as path from "path"; | ||
import backupLogging from "electron-log"; | ||
import * as fs from "fs-extra"; | ||
import * as os from "os"; | ||
import { sevenZip } from "./sevenZip"; | ||
import * as moment from "moment"; | ||
import { helper } from "./helper"; | ||
|
@@ -288,11 +289,16 @@ class Backup { | |
} | ||
} | ||
|
||
if (path.normalize(profileDir) === this.backupBasePath) { | ||
const handleInvalidPath = async (errorId: string) => { | ||
const invalidBackupPath = this.backupBasePath; | ||
this.backupBasePath = null; | ||
await this.showError( | ||
i18n.__("msg.error.backupPathJoplinDir", path.normalize(profileDir)) | ||
); | ||
await this.showError(i18n.__(errorId, invalidBackupPath)); | ||
}; | ||
|
||
if (helper.isSubdirectoryOrEqual(this.backupBasePath, os.homedir())) { | ||
await handleInvalidPath("msg.error.backupPathContainsHomeDir"); | ||
} else if (helper.isSubdirectoryOrEqual(this.backupBasePath, profileDir)) { | ||
await handleInvalidPath("msg.error.backupPathContainsJoplinDir"); | ||
} | ||
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. Perhaps we should also check a few other directories here.
Or perhaps the entire deletion routine should be reworked. So that it only deletes its own files ... I think I'll have a look at it when this PR has been merged. Fits in with another idea I have. 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. I've changed this! I'm not sure how necessary system folders are though — when I set the backup directory to 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. Yes when the user runs his system with UAC and or a administrator user. |
||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import joplin from "api"; | ||
import * as path from "path"; | ||
|
||
export namespace helper { | ||
export async function validFileName(fileName: string) { | ||
|
@@ -65,4 +66,28 @@ export namespace helper { | |
|
||
return result; | ||
} | ||
|
||
// Doesn't resolve simlinks | ||
// See https://stackoverflow.com/questions/44892672/how-to-check-if-two-paths-are-the-same-in-npm | ||
// for possible alternative implementations. | ||
export function isSubdirectoryOrEqual( | ||
parent: string, | ||
possibleChild: string, | ||
|
||
// Testing only | ||
pathModule: typeof path = path | ||
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. Is this not possible otherwise, via a spy or the like? 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. I think the difficulties here are that
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. The third issue above seems to be the most significant. Even this alternative implementation causes a stack overflow: |
||
) { | ||
// Appending path.sep to handle this case: | ||
// parent: /a/b/test | ||
// possibleChild: /a/b/test2 | ||
// "/a/b/test2".startsWith("/a/b/test") -> true, but | ||
// "/a/b/test2/".startsWith("/a/b/test/") -> false | ||
// | ||
// Note that .resolve removes trailing slashes. | ||
// | ||
const normalizedParent = pathModule.resolve(parent) + pathModule.sep; | ||
const normalizedChild = pathModule.resolve(possibleChild) + pathModule.sep; | ||
|
||
return normalizedChild.startsWith(normalizedParent); | ||
} | ||
} |
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.
Previously, the
backupPath
was a parent directory of the test profile directory. As such, the relative path has been changed.