Skip to content

Instantly share code, notes, and snippets.

@MarkTiedemann
Last active April 13, 2022 15:52
Show Gist options
  • Save MarkTiedemann/e4a44fcb6420183c7ff4549b95e07803 to your computer and use it in GitHub Desktop.
Save MarkTiedemann/e4a44fcb6420183c7ff4549b95e07803 to your computer and use it in GitHub Desktop.
import fs from "node:fs";
import crypto from "node:crypto";
const hashAlgo = "sha512";
function hash(file) {
return new Promise(resolve => {
fs.createReadStream(file).pipe(
crypto.createHash(hashAlgo).setEncoding("base64")
).on("finish", function() {
resolve(`${hashAlgo}-${this.read()}`);
});
});
}
const fsExploitFile = "./fs-exploit.mjs";
const relativeFs = "./relative-fs.mjs";
const [fsExploitHash, safeFsHash] = await Promise.all([
hash(fsExploitFile),
hash(relativeFs)
]);
fs.writeFileSync("policy.json", JSON.stringify({
resources: {
[fsExploitFile]: {
integrity: fsExploitHash,
dependencies: {
"node:fs": relativeFs,
"node:path": true,
"node:process": true
}
},
[relativeFs]: {
integrity: safeFsHash,
dependencies: {
"node:fs": true,
"node:path": true,
"node:process": true
}
}
}
}, null, 2));
import fs from "node:fs";
import path from "node:path";
import process from "node:process";
fs.readFileSync("./secret.txt");
// May not read from parent directory
try {
fs.readFileSync("../secret.txt");
} catch (e) {
console.error(e);
}
// May not read from same directory on a different drive
if (process.platform === "win32") {
try {
const cwd = process.cwd();
const [drive, directory] = cwd.split(":");
const driveCharCode = drive.toUpperCase().charCodeAt(0);
const nextDriveLetter = String.fromCharCode(driveCharCode === 90 /*Z*/ ? 65 /*A*/ : driveCharCode + 1);
const sameDirectoryWrongDrive = path.join(`${nextDriveLetter}:${directory}`, "secret.txt");
fs.readFileSync(sameDirectoryWrongDrive);
} catch (e) {
console.error(e);
}
}
{
"resources": {
"./fs-exploit.mjs": {
"integrity": "sha512-FIqIT3ls3kDsaSuLaE9nZnlMHj5qJJqnjXJZykg/3V85N+SYAisZQbqO81b9UFpbnKwO8fJnTlDNDYKaKD/Nkw==",
"dependencies": {
"node:fs": "./relative-fs.mjs",
"node:path": true,
"node:process": true
}
},
"./relative-fs.mjs": {
"integrity": "sha512-JLzd/IljL8i9h1wGTiE4uwvJS9k+K1W5jral+4aUdw7ZcIX5EeVMHHYWUU80S1XfrlcJ8h1qFWxo8vTUEW8q2A==",
"dependencies": {
"node:fs": true,
"node:path": true,
"node:process": true
}
}
}
}
import fs from "node:fs";
import path from "node:path";
import process from "node:process";
const isWindows = process.platform === "win32";
const cwd = process.cwd();
const drive = isWindows ? getDrive(cwd) : null;
function getDrive(file) {
return file.split(":")[0].toUpperCase();
}
function isRelativePath(file) {
const normalized = path.normalize(file);
if (isWindows && path.isAbsolute(normalized) && drive !== getDrive(normalized)) {
return false;
}
const relative = path.relative(cwd, normalized);
return !relative.startsWith("..");
}
function readFileSync(file, options) {
if (!isRelativePath(file)) {
throw new Error(`ENOENT: no such file or directory, open '${file}'`);
}
return fs.readFileSync(file, options);
}
export default { readFileSync };
@node ./build-policy.mjs
@node --experimental-policy=policy.json ./fs-exploit.mjs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment