fix autofix body leak, harden prompt against injection, trigger-aware comments (#512)
* fix autofix body leak, harden prompt against injection, trigger-aware comments never forward event bodies to the agent prompt — they are user-generated content and a prompt injection vector. the agent fetches bodies on demand via MCP tools (checkout_pr, get_issue, etc.). - always set event.body to null in dispatch(), add promptFromBody: false to autofix, strip body from nested pull_request object - replace buildEventTitleBody with buildEventTitle rendering inline references like PR #497 ("Title") instead of raw markdown headings - add LEAPING_REASON_MAP for trigger-aware progress comments (e.g. "CI failure detected. Leaping into action...") - thread type through buildLeapingIntoActionComment, createLeapingComment, and updateCommentToLeaping Made-with: Cursor * rename translateWorkflowRunType.ts to workflowRunTypes.ts Made-with: Cursor
This commit is contained in:
committed by
pullfrog[bot]
parent
d525fc21be
commit
37f984f4f8
@@ -150317,17 +150317,11 @@ function buildRuntimeContext(ctx) {
|
||||
const filtered = Object.fromEntries(Object.entries(data).filter(([_2, v]) => v !== void 0));
|
||||
return encode(filtered);
|
||||
}
|
||||
function buildEventTitleBody(event) {
|
||||
const sections = [];
|
||||
function buildEventTitle(event) {
|
||||
const trimmedTitle = typeof event.title === "string" ? event.title.trim() : "";
|
||||
const trimmedBody = typeof event.body === "string" ? event.body.trim() : "";
|
||||
if (trimmedTitle) {
|
||||
sections.push(`# ${trimmedTitle}`);
|
||||
}
|
||||
if (trimmedBody) {
|
||||
sections.push(trimmedBody);
|
||||
}
|
||||
return sections.join("\n\n");
|
||||
if (!trimmedTitle) return "";
|
||||
const prefix = event.issue_number ? `${event.is_pr ? "PR" : "Issue"} #${event.issue_number}` : "";
|
||||
return prefix ? `${prefix} ("${trimmedTitle}")` : `("${trimmedTitle}")`;
|
||||
}
|
||||
function buildEventMetadata(event) {
|
||||
const { title: _t, body: _b, trigger, ...rest } = event;
|
||||
@@ -150485,9 +150479,9 @@ function buildContextSections(ctx) {
|
||||
const eventInstructionsSection = ctx.eventInstructions ? `************* EVENT-LEVEL INSTRUCTIONS *************
|
||||
|
||||
${ctx.eventInstructions}` : "";
|
||||
const titleBodySection = ctx.eventTitleBody ? `${relatedLabel}
|
||||
const titleBodySection = ctx.eventTitle ? `${relatedLabel}
|
||||
|
||||
${ctx.eventTitleBody}` : "";
|
||||
${ctx.eventTitle}` : "";
|
||||
const metadataSection = ctx.eventMetadata ? `--- event context ---
|
||||
|
||||
${ctx.eventMetadata}` : "";
|
||||
@@ -150505,15 +150499,15 @@ ${metadataSection}`;
|
||||
return [eventInstructionsSection, userSection].filter(Boolean).join("\n\n");
|
||||
}
|
||||
function buildCommonInputs(ctx) {
|
||||
const eventTitleBody = buildEventTitleBody(ctx.payload.event);
|
||||
const eventTitle = buildEventTitle(ctx.payload.event);
|
||||
const eventMetadata = buildEventMetadata(ctx.payload.event);
|
||||
const runtime = buildRuntimeContext(ctx);
|
||||
const user = ctx.payload.prompt;
|
||||
const eventInstructions = ctx.payload.eventInstructions ?? "";
|
||||
const event = [eventTitleBody, eventMetadata].filter(Boolean).join("\n\n---\n\n");
|
||||
const event = [eventTitle, eventMetadata].filter(Boolean).join("\n\n---\n\n");
|
||||
const userQuoted = user ? user.split("\n").map((line) => `> ${line}`).join("\n") : "";
|
||||
return {
|
||||
eventTitleBody,
|
||||
eventTitle,
|
||||
eventMetadata,
|
||||
runtime,
|
||||
user,
|
||||
@@ -150567,7 +150561,7 @@ If the task clearly requires no work, call \`${ghPullfrogMcpName}/report_progres
|
||||
const contextSections = buildContextSections({
|
||||
payload: ctx.payload,
|
||||
eventInstructions: inputs.eventInstructions,
|
||||
eventTitleBody: inputs.eventTitleBody,
|
||||
eventTitle: inputs.eventTitle,
|
||||
eventMetadata: inputs.eventMetadata,
|
||||
userQuoted: inputs.userQuoted
|
||||
});
|
||||
|
||||
+11
-20
@@ -53,22 +53,13 @@ function buildRuntimeContext(ctx: InstructionsContext): string {
|
||||
return toonEncode(filtered);
|
||||
}
|
||||
|
||||
function buildEventTitleBody(event: PayloadEvent): string {
|
||||
const sections: string[] = [];
|
||||
|
||||
// render title + body as markdown
|
||||
function buildEventTitle(event: PayloadEvent): string {
|
||||
const trimmedTitle = typeof event.title === "string" ? event.title.trim() : "";
|
||||
const trimmedBody = typeof event.body === "string" ? event.body.trim() : "";
|
||||
if (!trimmedTitle) return "";
|
||||
|
||||
if (trimmedTitle) {
|
||||
sections.push(`# ${trimmedTitle}`);
|
||||
}
|
||||
const prefix = event.issue_number ? `${event.is_pr ? "PR" : "Issue"} #${event.issue_number}` : "";
|
||||
|
||||
if (trimmedBody) {
|
||||
sections.push(trimmedBody);
|
||||
}
|
||||
|
||||
return sections.join("\n\n");
|
||||
return prefix ? `${prefix} ("${trimmedTitle}")` : `("${trimmedTitle}")`;
|
||||
}
|
||||
|
||||
function buildEventMetadata(event: PayloadEvent): string {
|
||||
@@ -261,7 +252,7 @@ export interface ResolvedInstructions {
|
||||
interface ContextSectionsInput {
|
||||
payload: ResolvedPayload;
|
||||
eventInstructions: string;
|
||||
eventTitleBody: string;
|
||||
eventTitle: string;
|
||||
eventMetadata: string;
|
||||
userQuoted: string;
|
||||
}
|
||||
@@ -276,7 +267,7 @@ function buildContextSections(ctx: ContextSectionsInput): string {
|
||||
${ctx.eventInstructions}`
|
||||
: "";
|
||||
|
||||
const titleBodySection = ctx.eventTitleBody ? `${relatedLabel}\n\n${ctx.eventTitleBody}` : "";
|
||||
const titleBodySection = ctx.eventTitle ? `${relatedLabel}\n\n${ctx.eventTitle}` : "";
|
||||
const metadataSection = ctx.eventMetadata ? `--- event context ---\n\n${ctx.eventMetadata}` : "";
|
||||
|
||||
const userSection = ctx.userQuoted
|
||||
@@ -298,7 +289,7 @@ ${metadataSection}`;
|
||||
|
||||
// shared computation for all instruction builders
|
||||
interface CommonInputs {
|
||||
eventTitleBody: string;
|
||||
eventTitle: string;
|
||||
eventMetadata: string;
|
||||
runtime: string;
|
||||
user: string;
|
||||
@@ -308,12 +299,12 @@ interface CommonInputs {
|
||||
}
|
||||
|
||||
function buildCommonInputs(ctx: InstructionsContext): CommonInputs {
|
||||
const eventTitleBody = buildEventTitleBody(ctx.payload.event);
|
||||
const eventTitle = buildEventTitle(ctx.payload.event);
|
||||
const eventMetadata = buildEventMetadata(ctx.payload.event);
|
||||
const runtime = buildRuntimeContext(ctx);
|
||||
const user = ctx.payload.prompt;
|
||||
const eventInstructions = ctx.payload.eventInstructions ?? "";
|
||||
const event = [eventTitleBody, eventMetadata].filter(Boolean).join("\n\n---\n\n");
|
||||
const event = [eventTitle, eventMetadata].filter(Boolean).join("\n\n---\n\n");
|
||||
const userQuoted = user
|
||||
? user
|
||||
.split("\n")
|
||||
@@ -321,7 +312,7 @@ function buildCommonInputs(ctx: InstructionsContext): CommonInputs {
|
||||
.join("\n")
|
||||
: "";
|
||||
return {
|
||||
eventTitleBody,
|
||||
eventTitle,
|
||||
eventMetadata,
|
||||
runtime,
|
||||
user,
|
||||
@@ -388,7 +379,7 @@ If the task clearly requires no work, call \`${ghPullfrogMcpName}/report_progres
|
||||
const contextSections = buildContextSections({
|
||||
payload: ctx.payload,
|
||||
eventInstructions: inputs.eventInstructions,
|
||||
eventTitleBody: inputs.eventTitleBody,
|
||||
eventTitle: inputs.eventTitle,
|
||||
eventMetadata: inputs.eventMetadata,
|
||||
userQuoted: inputs.userQuoted,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user