| 🌐 |
Domain Validation Assist |
Experimental author assist for trusted WinGetValidator URL and domain results. Posts one bounded recommendation only for explicit URL evidence or an exact maintained approval-inventory match. |
| pull_request_target |
roles |
bots |
|
|
|
| wingetvalidator-prod[bot] |
|
|
github.event_name == 'pull_request_target' && github.event.action == 'labeled' && github.actor == 'wingetvalidator-prod[bot]' && github.event.pull_request.user.login != 'wingetbot' && contains(
fromJSON('["Error-Installer-Availability","Validate-Domain-Installer","Validation-404-Error","Validation-Agreement-Domain","Validation-Domain","Validation-Domains-Mismatch","Validation-Forbidden-URL-Error","Validation-Indirect-URL","Validation-Open-Url-Failed","Validation-Unapproved-URL"]'),
github.event.label.name
) |
false |
| name |
uses |
env |
with |
| Collect trusted validation Checks |
actions/github-script@v9 |
| TARGET_PR |
TRIGGER_HEAD_SHA |
| ${{ github.event.pull_request.number || '' }} |
${{ github.event.pull_request.head.sha || '' }} |
|
| github-token |
script |
| ${{ github.token }} |
const fs = require("fs");
const outputPath = "/tmp/gh-aw/validation-checks.json";
fs.mkdirSync("/tmp/gh-aw", { recursive: true });
const owner = "microsoft";
const repo = "winget-pkgs";
const trustedAppId = 1451866;
const trustedAppSlug = "wingetvalidator-prod";
const pullRequestNumber = Number(process.env.TARGET_PR);
const triggerHeadSha = String(process.env.TRIGGER_HEAD_SHA ?? "").trim();
const maxEvidenceBytes = 600000;
const output = {
available: false,
pullRequestNumber: null,
headSha: null,
operationId: null,
currentLabels: [],
completionLabels: [],
completionCheck: null,
checks: [],
checksTruncated: false,
};
const writeOutput = () =>
fs.writeFileSync(outputPath, JSON.stringify(output));
const isTrustedCheck = (check, headSha) =>
check?.app?.id === trustedAppId &&
check?.app?.slug === trustedAppSlug &&
check.head_sha === headSha;
const mapCheck = (check) => {
const limits = { title: 1000, summary: 4000, text: 32000 };
const raw = {};
for (const key of Object.keys(limits)) {
raw[key] = String(check.output?.[key] ?? "");
}
return {
id: check.id,
name: check.name,
conclusion: check.conclusion,
completedAt: check.completed_at,
externalId: check.external_id,
output: {
title: raw.title.slice(0, limits.title),
summary: raw.summary.slice(0, limits.summary),
text: raw.text.slice(0, limits.text),
truncated: Object.keys(limits).some(
(key) => raw[key].length > limits[key],
),
},
};
};
if (!Number.isSafeInteger(pullRequestNumber) || pullRequestNumber <= 0) {
output.reason = "The targeted pull request number is invalid.";
writeOutput();
return;
}
try {
const pull = await github.rest.pulls.get({
owner,
repo,
pull_number: pullRequestNumber,
});
const headSha = String(pull.data.head.sha ?? "").trim();
output.headSha = headSha;
output.currentLabels = (pull.data.labels ?? [])
.map((label) => String(label?.name ?? "").trim())
.filter(Boolean);
if (
pull.data.state !== "open" ||
!/^[0-9a-f]{40}$/i.test(triggerHeadSha) ||
triggerHeadSha !== headSha
) {
output.reason =
"The pull request is closed or the triggering head SHA is missing or stale.";
return;
}
let checkRuns = [];
let totalCheckRuns = 0;
let completionCheck = null;
for (let attempt = 0; attempt < 2; attempt++) {
const response = await github.rest.checks.listForRef({
owner,
repo,
ref: headSha,
app_id: trustedAppId,
filter: "all",
per_page: 100,
});
checkRuns = response.data.check_runs ?? [];
totalCheckRuns = response.data.total_count ?? checkRuns.length;
completionCheck = checkRuns
.filter((check) =>
isTrustedCheck(check, headSha) &&
check.name === "10. Validation Completed" &&
check.status === "completed",
)
.sort((left, right) => {
const timeDifference =
Date.parse(right.completed_at ?? "") -
Date.parse(left.completed_at ?? "");
return timeDifference || Number(right.id) - Number(left.id);
})[0];
if (completionCheck || attempt === 1) {
break;
}
await new Promise((resolve) => setTimeout(resolve, 10000));
}
const completionJsonBlocks = [...String(
completionCheck?.output?.text ?? "",
).matchAll(
/```json\s*([\s\S]*?)```/gi,
)];
let completionPayload = null;
if (completionJsonBlocks.length === 1) {
try {
completionPayload = JSON.parse(completionJsonBlocks[0][1]);
} catch {
completionPayload = null;
}
}
const completionPullRequestNumber = completionPayload?.PullRequestNumber;
const completionOperationId =
String(completionPayload?.OperationId ?? "").trim();
const completionExternalId =
String(completionCheck?.external_id ?? "").trim();
if (
!completionCheck ||
!Number.isSafeInteger(completionPullRequestNumber) ||
completionPullRequestNumber !== pullRequestNumber ||
!completionOperationId ||
completionOperationId !== completionExternalId
) {
output.reason =
"The newest Validation Completed Check is missing or does not bind this pull request to one operation.";
return;
}
const completionTime = Date.parse(completionCheck.completed_at ?? "");
const newerPendingCheck = checkRuns.some(
(check) =>
isTrustedCheck(check, headSha) &&
["queued", "in_progress"].includes(check.status) &&
(Number(check.id) > Number(completionCheck.id) ||
Date.parse(check.started_at ?? "") > completionTime),
);
if (totalCheckRuns > checkRuns.length || newerPendingCheck) {
output.reason =
"Check data is incomplete or a newer validation operation is still running.";
return;
}
output.pullRequestNumber = completionPullRequestNumber;
output.operationId = completionOperationId;
output.completionLabels = Array.isArray(completionPayload?.Labels)
? completionPayload.Labels.map((label) => ({
name: String(label?.Name ?? "").trim(),
result: String(label?.Result ?? "").trim(),
})).filter((label) => label.name)
: [];
const operationChecks = checkRuns
.filter(
(check) =>
isTrustedCheck(check, headSha) &&
check.status === "completed" &&
check.name !== "10. Validation Completed" &&
String(check.external_id ?? "").trim() ===
completionOperationId,
)
.sort((left, right) =>
String(left.name).localeCompare(String(right.name)),
);
output.completionCheck = mapCheck(completionCheck);
output.checks = operationChecks.slice(0, 12).map(mapCheck);
output.checksTruncated =
operationChecks.length > output.checks.length ||
output.completionCheck.output.truncated ||
output.checks.some((check) => check.output.truncated);
output.available = output.checks.length > 0 && !output.checksTruncated;
if (output.checksTruncated) {
output.reason =
"One or more trusted Check outputs were truncated.";
}
if (!output.available) {
output.reason ??=
"No completed trusted Check belongs to the newest validation operation.";
}
if (
output.available &&
Buffer.byteLength(JSON.stringify(output), "utf8") >
maxEvidenceBytes
) {
output.available = false;
output.operationId = null;
output.completionCheck = null;
output.checks = [];
output.reason =
"The complete evidence envelope exceeds the review bound.";
}
} catch (error) {
output.reason = `Validation Check retrieval failed: ${
error instanceof Error ? error.message : String(error)
}`;
} finally {
writeOutput();
}
|
|
|
| name |
uses |
env |
with |
| Skip agent when domain evidence is unavailable |
actions/github-script@v9 |
| GH_AW_SAFE_OUTPUTS |
| ${{ steps.set-runtime-paths.outputs.GH_AW_SAFE_OUTPUTS }} |
|
| script |
| const fs = require("fs");
const path = require("path");
const evidence = JSON.parse(
fs.readFileSync("/tmp/gh-aw/validation-checks.json", "utf8"),
);
if (evidence.available !== true) {
const safeOutputsPath =
String(process.env.GH_AW_SAFE_OUTPUTS ?? "").trim() ||
path.join(
process.env.RUNNER_TEMP || "/tmp",
"gh-aw",
"safeoutputs",
"outputs.jsonl",
);
fs.mkdirSync(path.dirname(safeOutputsPath), { recursive: true });
fs.appendFileSync(
safeOutputsPath,
`${JSON.stringify({
type: "noop",
message: "No trusted domain validation evidence is available.",
})}\n`,
);
}
|
|
|
| name |
uses |
with |
| Upload sealed domain validation evidence |
actions/upload-artifact@v7 |
| name |
path |
if-no-files-found |
retention-days |
| domain-validation-evidence-${{ github.run_id }}-${{ github.run_attempt }} |
/tmp/gh-aw/validation-checks.json |
error |
1 |
|
|
|
| group |
cancel-in-progress |
queue |
| gh-aw-${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} |
false |
max |
|
copilot |
| checks |
contents |
issues |
pull-requests |
copilot-requests |
| read |
read |
read |
read |
write |
|
|
| github |
bash |
| toolsets |
allowed-repos |
min-integrity |
| context |
| repos |
| issues |
| pull_requests |
|
|
none |
|
|
|
| threat-detection |
report-failure-as-issue |
report-failed-jobs |
report-incomplete |
missing-tool |
missing-data |
noop |
jobs |
| true |
false |
false |
|
false |
false |
|
| post-domain-validation-comment |
| description |
runs-on |
needs |
if |
permissions |
inputs |
steps |
| Post the one validated domain-assist comment to the triggering pull request from structured, evidence-bound fields. |
ubuntu-slim |
detection |
needs.detection.result == 'success' && needs.detection.outputs.detection_success == 'true' |
| checks |
contents |
pull-requests |
| read |
read |
write |
|
| classification |
check_name |
hostname |
| description |
required |
type |
| Exact supported domain finding class |
true |
string |
|
| description |
required |
type |
| Exact trusted Check Run name containing the evidence |
true |
string |
|
| description |
required |
type |
| Lowercase hostname named by the trusted Check |
true |
string |
|
|
| name |
uses |
with |
| Download sealed domain validation evidence |
actions/download-artifact@v8 |
| name |
path |
| domain-validation-evidence-${{ github.run_id }}-${{ github.run_attempt }} |
${{ runner.temp }}/domain-validation-evidence |
|
|
| name |
uses |
env |
with |
| Revalidate and post fixed-target comment |
actions/github-script@v9 |
| EVIDENCE_PATH |
TARGET_PR |
EVENT_HEAD |
EVENT_LABEL |
| ${{ runner.temp }}/domain-validation-evidence/validation-checks.json |
${{ github.event.pull_request.number || '' }} |
${{ github.event.pull_request.head.sha || '' }} |
${{ github.event.label.name || '' }} |
|
| github-token |
script |
| ${{ github.token }} |
const fs = require("fs");
const owner = "microsoft";
const repo = "winget-pkgs";
const targetPr = Number(process.env.TARGET_PR);
const eventHead = String(process.env.EVENT_HEAD ?? "").trim();
const eventLabel = String(process.env.EVENT_LABEL ?? "").trim();
const type = "post_domain_validation_comment";
const trustedAppId = 1451866;
const trustedAppSlug = "wingetvalidator-prod";
const footer =
"###### Template: msftbot/authorAssist/domainValidation";
const classifications = new Set([
"DEAD_URL", "MALFORMED_URL", "WAIVER_REVIEW",
"CDN_REDIRECT_REVIEW",
]);
const supported = new Set([
"Error-Installer-Availability", "Validate-Domain-Installer",
"Validation-404-Error", "Validation-Agreement-Domain",
"Validation-Domain", "Validation-Domains-Mismatch",
"Validation-Forbidden-URL-Error", "Validation-Indirect-URL",
"Validation-Open-Url-Failed", "Validation-Unapproved-URL",
]);
const security = new Set([
"Binary-Validation-Error", "Blocking-Issue",
"Error-Analysis-Timeout", "Error-Hash-Mismatch",
"Internal-Error", "Internal-Error-AppsAndFeaturesVersion",
"Internal-Error-Dependencies", "Internal-Error-Domain",
"Internal-Error-Dynamic-Scan", "Internal-Error-Keyword-Policy",
"Internal-Error-Manifest", "Internal-Error-Manifest-Installer",
"Internal-Error-NoArchitectures",
"Internal-Error-NoSupportedArchitectures", "Internal-Error-PR",
"Internal-Error-Static-Scan", "Internal-Error-URL",
"Internal-Error-Webhook", "Needs-SmartScreen-Investigation",
"Network-Blocker", "Package-Flagged", "PUA-Detection",
"PullRequest-Error", "Scripted-Application",
"URL-Validation-Error", "Validation-Certificate-Root",
"Validation-Defender-Error", "Validation-Executable-Error",
"Validation-Hash-Flagged", "Validation-Hash-Verification-Failed",
"Validation-HTTP-Error", "Validation-No-Executables",
"Validation-Shell-Execute", "Validation-SmartScreen",
"Validation-SmartScreen-Error", "Validation-Submission-Expired",
"Validation-Submission-Failed",
"Validation-Submission-Mismatch",
"Validation-Submission-Missing",
"Validation-Submission-Unsupported",
"Validation-Virus-Scan-Error",
]);
const fail = (message) => {
core.setFailed(message);
return false;
};
const parseCompletionPayload = (check) => {
const blocks = [...String(check?.output?.text ?? "").matchAll(
/```json\s*([\s\S]*?)```/gi,
)];
if (blocks.length !== 1) return null;
try {
return JSON.parse(blocks[0][1]);
} catch {
return null;
}
};
const hostnameFromUri = (value) => {
try {
return new URL(value).hostname.toLowerCase();
} catch {
return String(value).match(
/^[a-z][a-z0-9+.-]*://([^/:?#\s]+)/i,
)?.[1]?.toLowerCase() ?? null;
}
};
const parseCsv = (text) => {
const rows = [];
let row = [];
let field = "";
let quoted = false;
for (let index = 0; index < text.length; index++) {
const character = text[index];
if (quoted) {
if (character === '"') {
if (text[index + 1] === '"') {
field += '"';
index++;
} else {
quoted = false;
}
} else {
field += character;
}
} else if (character === '"') {
if (field.length !== 0) {
throw new Error("Invalid CSV quoting.");
}
quoted = true;
} else if (character === ",") {
row.push(field);
field = "";
} else if (character === "\n") {
row.push(field.replace(/\r$/, ""));
rows.push(row);
row = [];
field = "";
} else {
field += character;
}
}
if (quoted) throw new Error("Unterminated CSV field.");
if (field.length !== 0 || row.length !== 0) {
row.push(field.replace(/\r$/, ""));
rows.push(row);
}
return rows;
};
if (
!Number.isSafeInteger(targetPr) ||
targetPr <= 0 ||
!/^[0-9a-f]{40}$/i.test(eventHead) ||
!supported.has(eventLabel)
) {
return fail("Invalid trusted pull-request event context.");
}
let items, evidence;
try {
const evidencePath = process.env.EVIDENCE_PATH;
if (!evidencePath || fs.statSync(evidencePath).size > 600000) {
throw new Error("Sealed evidence is unavailable or oversized.");
}
evidence = JSON.parse(fs.readFileSync(evidencePath, "utf8"));
items = JSON.parse(fs.readFileSync(
process.env.GH_AW_AGENT_OUTPUT, "utf8",
)).items;
} catch {
return fail("Agent output or sealed evidence is missing or invalid.");
}
const operationId = String(evidence?.operationId ?? "");
if (
evidence?.available !== true ||
evidence?.checksTruncated !== false ||
evidence?.pullRequestNumber !== targetPr ||
evidence?.headSha !== eventHead ||
operationId.length === 0 ||
operationId.length > 128 ||
!Array.isArray(evidence?.currentLabels) ||
!evidence.currentLabels.includes(eventLabel) ||
!Array.isArray(evidence?.completionLabels) ||
!evidence.completionLabels.some(
(label) => label?.name === eventLabel,
) ||
evidence?.completionCheck?.name !==
"10. Validation Completed" ||
evidence.completionCheck.externalId !== operationId ||
!Array.isArray(evidence?.checks) ||
evidence.checks.length === 0 ||
evidence.checks.length > 12 ||
evidence.checks.some(
(check) => check?.externalId !== operationId,
)
) {
return fail("Sealed domain evidence is not publishable.");
}
const matches = Array.isArray(items)
? items.filter((item) => item?.type === type) : [];
if (matches.length !== 1) {
return fail("Expected exactly one domain comment output.");
}
const item = matches[0];
const expectedKeys = [
"check_name", "classification", "hostname", "type",
];
if (
Object.keys(item).sort().join(",") !==
expectedKeys.sort().join(",")
) {
return fail("Domain comment output has unexpected fields.");
}
const classification = String(item.classification ?? "").trim();
const checkName = String(item.check_name ?? "").trim();
const hostname = String(item.hostname ?? "").trim();
if (
!classifications.has(classification) ||
!["03. URLs Validation", "04. URL Domain Validation"].includes(
checkName,
) ||
hostname !== hostname.toLowerCase() ||
hostname.length > 253 ||
!/^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(
hostname,
)
) {
return fail("Structured domain output failed validation.");
}
const pull = await github.rest.pulls.get({
owner,
repo,
pull_number: targetPr,
});
const labels = (pull.data.labels ?? [])
.map((label) => String(label?.name ?? ""));
const active = labels.filter((label) => supported.has(label));
if (
pull.data.state !== "open" ||
pull.data.head?.sha !== eventHead ||
active.length !== 1 ||
active[0] !== eventLabel ||
labels.some((label) => security.has(label))
) {
core.notice("Pull request is no longer eligible for a comment.");
return;
}
const files = await github.paginate(
github.rest.pulls.listFiles,
{ owner, repo, pull_number: targetPr, per_page: 100 },
);
if (files.length === 0 || files.length > 100) {
return fail("Current changed-file evidence is incomplete.");
}
const versionFolders = new Set();
const packageIdentifiers = new Set();
for (const file of files) {
const path = String(file?.filename ?? "");
const match = path.match(
/^manifests/[0-9a-z]/((?:[^/]+/)+)([^/]+)/[^/]+.yaml$/,
);
if (!match) {
return fail("Current files are outside one package version.");
}
versionFolders.add(
path.substring(0, path.lastIndexOf("/")),
);
packageIdentifiers.add(
match[1].slice(0, -1).replaceAll("/", "."),
);
}
if (
versionFolders.size !== 1 ||
packageIdentifiers.size !== 1
) {
return fail("Current files do not identify one package version.");
}
const packageIdentifier = [...packageIdentifiers][0];
const classLabels = {
DEAD_URL: new Set([
"Error-Installer-Availability", "Validation-404-Error",
]),
MALFORMED_URL: new Set([
"Validation-Open-Url-Failed",
]),
WAIVER_REVIEW: new Set([
"Validation-Agreement-Domain", "Validation-Domain",
"Validation-Forbidden-URL-Error",
"Validation-Unapproved-URL",
]),
CDN_REDIRECT_REVIEW: new Set([
"Validate-Domain-Installer", "Validation-Domains-Mismatch",
"Validation-Indirect-URL",
]),
};
if (!classLabels[classification].has(eventLabel)) {
return fail("The active label does not support this class.");
}
let manifestField = null;
if (
classification === "WAIVER_REVIEW" ||
classification === "CDN_REDIRECT_REVIEW"
) {
const repository = await github.rest.repos.get({
owner,
repo,
});
const defaultBranch = String(
repository.data.default_branch ?? "",
);
if (
!defaultBranch ||
pull.data.base?.repo?.full_name !== `${owner}/${repo}` ||
pull.data.base?.ref !== defaultBranch
) {
return fail("The pull request does not target the default branch.");
}
const inventoryResponse = await github.rest.repos.getContent({
owner,
repo,
path: "Tools/ManualValidation/Autowaiver.csv",
ref: defaultBranch,
});
const inventory = inventoryResponse.data;
if (
Array.isArray(inventory) ||
inventory.type !== "file" ||
inventory.encoding !== "base64" ||
!Number.isSafeInteger(inventory.size) ||
inventory.size <= 0 ||
inventory.size > 200000
) {
return fail("The current Autowaiver inventory is unavailable.");
}
let rows;
try {
rows = parseCsv(
Buffer.from(inventory.content, "base64").toString("utf8"),
);
} catch {
return fail("The current Autowaiver inventory is invalid.");
}
const header = [
"PackageIdentifier", "ManifestValue", "ManifestKey",
"RemoveLabel",
];
if (
rows.length < 2 ||
rows[0].length !== header.length ||
rows[0].some((value, index) => value !== header[index]) ||
rows.slice(1).some((row) => row.length !== header.length)
) {
return fail("The current Autowaiver inventory shape is invalid.");
}
const expected = [
packageIdentifier, hostname, eventLabel,
].map((value) => value.toLowerCase());
const matchingRows = rows.slice(1).filter((row) =>
row[0].trim().toLowerCase() === expected[0] &&
row[1].trim().toLowerCase() === expected[1] &&
row[3].trim().toLowerCase() === expected[2] &&
/^[A-Za-z][A-Za-z0-9]{0,63}(?:Url|URL)$/.test(
row[2].trim(),
),
);
if (matchingRows.length !== 1) {
return fail("No exact current Autowaiver tuple supports this review.");
}
manifestField = matchingRows[0][2].trim();
}
const [
finalPullResponse,
comments,
reviews,
reviewComments,
] = await Promise.all([
github.rest.pulls.get({
owner,
repo,
pull_number: targetPr,
}),
github.paginate(
github.rest.issues.listComments,
{ owner, repo, issue_number: targetPr, per_page: 100 },
),
github.paginate(
github.rest.pulls.listReviews,
{ owner, repo, pull_number: targetPr, per_page: 100 },
),
github.paginate(
github.rest.pulls.listReviewComments,
{ owner, repo, pull_number: targetPr, per_page: 100 },
),
]);
const finalPull = finalPullResponse.data;
const finalLabels = (finalPull.labels ?? [])
.map((label) => String(label?.name ?? ""));
const finalActive = finalLabels.filter((label) =>
supported.has(label),
);
const duplicate = comments.some((comment) =>
String(comment?.body ?? "").includes(footer) &&
String(comment?.body ?? "").includes(
`Head SHA: `${eventHead}``,
),
);
const feedbackPattern =
/\b(?:URL|URI|domain|hostname|redirect|404|forbidden|waiv(?:e|er))\b/i;
const addressPattern =
/(?:https?://[^\s<>()]+|\b(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?.)+[a-z]{2,63}\b)/i;
const isHumanFeedback = (item) =>
item?.user?.type === "User" &&
!String(item.user?.login ?? "").endsWith("[bot]") &&
(
feedbackPattern.test(String(item.body ?? "")) ||
addressPattern.test(String(item.body ?? ""))
);
const humanFeedback =
comments.some(isHumanFeedback) ||
reviews.some(
(review) =>
review.state !== "DISMISSED" &&
isHumanFeedback(review),
) ||
reviewComments.some(isHumanFeedback);
if (
finalPull.state !== "open" ||
finalPull.head?.sha !== eventHead ||
finalActive.length !== 1 ||
finalActive[0] !== eventLabel ||
finalLabels.some((label) => security.has(label)) ||
finalLabels.some((label) => label.startsWith("Waived-")) ||
humanFeedback ||
duplicate
) {
core.notice("Final pull request gate suppressed the comment.");
return;
}
// Keep this as the final evidence read before rendering and posting.
const checksResponse = await github.rest.checks.listForRef({
owner,
repo,
ref: eventHead,
app_id: trustedAppId,
filter: "all",
per_page: 100,
});
const checkRuns = checksResponse.data.check_runs ?? [];
if (
(checksResponse.data.total_count ?? checkRuns.length) >
checkRuns.length
) {
return fail("Fresh trusted Check evidence is incomplete.");
}
const trustedChecks = checkRuns.filter(
(check) =>
check?.app?.id === trustedAppId &&
check?.app?.slug === trustedAppSlug &&
check.head_sha === eventHead,
);
const operationPattern = new RegExp(
`^WinGetSvc-Validation-${targetPr}-([0-9]+)$`,
);
const selectedSequence = operationPattern.exec(operationId);
const operationSequences = trustedChecks.map((check) => {
const match = operationPattern.exec(
String(check.external_id ?? "").trim(),
);
return match ? BigInt(match[1]) : null;
});
const completionCheck = trustedChecks
.filter(
(check) =>
check.name === "10. Validation Completed" &&
check.status === "completed",
)
.sort(
(left, right) =>
Date.parse(right.completed_at ?? "") -
Date.parse(left.completed_at ?? "") ||
Number(right.id) - Number(left.id),
)[0];
const completionPayload =
parseCompletionPayload(completionCheck);
const freshOperationId = String(
completionPayload?.OperationId ?? "",
).trim();
const completionTime = Date.parse(
completionCheck?.completed_at ?? "",
);
const newerTrustedCheck = trustedChecks.some(
(check) =>
check.id !== completionCheck?.id &&
(
Number(check.id) > Number(completionCheck?.id) ||
Date.parse(check.started_at ?? "") > completionTime
),
);
if (
!completionCheck ||
!selectedSequence ||
operationSequences.some(
(sequence) =>
sequence === null ||
sequence > BigInt(selectedSequence[1]),
) ||
completionPayload?.PullRequestNumber !== targetPr ||
freshOperationId !== operationId ||
String(completionCheck.external_id ?? "").trim() !==
operationId ||
newerTrustedCheck
) {
return fail("The sealed validation operation is no longer newest.");
}
const selectedChecks = trustedChecks.filter(
(check) =>
check.status === "completed" &&
check.name === checkName &&
String(check.external_id ?? "").trim() === operationId,
);
if (selectedChecks.length !== 1) {
return fail("The selected trusted Check is not unique.");
}
const selectedCheck = selectedChecks[0];
if (
!["neutral", "failure", "action_required"].includes(
String(selectedCheck.conclusion ?? "").toLowerCase(),
) ||
!evidence.checks.some(
(check) =>
check?.id === selectedCheck.id &&
check?.name === checkName &&
check?.externalId === operationId,
)
) {
return fail("The selected Check is not bound to sealed evidence.");
}
const checkText = [
selectedCheck.output?.title,
selectedCheck.output?.summary,
selectedCheck.output?.text,
].map((value) => String(value ?? "")).join("\n");
const lines = checkText
.split(/\r?\n/)
.map((line) => line.trim())
.filter(Boolean);
const failedUriLines = lines.filter((line) =>
/\bURI:\s*.*?,\s*Validation result:\s*Failed\b/i.test(line),
);
const urlRecords = lines.map((line) => {
const match = line.match(
/\bURI:\s*(.*?),\s*Validation result:\s*([A-Za-z]+)(.*)$/i,
);
const details = String(match?.[3] ?? "");
const status = details.match(
/(?:^|,\s*)Http status code:\s*([^,\r\n]+)/i,
)?.[1]?.trim().toLowerCase() ?? "";
const diagnostic = details.match(
/(?:^|,\s*)(?:Error Message|Exception|Error):\s*(.+)$/i,
)?.[1]?.trim() ?? "";
const raw = String(match?.[1] ?? "").trim();
return match
? {
diagnostic,
hostname: hostnameFromUri(raw),
href: (() => {
try {
return new URL(raw).href;
} catch {
return null;
}
})(),
line,
raw,
result: match[2].toLowerCase(),
status,
}
: null;
}).filter(Boolean);
const failedRecords = urlRecords.filter(
(record) =>
record.result === "failed" &&
record.hostname,
);
if (
failedUriLines.length !== failedRecords.length ||
failedUriLines.length !==
urlRecords.filter(
(record) => record.result === "failed",
).length
) {
return fail("A failed URI record is incomplete or unparseable.");
}
const deadRecords = failedRecords.filter(
(record) =>
/^(?:404|not[\s_-]*found)$/.test(record.status),
);
const malformedRecords = failedRecords.filter(
(record) =>
/\b(?:(?:invalid|malformed)\s+(?:url|uri)|(?:url|uri)\s+(?:is\s+)?(?:invalid|malformed)|(?:url|uri)\s+format)\b/i.test(
record.diagnostic,
),
);
const forbiddenRecords = failedRecords.filter(
(record) =>
/^(?:403|forbidden)$/.test(record.status),
);
const domainHostnames = new Set();
for (const line of lines) {
const match = line.match(
/(?:^|\b\d{2}:\d{2}:\d{2}Z\s+)-\s+([a-z0-9.-]+)\s*$/i,
);
if (match) domainHostnames.add(match[1].toLowerCase());
}
const oneHost = (records) => {
const hostnames = new Set(
records.map((record) => record.hostname),
);
return hostnames.size === 1 && hostnames.has(hostname);
};
const manualDomainReview =
domainHostnames.size === 1 &&
domainHostnames.has(hostname) &&
/installer URLs need to be validated/i.test(checkText) &&
/needs to go to manual review/i.test(checkText);
const provenClasses = [];
if (
failedRecords.length > 0 &&
deadRecords.length === failedRecords.length &&
oneHost(deadRecords)
) {
provenClasses.push("DEAD_URL");
}
if (
failedRecords.length > 0 &&
malformedRecords.length === failedRecords.length &&
oneHost(malformedRecords)
) {
provenClasses.push("MALFORMED_URL");
}
if (
(
failedRecords.length > 0 &&
forbiddenRecords.length === failedRecords.length &&
oneHost(forbiddenRecords)
) ||
(
failedRecords.length === 0 &&
classification === "WAIVER_REVIEW" &&
manualDomainReview
)
) {
provenClasses.push("WAIVER_REVIEW");
}
if (
failedRecords.length === 0 &&
classification === "CDN_REDIRECT_REVIEW" &&
manualDomainReview
) {
provenClasses.push("CDN_REDIRECT_REVIEW");
}
if (
provenClasses.length !== 1 ||
provenClasses[0] !== classification
) {
return fail("Fresh Check evidence does not prove one class.");
}
const recommendation =
classification === "WAIVER_REVIEW"
? "Wait for maintainer review of the exact approved inventory match; this workflow does not create or promise a waiver."
: classification === "CDN_REDIRECT_REVIEW"
? "Wait for maintainer review of the exact approved redirect or domain inventory match; this workflow does not create or promise a waiver."
: "Replace or remove the invalid or unavailable URL using verified publisher-controlled information; if it is an InstallerUrl, regenerate InstallerSha256.";
const finding =
manifestField
? `field **`${manifestField}`** on hostname **`${hostname}`**`
: `hostname **`${hostname}`**`;
const body = [
"> [!WARNING]",
"> **Experimental automated suggestion - please verify before acting.**",
">",
`> The trusted validation result reported **`${classification}`** for ${finding}.`,
">",
`> **Suggested action:** ${recommendation}`,
">",
"> <details><summary>Validation evidence</summary>",
">",
`> Head SHA: `${eventHead}``,
">",
`> Validation check: `${checkName}``,
">",
"> </details>",
].join("\n");
const runUrl =
`${process.env.GITHUB_SERVER_URL}/` +
`${process.env.GITHUB_REPOSITORY}/actions/runs/` +
process.env.GITHUB_RUN_ID;
const finalBody =
`${body}\n\n${footer} by ` +
`[Domain Validation Assist](${runUrl})`;
if (finalBody.length > 3500) {
return fail("Final comment exceeds its size limit.");
}
await github.rest.issues.createComment({
owner,
repo,
issue_number: targetPr,
body: finalBody,
});
|
|
|
|
|
|
|