fix(ci): keep secrets out of gitea run logs
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 31s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Failing after 31s
CD Pipeline / build-and-deploy (push) Has been skipped
CD Pipeline / post-deploy-checks (push) Has been skipped
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
* Guard against putting secrets in Gitea step env/with blocks.
|
||||
* Gitea/act_runner logs may render those blocks before masking is effective.
|
||||
* Guard against putting secrets directly in executable Gitea workflow text.
|
||||
* Gitea/act_runner renders `run:` scripts before masking is effective, so
|
||||
* `${{ secrets.* }}` must stay out of shell bodies and action `with:` inputs.
|
||||
* Narrow step `env:` is the least-bad transport here because the printed shell
|
||||
* body can reference only variable names.
|
||||
*/
|
||||
|
||||
const fs = require("fs");
|
||||
@@ -11,6 +14,7 @@ const root = path.resolve(__dirname, "../..");
|
||||
const workflowDir = path.join(root, ".gitea", "workflows");
|
||||
const violations = [];
|
||||
const routeViolations = [];
|
||||
const secretExprPattern = /\$\{\{\s*secrets\./;
|
||||
|
||||
for (const fileName of fs.readdirSync(workflowDir).sort()) {
|
||||
if (!fileName.endsWith(".yml") && !fileName.endsWith(".yaml")) {
|
||||
@@ -49,7 +53,12 @@ for (const fileName of fs.readdirSync(workflowDir).sort()) {
|
||||
block = null;
|
||||
}
|
||||
|
||||
const blockMatch = line.match(/^(\s*)(env|with):\s*$/);
|
||||
if ((trimmed.startsWith("run:") || trimmed.startsWith("with:")) && secretExprPattern.test(line)) {
|
||||
const inlineSection = trimmed.startsWith("with:") ? "with" : "run";
|
||||
violations.push(`${filePath}:${index + 1}:${inlineSection}`);
|
||||
}
|
||||
|
||||
const blockMatch = line.match(/^(\s*)(env|with|run):\s*(?:[>|].*)?$/);
|
||||
if (blockMatch) {
|
||||
block = {
|
||||
indent: blockMatch[1].length,
|
||||
@@ -58,14 +67,14 @@ for (const fileName of fs.readdirSync(workflowDir).sort()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (block && line.includes("${{ secrets.")) {
|
||||
if (block && block.section !== "env" && secretExprPattern.test(line)) {
|
||||
violations.push(`${filePath}:${index + 1}:${block.section}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (violations.length > 0) {
|
||||
console.error("Gitea workflow exposes secrets through step env/with:");
|
||||
console.error("Gitea workflow exposes secrets through run/with text:");
|
||||
for (const violation of violations) {
|
||||
console.error(` - ${violation}`);
|
||||
}
|
||||
@@ -80,4 +89,4 @@ if (routeViolations.length > 0) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log("no Gitea step env/with secrets or legacy Telegram routes");
|
||||
console.log("no Gitea run/with secrets or legacy Telegram routes");
|
||||
|
||||
Reference in New Issue
Block a user