chore(security): harden helpers + document conflict-labeler safety

From the workflow security audit:
- symlink-native-dirs.js: drop the execSync shell strings for fs.symlink/mkdir
  (removes a latent shell-injection surface; also clears dead commented code).
- automerge.sh: add 'set -euo pipefail' and restore the starting branch on exit
  so a mid-merge failure can't leave the repo on the wrong branch.
- conflict.yml: document that this pull_request_target workflow must never check
  out or run PR-head code (it only labels via the API today).
This commit is contained in:
Gauvino
2026-06-01 20:35:05 +02:00
parent 54ee507209
commit 06510d2bd6
3 changed files with 70 additions and 89 deletions

View File

@@ -1,62 +1,28 @@
#!/usr/bin/env node
const _fs = require("node:fs");
// Symlinks the platform-specific native dirs to `ios` / `android` depending on EXPO_TV.
// Uses fs APIs (no shell) so there is no command-injection surface.
const fs = require("node:fs");
const path = require("node:path");
const process = require("node:process");
const { execSync } = require("node:child_process");
const root = process.cwd();
// const tvosPath = path.join(root, 'iostv');
// const iosPath = path.join(root, 'iosmobile');
// const androidPath = path.join(root, 'androidmobile');
// const androidTVPath = path.join(root, 'androidtv');
// const device = process.argv[2];
// const platform = process.argv[2];
const isTV = process.env.EXPO_TV || false;
const isTV = process.env.EXPO_TV && process.env.EXPO_TV !== "0";
const paths = new Map([
["tvos", path.join(root, "iostv")],
["ios", path.join(root, "iosmobile")],
["android", path.join(root, "androidmobile")],
["androidtv", path.join(root, "androidtv")],
]);
const links = isTV
? { ios: path.join(root, "iostv"), android: path.join(root, "androidtv") }
: {
ios: path.join(root, "iosmobile"),
android: path.join(root, "androidmobile"),
};
// const platformPath = paths.get(platform);
if (isTV) {
stdout = execSync(
`mkdir -p ${paths.get("tvos")}; ln -nsf ${paths.get("tvos")} ios`,
);
console.log(stdout.toString());
stdout = execSync(
`mkdir -p ${paths.get("androidtv")}; ln -nsf ${paths.get(
"androidtv",
)} android`,
);
console.log(stdout.toString());
} else {
stdout = execSync(
`mkdir -p ${paths.get("ios")}; ln -nsf ${paths.get("ios")} ios`,
);
console.log(stdout.toString());
stdout = execSync(
`mkdir -p ${paths.get("android")}; ln -nsf ${paths.get("android")} android`,
);
console.log(stdout.toString());
for (const [link, target] of Object.entries(links)) {
fs.mkdirSync(target, { recursive: true });
try {
fs.unlinkSync(link); // replace an existing symlink/file (ln -nsf)
} catch {
// nothing to remove
}
fs.symlinkSync(target, link);
console.log(`${link} -> ${target}`);
}
// target = "";
// switch (platform) {
// case "tvos":
// target = "ios";
// break;
// case "ios":
// target = "ios";
// break;
// case "android":
// target = "android";
// break;
// case "androidtv":
// target = "android";
// break;
// }