Skip to content

Commit 06f921f

Browse files
committed
fix(github-actions): ensure that the artifacts provided for preview service are not symlinks (#2468)
Detect situations in which provided metadata is a symlink instead of a direct file which could be attempting to exfiltrate secrets. PR Close #2468
1 parent 7a4326a commit 06f921f

File tree

2 files changed

+19
-2
lines changed

2 files changed

+19
-2
lines changed

github-actions/previews/upload-artifacts-to-firebase/extract-artifact-metadata.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19399,7 +19399,12 @@ var artifactMetadata = {
1939919399
async function main() {
1940019400
const [artifactDirPath] = process.argv.slice(2);
1940119401
for (const [key, name] of Object.entries(artifactMetadata)) {
19402-
const content = await fs.promises.readFile(path.join(artifactDirPath, name), "utf8");
19402+
const expectedPath = path.join(artifactDirPath, name);
19403+
const realPath = await fs.promises.realpath(expectedPath);
19404+
if (expectedPath !== realPath) {
19405+
throw Error(`Value for unsafe-${key} not stored directly in file as expected, instead stored in ${realPath}`);
19406+
}
19407+
const content = await fs.promises.readFile(expectedPath, "utf8");
1940319408
const outputName = `unsafe-${key}`;
1940419409
console.info(`Setting output: ${outputName} = ${content}`);
1940519410
(0, import_core.setOutput)(outputName, content.trim());

github-actions/previews/upload-artifacts-to-firebase/lib/extract-artifact-metadata.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,19 @@ async function main() {
2323
const [artifactDirPath] = process.argv.slice(2);
2424

2525
for (const [key, name] of Object.entries(artifactMetadata)) {
26-
const content = await fs.promises.readFile(path.join(artifactDirPath, name), 'utf8');
26+
/** The expected path of the artifact */
27+
const expectedPath = path.join(artifactDirPath, name);
28+
29+
// We confirm that the provided artifact path is actually in the expected location instead of pointing somewhere
30+
// else to exfiltrate information.
31+
const realPath = await fs.promises.realpath(expectedPath);
32+
if (expectedPath !== realPath) {
33+
throw Error(
34+
`Value for unsafe-${key} not stored directly in file as expected, instead stored in ${realPath}`,
35+
);
36+
}
37+
38+
const content = await fs.promises.readFile(expectedPath, 'utf8');
2739
const outputName = `unsafe-${key}`;
2840

2941
console.info(`Setting output: ${outputName} = ${content}`);

0 commit comments

Comments
 (0)