From 377eeee2c72b222371b774521dafa9c6c0a8480a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Aug 2026 17:02:13 +0000 Subject: [PATCH 1/4] Initial plan From 462288d16de195540ac360041e80b917b510b456 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Aug 2026 17:08:17 +0000 Subject: [PATCH 2/4] Fix scan-images job: use GraphQL to assign Copilot to issue Co-authored-by: britaniar <145056127+britaniar@users.noreply.github.com> --- .github/workflows/trivy.yml | 42 ++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 807e5517..0d7b6c89 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -189,13 +189,49 @@ jobs: } const body = process.env.ISSUE_BODY; - await github.rest.issues.create({ + const issue = await github.rest.issues.create({ owner: context.repo.owner, repo: context.repo.repo, title: title, body: body, - labels: ['security', 'trivy'], - assignees: ['copilot'] + labels: ['security', 'trivy'] }); + + // Assigning the issue to Copilot requires the GraphQL API since the + // Copilot coding agent is not a regular user and cannot be set via + // the REST "assignees" field. + try { + const suggested = await github.graphql( + `query($owner: String!, $repo: String!) { + repository(owner: $owner, name: $repo) { + id + suggestedActors(capabilities: [CAN_BE_ASSIGNED], first: 100) { + nodes { + login + id + } + } + } + }`, + { owner: context.repo.owner, repo: context.repo.repo } + ); + const copilotActor = suggested.repository.suggestedActors.nodes.find( + (actor) => actor.login.toLowerCase() === 'copilot' + ); + if (copilotActor) { + await github.graphql( + `mutation($assignableId: ID!, $actorIds: [ID!]!) { + replaceActorsForAssignable(input: { assignableId: $assignableId, actorIds: $actorIds }) { + clientMutationId + } + }`, + { assignableId: issue.data.node_id, actorIds: [copilotActor.id] } + ); + } else { + console.log('Copilot is not a suggested assignee for this repository, skipping assignment.'); + } + } catch (error) { + console.log(`Failed to assign Copilot to the issue: ${error.message}`); + } env: ISSUE_BODY: ${{ steps.vuln-summary.outputs.body }} From c2a204809000fc6ed39f7d51161334edbf1e6fbc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 18 Aug 2026 17:13:25 +0000 Subject: [PATCH 3/4] Allow manual runs to simulate scheduled trivy scan for testing Co-authored-by: britaniar <145056127+britaniar@users.noreply.github.com> --- .github/workflows/trivy.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 0d7b6c89..90171e69 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -8,7 +8,13 @@ on: create: # Publish semver tags as releases. tags: [ 'v*.*.*' ] - workflow_dispatch: {} + workflow_dispatch: + inputs: + simulate_schedule: + description: 'Simulate a scheduled run (test issue creation/Copilot assignment on vulnerabilities)' + type: boolean + default: false + required: false permissions: contents: read @@ -125,7 +131,7 @@ jobs: echo "has_vulns=$has_vulns" >> "$GITHUB_OUTPUT" - name: Fail on vulnerabilities (non-scheduled runs) - if: steps.check-vulns.outputs.has_vulns == 'true' && github.event_name != 'schedule' + if: steps.check-vulns.outputs.has_vulns == 'true' && github.event_name != 'schedule' && !(github.event_name == 'workflow_dispatch' && inputs.simulate_schedule == true) run: | echo "::error::Vulnerabilities found. See trivy scan output." for file in trivy-hub-net.json trivy-member-net.json trivy-mcs.json; do @@ -135,7 +141,7 @@ jobs: exit 1 - name: Build vulnerability summary - if: steps.check-vulns.outputs.has_vulns == 'true' && github.event_name == 'schedule' + if: steps.check-vulns.outputs.has_vulns == 'true' && (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.simulate_schedule == true)) id: vuln-summary run: | { @@ -167,7 +173,7 @@ jobs: } >> "$GITHUB_OUTPUT" - name: Create issue for Copilot - if: steps.check-vulns.outputs.has_vulns == 'true' && github.event_name == 'schedule' + if: steps.check-vulns.outputs.has_vulns == 'true' && (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.simulate_schedule == true)) uses: actions/github-script@v7 with: script: | From 7a669bb4335d0150453147bd79daa11c00acfc9b Mon Sep 17 00:00:00 2001 From: Britania Rodriguez Reyes Date: Tue, 18 Aug 2026 15:53:36 -0700 Subject: [PATCH 4/4] fix: notify security team for scheduled Trivy findings Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/workflows/trivy.yml | 87 +++++++++++-------------------------- 1 file changed, 25 insertions(+), 62 deletions(-) diff --git a/.github/workflows/trivy.yml b/.github/workflows/trivy.yml index 90171e69..a72f6f05 100644 --- a/.github/workflows/trivy.yml +++ b/.github/workflows/trivy.yml @@ -8,13 +8,7 @@ on: create: # Publish semver tags as releases. tags: [ 'v*.*.*' ] - workflow_dispatch: - inputs: - simulate_schedule: - description: 'Simulate a scheduled run (test issue creation/Copilot assignment on vulnerabilities)' - type: boolean - default: false - required: false + workflow_dispatch: {} permissions: contents: read @@ -131,7 +125,7 @@ jobs: echo "has_vulns=$has_vulns" >> "$GITHUB_OUTPUT" - name: Fail on vulnerabilities (non-scheduled runs) - if: steps.check-vulns.outputs.has_vulns == 'true' && github.event_name != 'schedule' && !(github.event_name == 'workflow_dispatch' && inputs.simulate_schedule == true) + if: steps.check-vulns.outputs.has_vulns == 'true' && github.event_name != 'schedule' run: | echo "::error::Vulnerabilities found. See trivy scan output." for file in trivy-hub-net.json trivy-member-net.json trivy-mcs.json; do @@ -141,7 +135,7 @@ jobs: exit 1 - name: Build vulnerability summary - if: steps.check-vulns.outputs.has_vulns == 'true' && (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.simulate_schedule == true)) + if: steps.check-vulns.outputs.has_vulns == 'true' && github.event_name == 'schedule' id: vuln-summary run: | { @@ -172,13 +166,15 @@ jobs: echo 'EOF' } >> "$GITHUB_OUTPUT" - - name: Create issue for Copilot - if: steps.check-vulns.outputs.has_vulns == 'true' && (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.simulate_schedule == true)) - uses: actions/github-script@v7 + - name: Create or update security issue + if: steps.check-vulns.outputs.has_vulns == 'true' && github.event_name == 'schedule' + uses: actions/github-script@v9 with: script: | const today = new Date().toISOString().split('T')[0]; const title = `fix: address trivy CVEs found on ${today}`; + const securityTeam = '@Azure/fleet-networking-security'; + const body = `${process.env.ISSUE_BODY}\n\n### Security owners\n${securityTeam}`; // Check if an open issue already exists for today const existing = await github.rest.issues.listForRepo({ @@ -188,56 +184,23 @@ jobs: labels: 'security,trivy', per_page: 10 }); - const alreadyExists = existing.data.some(i => i.title === title); - if (alreadyExists) { - console.log('Issue already exists for today, skipping.'); - return; - } - - const body = process.env.ISSUE_BODY; - const issue = await github.rest.issues.create({ - owner: context.repo.owner, - repo: context.repo.repo, - title: title, - body: body, - labels: ['security', 'trivy'] - }); - - // Assigning the issue to Copilot requires the GraphQL API since the - // Copilot coding agent is not a regular user and cannot be set via - // the REST "assignees" field. - try { - const suggested = await github.graphql( - `query($owner: String!, $repo: String!) { - repository(owner: $owner, name: $repo) { - id - suggestedActors(capabilities: [CAN_BE_ASSIGNED], first: 100) { - nodes { - login - id - } - } - } - }`, - { owner: context.repo.owner, repo: context.repo.repo } - ); - const copilotActor = suggested.repository.suggestedActors.nodes.find( - (actor) => actor.login.toLowerCase() === 'copilot' - ); - if (copilotActor) { - await github.graphql( - `mutation($assignableId: ID!, $actorIds: [ID!]!) { - replaceActorsForAssignable(input: { assignableId: $assignableId, actorIds: $actorIds }) { - clientMutationId - } - }`, - { assignableId: issue.data.node_id, actorIds: [copilotActor.id] } - ); - } else { - console.log('Copilot is not a suggested assignee for this repository, skipping assignment.'); - } - } catch (error) { - console.log(`Failed to assign Copilot to the issue: ${error.message}`); + const issue = existing.data.find(i => i.title === title); + if (issue) { + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: body + }); + console.log('Updated the existing issue with the current scan and security team mention.'); + } else { + await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: title, + body: body, + labels: ['security', 'trivy'] + }); } env: ISSUE_BODY: ${{ steps.vuln-summary.outputs.body }}