Let gitea_api send only the query keys it needs, never sudo, and never approve a pull request
The confirmation review of 2026-10-09 measured GET /user?sudo=… answer the operator's own account: the query went to the forge unjudged, and the tools' token is the site administrator's, so any caller could act as any user. gitea_api now sends only allow-listed query keys and refuses sudo in any case, and a review that approves or requests changes is the operator's.
This commit is contained in:
@@ -14,7 +14,7 @@ import { GiteaClient, type BranchProtection } from "../client.js";
|
||||
import { appendNote, deliveryStatus, run, viewBody, viewComment } from "../delivery.js";
|
||||
import { containedFrom, isCommit, mergeableUnder, newestByContext } from "../checks.js";
|
||||
import {
|
||||
MERGE_METHODS, Refused, checkName, judgeApiCall, judgeContentsWrite, judgeDelete, judgeProtectionChange, routedPath,
|
||||
MERGE_METHODS, Refused, checkName, judgeApiCall, judgeContentsWrite, judgeDelete, judgeProtectionChange, routedPath, sentQuery,
|
||||
ruleCovers,
|
||||
} from "../guard.js";
|
||||
|
||||
@@ -643,10 +643,9 @@ function allGiteaTools(gitea: GiteaClient): ToolDefinition[] {
|
||||
await gitea.branchProtections(owner, repo));
|
||||
if (refused) throw new Refused(refused);
|
||||
}
|
||||
// The path judged is the path sent: normalised, its query kept.
|
||||
// The path judged is the path sent: normalised, with only the allow-listed query keys (guard.ts).
|
||||
const raw = String(args.path ?? "");
|
||||
const query = raw.includes("?") ? raw.slice(raw.indexOf("?")).split("#")[0] : "";
|
||||
const result = await gitea.api(routedPath(raw) + query, {
|
||||
const result = await gitea.api(routedPath(raw) + sentQuery(raw), {
|
||||
method,
|
||||
...(args.body ? { body: JSON.stringify(args.body) } : {}),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user