-
Notifications
You must be signed in to change notification settings - Fork 307
Add integrity filtering notice to workflow footer #21749
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6f746e9
2d72a73
0e98394
e759a1c
29edd01
ea600f4
c7481a3
bfe900e
1a17129
95b5759
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| // @ts-check | ||
| /// <reference types="@actions/github-script" /> | ||
|
|
||
| /** | ||
| * Gateway DIFC Filtered Module | ||
| * | ||
| * This module handles reading MCP gateway logs and extracting DIFC_FILTERED events | ||
| * for display in AI-generated footers. | ||
| */ | ||
|
|
||
| const fs = require("fs"); | ||
|
|
||
| const GATEWAY_JSONL_PATH = "/tmp/gh-aw/mcp-logs/gateway.jsonl"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These path constants could be configurable via environment variables to improve testability and flexibility across different deployment environments.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The hardcoded path |
||
| const RPC_MESSAGES_PATH = "/tmp/gh-aw/mcp-logs/rpc-messages.jsonl"; | ||
|
|
||
| /** | ||
| * Parses JSONL content and extracts DIFC_FILTERED events | ||
| * @param {string} jsonlContent - The JSONL file content | ||
| * @returns {Array<Object>} Array of DIFC_FILTERED event objects | ||
| */ | ||
| function parseDifcFilteredEvents(jsonlContent) { | ||
| const filteredEvents = []; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good approach using a pre-allocated array for |
||
| const lines = jsonlContent.split("\n"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider using |
||
| for (const line of lines) { | ||
| const trimmed = line.trim(); | ||
| if (!trimmed || !trimmed.includes("DIFC_FILTERED")) continue; | ||
| try { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good optimization using a string pre-check before attempting JSON.parse. This avoids the overhead of parsing lines that clearly won't contain DIFC_FILTERED events. 👍 |
||
| const entry = JSON.parse(trimmed); | ||
| if (entry.type === "DIFC_FILTERED") { | ||
| filteredEvents.push(entry); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The early-exit check |
||
| } | ||
| } catch { | ||
| // skip malformed lines | ||
| } | ||
| } | ||
| return filteredEvents; | ||
|
Comment on lines
+21
to
+36
|
||
| } | ||
|
|
||
| /** | ||
| * Reads DIFC_FILTERED events from MCP gateway logs. | ||
| * | ||
| * This function checks two possible locations for gateway logs: | ||
| * 1. Path specified by gatewayJsonlPath (or /tmp/gh-aw/mcp-logs/gateway.jsonl by default) | ||
| * 2. Path specified by rpcMessagesPath (or /tmp/gh-aw/mcp-logs/rpc-messages.jsonl as fallback) | ||
| * | ||
| * @param {string} [gatewayJsonlPath] - Path to gateway.jsonl. Defaults to /tmp/gh-aw/mcp-logs/gateway.jsonl | ||
| * @param {string} [rpcMessagesPath] - Path to rpc-messages.jsonl fallback. Defaults to /tmp/gh-aw/mcp-logs/rpc-messages.jsonl | ||
| * @returns {Array<Object>} Array of DIFC_FILTERED event objects | ||
| */ | ||
| function getDifcFilteredEvents(gatewayJsonlPath, rpcMessagesPath) { | ||
| const jsonlPath = gatewayJsonlPath || GATEWAY_JSONL_PATH; | ||
| const rpcPath = rpcMessagesPath || RPC_MESSAGES_PATH; | ||
|
|
||
| if (fs.existsSync(jsonlPath)) { | ||
| try { | ||
| const content = fs.readFileSync(jsonlPath, "utf8"); | ||
| return parseDifcFilteredEvents(content); | ||
| } catch { | ||
| return []; | ||
| } | ||
| } | ||
|
|
||
| if (fs.existsSync(rpcPath)) { | ||
| try { | ||
| const content = fs.readFileSync(rpcPath, "utf8"); | ||
| return parseDifcFilteredEvents(content); | ||
| } catch { | ||
| return []; | ||
| } | ||
| } | ||
|
|
||
| return []; | ||
| } | ||
|
|
||
| /** | ||
| * Generates HTML details/summary section for integrity-filtered items wrapped in a GitHub note alert. | ||
| * @param {Array<Object>} filteredEvents - Array of DIFC_FILTERED event objects | ||
| * @returns {string} GitHub note alert with details section, or empty string if no filtered events | ||
| */ | ||
| function generateDifcFilteredSection(filteredEvents) { | ||
| if (!filteredEvents || filteredEvents.length === 0) { | ||
| return ""; | ||
| } | ||
|
|
||
| // Deduplicate events by their significant fields | ||
| const seen = new Set(); | ||
| const uniqueEvents = filteredEvents.filter(event => { | ||
| const key = [event.html_url || "", event.tool_name || "", event.description || "", event.reason || ""].join("|"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The deduplication key includes all four fields joined by |
||
| if (seen.has(key)) return false; | ||
| seen.add(key); | ||
| return true; | ||
| }); | ||
|
|
||
| const count = uniqueEvents.length; | ||
| const itemWord = count === 1 ? "item" : "items"; | ||
|
|
||
| let section = "\n\n> [!NOTE]\n"; | ||
| section += `> <details>\n`; | ||
| section += `> <summary>🔒 Integrity filtering filtered ${count} ${itemWord}</summary>\n`; | ||
| section += `>\n`; | ||
| section += `> Integrity filtering activated and filtered the following ${itemWord} during workflow execution.\n`; | ||
| section += `> This happens when a tool call accesses a resource that does not meet the required integrity or secrecy level of the workflow.\n`; | ||
| section += `>\n`; | ||
|
|
||
| const maxItems = 16; | ||
| const visibleEvents = uniqueEvents.slice(0, maxItems); | ||
| const remainingCount = uniqueEvents.length - visibleEvents.length; | ||
|
|
||
| for (const event of visibleEvents) { | ||
| let reference; | ||
| if (event.html_url) { | ||
| const label = event.number ? `#${event.number}` : event.html_url; | ||
| reference = `[${label}](${event.html_url})`; | ||
| } else { | ||
| reference = event.description || (event.tool_name ? `\`${event.tool_name}\`` : "-"); | ||
| } | ||
| const tool = event.tool_name ? `\`${event.tool_name}\`` : "-"; | ||
| const reason = (event.reason || "-").replace(/\n/g, " "); | ||
| section += `> - ${reference} (${tool}: ${reason})\n`; | ||
| } | ||
|
|
||
| if (remainingCount > 0) { | ||
| section += `> - ... and ${remainingCount} more ${remainingCount === 1 ? "item" : "items"}\n`; | ||
| } | ||
|
|
||
| section += `>\n`; | ||
| section += `> </details>\n`; | ||
|
|
||
| return section; | ||
| } | ||
|
|
||
| module.exports = { | ||
| parseDifcFilteredEvents, | ||
| getDifcFilteredEvents, | ||
| generateDifcFilteredSection, | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
GATEWAY_JSONL_PATHconstant is hardcoded to/tmp/gh-aw/mcp-logs/gateway.jsonl. Consider making this configurable via environment variable to support different deployment environments.