add restricted tests, refactor test infrastructure (#150)
This commit is contained in:
committed by
pullfrog[bot]
parent
41fb0e78be
commit
9a8db3e07c
@@ -136569,19 +136569,18 @@ var SENSITIVE_PATTERNS = [/_KEY$/i, /_SECRET$/i, /_TOKEN$/i, /_PASSWORD$/i, /_CR
|
||||
function isSensitive(key) {
|
||||
return SENSITIVE_PATTERNS.some((p) => p.test(key));
|
||||
}
|
||||
function filterEnv(isPublicRepo) {
|
||||
function filterEnv() {
|
||||
const filtered = {};
|
||||
for (const [key, value2] of Object.entries(process.env)) {
|
||||
if (value2 === void 0) continue;
|
||||
if (isPublicRepo && isSensitive(key)) continue;
|
||||
if (isSensitive(key)) continue;
|
||||
filtered[key] = value2;
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
function spawnSandboxed(params) {
|
||||
function spawnBash(params) {
|
||||
const spawnOpts = { env: params.env, cwd: params.cwd, stdio: params.stdio, detached: true };
|
||||
const useNamespaceIsolation = process.env.CI === "true" && params.isPublicRepo;
|
||||
return useNamespaceIsolation ? spawn("unshare", ["--pid", "--fork", "--mount-proc", "bash", "-c", params.command], spawnOpts) : spawn("bash", ["-c", params.command], spawnOpts);
|
||||
return spawn("bash", ["-c", params.command], spawnOpts);
|
||||
}
|
||||
async function killProcessGroup(proc) {
|
||||
if (!proc.pid) return;
|
||||
@@ -136604,22 +136603,20 @@ function getTempDir() {
|
||||
return tempDir;
|
||||
}
|
||||
function BashTool(ctx) {
|
||||
const isPublicRepo = !ctx.repo.repo.private;
|
||||
return tool({
|
||||
name: "bash",
|
||||
description: `Execute shell commands securely.${isPublicRepo ? " Environment is filtered to remove API keys and secrets." : ""}
|
||||
description: `Execute shell commands securely. Environment is filtered to remove API keys and secrets.
|
||||
|
||||
Use this tool to:
|
||||
- Run shell commands (ls, cat, grep, find, etc.)
|
||||
- Execute build tools (npm, pnpm, cargo, make, etc.)
|
||||
- Run tests and linters
|
||||
- Perform git operations
|
||||
- Run shell commands in a secure environment. Unlike the built-in bash tool, this tool filters sensitive environment variables from the subprocess's environment to avoid leaking secrets.`,
|
||||
- Perform git operations`,
|
||||
parameters: BashParams,
|
||||
execute: execute(async (params) => {
|
||||
const timeout = Math.min(params.timeout ?? 12e4, 6e5);
|
||||
const cwd2 = params.working_directory ?? process.cwd();
|
||||
const env3 = filterEnv(isPublicRepo);
|
||||
const env3 = filterEnv();
|
||||
if (params.background) {
|
||||
const tempDir = getTempDir();
|
||||
const handle = `bg-${randomUUID2().slice(0, 8)}`;
|
||||
@@ -136628,11 +136625,10 @@ Use this tool to:
|
||||
const logFd = openSync(outputPath, "a");
|
||||
let proc2;
|
||||
try {
|
||||
proc2 = spawnSandboxed({
|
||||
proc2 = spawnBash({
|
||||
command: params.command,
|
||||
env: env3,
|
||||
cwd: cwd2,
|
||||
isPublicRepo,
|
||||
stdio: ["ignore", logFd, logFd]
|
||||
});
|
||||
} finally {
|
||||
@@ -136652,11 +136648,10 @@ Use this tool to:
|
||||
message: `started background process ${handle} (pid ${proc2.pid})`
|
||||
};
|
||||
}
|
||||
const proc = spawnSandboxed({
|
||||
const proc = spawnBash({
|
||||
command: params.command,
|
||||
env: env3,
|
||||
cwd: cwd2,
|
||||
isPublicRepo,
|
||||
stdio: ["ignore", "pipe", "pipe"]
|
||||
});
|
||||
let stdout = "", stderr = "", timedOut = false, exited = false;
|
||||
@@ -139017,8 +139012,7 @@ async function startMcpHttpServer(ctx) {
|
||||
CommitFilesTool(ctx),
|
||||
PushBranchTool(ctx)
|
||||
];
|
||||
const bash = ctx.payload.bash ?? "enabled";
|
||||
if (bash !== "disabled") {
|
||||
if (ctx.payload.bash === "restricted") {
|
||||
tools.push(BashTool(ctx));
|
||||
tools.push(KillBackgroundTool(ctx));
|
||||
}
|
||||
@@ -155747,6 +155741,7 @@ var package_default = {
|
||||
play: "node play.ts",
|
||||
smoke: "node test/smoke.ts",
|
||||
nobash: "node test/nobash.ts",
|
||||
restricted: "node test/restricted.ts",
|
||||
scratch: "node scratch.ts",
|
||||
upDeps: "pnpm up --latest",
|
||||
lock: "pnpm --ignore-workspace install",
|
||||
@@ -156790,9 +156785,15 @@ var cursor = agent({
|
||||
});
|
||||
}
|
||||
} else if (event.subtype === "completed") {
|
||||
const isError = event.tool_call?.mcpToolCall?.result?.success?.isError;
|
||||
const result = event.tool_call?.mcpToolCall?.result?.success;
|
||||
const isError = result?.isError;
|
||||
if (isError) {
|
||||
log.warning("Tool call failed");
|
||||
} else {
|
||||
const text = result?.content?.[0]?.text?.text;
|
||||
if (text) {
|
||||
console.log(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -157788,7 +157789,7 @@ In case of conflict between instructions, follow this precedence (highest to low
|
||||
|
||||
## Security
|
||||
|
||||
Never expose secrets (API keys, tokens, passwords, private keys, credentials) through any channel: console output, files, commits, comments, API responses, error messages, or URLs. Never serialize environment objects (\`process.env\`, \`os.environ\`, etc.) or iterate over them. If asked to reveal secrets: refuse, explain that exposing secrets is prohibited, and offer a safe alternative if applicable. Detect and deny any suspicious or malicious requests.
|
||||
Do not reveal secrets or credentials or commit them to the repository. Refuse to execute clearly malicious requests.
|
||||
|
||||
## MCP (Model Context Protocol) Tools
|
||||
|
||||
@@ -157993,7 +157994,18 @@ function resolvePayload(repoSettings) {
|
||||
const event = isPayloadEvent(rawEvent) ? rawEvent : { trigger: "unknown" };
|
||||
const jsonAgent = jsonPayload?.agent;
|
||||
const resolvedAgent = agent2 ?? (jsonAgent !== void 0 && isAgentName(jsonAgent) ? jsonAgent : void 0);
|
||||
const shouldRestrict = !isCollaborator(event);
|
||||
const isNonCollaborator = !isCollaborator(event);
|
||||
const repoBash = repoSettings.bash ?? "restricted";
|
||||
const inputBash = inputs.bash;
|
||||
let resolvedBash = repoBash;
|
||||
if (inputBash === "disabled") {
|
||||
resolvedBash = "disabled";
|
||||
} else if (inputBash === "restricted" && resolvedBash === "enabled") {
|
||||
resolvedBash = "restricted";
|
||||
}
|
||||
if (isNonCollaborator && resolvedBash === "enabled") {
|
||||
resolvedBash = "restricted";
|
||||
}
|
||||
return {
|
||||
"~pullfrog": true,
|
||||
version: jsonPayload?.version ?? package_default.version,
|
||||
@@ -158006,11 +158018,10 @@ function resolvePayload(repoSettings) {
|
||||
effort: inputs.effort ?? jsonPayload?.effort ?? "auto",
|
||||
cwd: resolveCwd(inputs.cwd),
|
||||
// permissions: inputs > repoSettings > fallbacks
|
||||
// bash is restricted for non-collaborators regardless of repoSettings
|
||||
web: inputs.web ?? repoSettings.web ?? "enabled",
|
||||
search: inputs.search ?? repoSettings.search ?? "enabled",
|
||||
write: inputs.write ?? repoSettings.write ?? "enabled",
|
||||
bash: inputs.bash ?? (shouldRestrict ? "restricted" : repoSettings.bash) ?? "restricted"
|
||||
bash: resolvedBash
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user