diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json index bec60902c..3cbfba9a0 100644 --- a/.github/plugin/marketplace.json +++ b/.github/plugin/marketplace.json @@ -1389,8 +1389,8 @@ { "name": "github-security", "source": "plugins/github-security", - "description": "Security extension for GitHub Copilot App with a canvas to work on GHAS findings.", - "version": "0.2.0" + "description": "GitHub Security canvas for Copilot. Review your session's changes for vulnerabilities and fix code scanning alerts.", + "version": "0.2.1" }, { "name": "globestudio", diff --git a/docs/README.plugins.md b/docs/README.plugins.md index 10dd04d74..49d74cb33 100644 --- a/docs/README.plugins.md +++ b/docs/README.plugins.md @@ -74,7 +74,7 @@ See [CONTRIBUTING.md](../CONTRIBUTING.md#adding-plugins) for guidelines on how t | [gem-team](../plugins/gem-team/README.md) | Self-Learning Multi-agent orchestration framework for spec-driven development and automated verification. With smarter tool calling and leaner context. | 14 items | multi-agent, orchestration, tdd, testing, e2e, devops, security-audit, code-review, prd, mobile | | [gesture-review](../plugins/gesture-review/README.md) | Review pull requests with a live camera feed and approve or reject using thumbs-up/thumbs-down gestures. | 1 items | camera-input, gesture-control, github-prs, hands-free, mediapipe, pull-request-review | | [git-worktree-explorer](../plugins/git-worktree-explorer/README.md) | Visualize the active Git repository through worktrees, branches, commits, and optional GitHub pull request context. | 1 items | branch-visualization, canvas, commit-history, git, repository-topology, worktrees | -| [github-security](../plugins/github-security/README.md) | Security extension for GitHub Copilot App with a canvas to work on GHAS findings. | 1 items | security, code-scanning, canvas, ghas, alert, finding | +| [github-security](../plugins/github-security/README.md) | GitHub Security canvas for Copilot. Review your session's changes for vulnerabilities and fix code scanning alerts. | 1 items | security, code-scanning, canvas, ghas, alert, finding | | [globestudio](../plugins/globestudio/README.md) | Make dotted world maps and animated 3D globes and put them on a website. Bundles the globestudio skill, which writes the design as one config and embeds it as an iframe, a React component or a web component, with the hosted Globestudio MCP server for presets, share links and embed code. Free, MIT, no API key. | 1 items | globe, maps, dotted-map, 3d-globe, data-visualization, embed, react, web-component, mcp, design | | [go-mcp-development](../plugins/go-mcp-development/README.md) | Complete toolkit for building Model Context Protocol (MCP) servers in Go using the official github.com/modelcontextprotocol/go-sdk. Includes instructions for best practices, a prompt for generating servers, and an expert chat mode for guidance. | 2 items | go, golang, mcp, model-context-protocol, server-development, sdk | | [java-development](../plugins/java-development/README.md) | Comprehensive collection of prompts and instructions for Java development including Spring Boot, Quarkus, testing, documentation, and best practices. | 4 items | java, springboot, quarkus, jpa, junit, javadoc | diff --git a/extensions/github-security/README.md b/extensions/github-security/README.md new file mode 100644 index 000000000..fb9c90bcb --- /dev/null +++ b/extensions/github-security/README.md @@ -0,0 +1,81 @@ +# GitHub Security + +Bring security into your Copilot workflow. The official GitHub Security extension adds a **GitHub Security** canvas to help you catch vulnerabilities early and work through existing findings, all without leaving your session: + +- **Catch new vulnerabilities before they ship.** Run a security review of the changes you're making in the current session, so you can fix problems before you open a pull request. +- **Fix vulnerabilities already in your code.** Bring your repository's existing code scanning alerts into the session and hand them to Copilot to explain and fix. + + + +## Features + +### Catch security issues before your pull request + +- **Review as you work.** Run a security review of your session’s changes and see the findings in the canvas. +- **Fix before you push.** Hand review findings back to Copilot to fix in the same session, while the context is still fresh. + +### Work through existing code scanning alerts + +- **Code scanning alerts in your session.** Load code scanning alerts for the current repository from GitHub.com or GitHub Enterprise Cloud and browse them alongside your code. +- **Filter and triage.** Filter findings by severity, tools, or assignees, and see assignees, tags and linked pull requests at a glance. +- **Dismiss alerts.** Dismiss code scanning alerts with a reason directly from the canvas. + +### Understand and fix each finding + +- **See the code around it.** Findings include a highlighted snippet from your checkout. +- **Get a clear explanation.** Ask Copilot to explain one or more findings. +- **Make a fix you can review.** Ask Copilot to update your code, then review its changes. + +## Requirements + +- The GitHub Copilot App. Standalone Copilot CLI is not supported. +- A repository on GitHub.com or GitHub Enterprise Cloud. GitHub Enterprise Server is not supported. +- Access to code scanning alerts for the repository (GitHub Advanced Security or GitHub Code Security), to work with existing alerts. +- A local checkout of the repository, opened as a session in the Copilot App. + +To load existing code scanning alerts, your Copilot App version must support GitHub authentication for extensions. Security reviews of your session's changes work without it. + +## Install + +### From the Copilot App + +1. Open **Customize** and select the **Plugins** tab. +2. Find **github-security** in the **awesome-copilot** marketplace and select **Install**. +3. Reload extensions. You may need to start a new session before the **GitHub Security** canvas appears. + +### From the terminal + +With the Copilot App closed, run: + +```shell +copilot plugin install github-security@awesome-copilot +``` + +To keep the extension current, open the **Update all** menu on the **Plugins** tab and select **Update plugins automatically**, or run `copilot plugin update github-security@awesome-copilot`. + +## Agent tools + +The extension registers tools that Copilot can call during a session. Each call goes through Copilot's normal per-invocation approval, the extension never bypasses tool permission prompts. + +| Tool | What it does | +| --- | --- | +| `fetchGhasFindings` | Loads code scanning alerts for the current repository into the canvas. | +| `loadLocalFindings` | Adds findings from a local security review to the canvas. | +| `runFindingWorkflow` | Runs the explain, fix or recheck workflow for selected findings. | +| `reportFindingStatus` | Records whether a finding is resolved or still present after a fix or recheck. | +| `getExtensionState` | Reads the canvas state so Copilot knows which findings you're looking at. | + +## Data and permissions + +- The extension authenticates with the GitHub account you're signed in to in the Copilot App. It doesn't ask for or store tokens. +- Code scanning API requests use the repository's host, and the canvas loads assignee avatars from URLs returned by GitHub. The canvas runs on a local loopback server: static assets do not require authentication, while state, command and code-snippet endpoints require a per-instance token. +- Explain, fix and recheck run in your existing Copilot session and model. The extension doesn't call any other AI service. +- **Resolved** and **In progress** statuses set by Copilot are local to your session. They don't close or change code scanning alerts. Only an explicit **Dismiss** action updates the alert on GitHub. + +Security findings and generated fixes require review. They don't guarantee that a repository is free of vulnerabilities. + +## Third-party notices + +The bundled dependencies' versions, licenses and notices are included with the +[extension](https://github.com/github/awesome-copilot/blob/main/extensions/github-security/THIRD_PARTY_NOTICES.md) and +[canvas](https://github.com/github/awesome-copilot/blob/main/extensions/github-security/client/THIRD_PARTY_NOTICES.md). diff --git a/extensions/github-security/assets/preview.png b/extensions/github-security/assets/preview.png index c8987b829..072cf13df 100644 Binary files a/extensions/github-security/assets/preview.png and b/extensions/github-security/assets/preview.png differ diff --git a/extensions/github-security/assets/screenshot.png b/extensions/github-security/assets/screenshot.png new file mode 100644 index 000000000..072cf13df Binary files /dev/null and b/extensions/github-security/assets/screenshot.png differ diff --git a/extensions/github-security/client/assets/index-b7LlkNjg.css b/extensions/github-security/client/assets/index-D4k0QXEX.css similarity index 99% rename from extensions/github-security/client/assets/index-b7LlkNjg.css rename to extensions/github-security/client/assets/index-D4k0QXEX.css index ca30bc18c..6bea07fc6 100644 --- a/extensions/github-security/client/assets/index-b7LlkNjg.css +++ b/extensions/github-security/client/assets/index-D4k0QXEX.css @@ -396,7 +396,7 @@ } li:hover .finding-row-status, - li:focus-within .finding-row-status, + li:has(:focus-visible) .finding-row-status, .finding-row-actions-open .finding-row-status { visibility: hidden; } @@ -1728,16 +1728,16 @@ user-select: text; } - .group-focus-within\:opacity-100:is(:where(.group):focus-within *) { - opacity: 1; - } - @media (hover: hover) { .group-hover\:opacity-100:is(:where(.group):hover *) { opacity: 1; } } + .group-has-\[\:focus-visible\]\:opacity-100:is(:where(.group):has(:focus-visible) *) { + opacity: 1; + } + .before\:pointer-events-none:before { content: var(--tw-content); pointer-events: none; @@ -1892,14 +1892,6 @@ opacity: 1; } - .\@sm\:group-focus-within\:pointer-events-auto:is(:where(.group):focus-within *) { - pointer-events: auto; - } - - .\@sm\:group-focus-within\:opacity-100:is(:where(.group):focus-within *) { - opacity: 1; - } - @media (hover: hover) { .\@sm\:group-hover\:pointer-events-auto:is(:where(.group):hover *) { pointer-events: auto; @@ -1909,6 +1901,14 @@ opacity: 1; } } + + .\@sm\:group-has-\[\:focus-visible\]\:pointer-events-auto:is(:where(.group):has(:focus-visible) *) { + pointer-events: auto; + } + + .\@sm\:group-has-\[\:focus-visible\]\:opacity-100:is(:where(.group):has(:focus-visible) *) { + opacity: 1; + } } .\[\&_\[data-description-variant\=block\]\]\:-translate-y-0\.5 [data-description-variant="block"] { diff --git a/extensions/github-security/client/assets/index-Cqu7KDJY.js b/extensions/github-security/client/assets/index-_8h8h3EK.js similarity index 99% rename from extensions/github-security/client/assets/index-Cqu7KDJY.js rename to extensions/github-security/client/assets/index-_8h8h3EK.js index ce06f1d45..30e659ab4 100644 --- a/extensions/github-security/client/assets/index-Cqu7KDJY.js +++ b/extensions/github-security/client/assets/index-_8h8h3EK.js @@ -48153,11 +48153,16 @@ function ScrollContainer({ restorationKey, restorationVersion, ...props }) { //#region canvas/components/StaleLocalReviewMessage.tsx var message = "Code has changed since review"; function StaleLocalReviewMessage({ className = "", withSeparator = false }) { + const [isTruncated, setIsTruncated] = (0, import_react.useState)(false); return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { "aria-label": message, className, + onMouseEnter: (event) => { + const { scrollWidth, clientWidth } = event.currentTarget; + setIsTruncated(scrollWidth > clientWidth); + }, role: "note", - title: message, + title: isTruncated ? message : void 0, children: [withSeparator && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ "\xA0", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { @@ -48761,7 +48766,7 @@ function FindingActions({ disabled, displayTitle, moreActions, moreActionsOpen, }); return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { "aria-label": `Actions for ${displayTitle}`, - className: `flex w-full gap-1 pt-2 opacity-100 @sm:w-auto @sm:shrink-0 @sm:pt-0 [@media(hover:none)]:pointer-events-auto [@media(hover:none)]:opacity-100 ${moreActionsOpen ? "@sm:pointer-events-auto @sm:opacity-100" : "@sm:pointer-events-none @sm:opacity-0 @sm:group-hover:pointer-events-auto @sm:group-hover:opacity-100 @sm:group-focus-within:pointer-events-auto @sm:group-focus-within:opacity-100"}`, + className: `flex w-full gap-1 pt-2 opacity-100 @sm:w-auto @sm:shrink-0 @sm:pt-0 [@media(hover:none)]:pointer-events-auto [@media(hover:none)]:opacity-100 ${moreActionsOpen ? "@sm:pointer-events-auto @sm:opacity-100" : "@sm:pointer-events-none @sm:opacity-0 @sm:group-hover:pointer-events-auto @sm:group-hover:opacity-100 @sm:group-has-[:focus-visible]:pointer-events-auto @sm:group-has-[:focus-visible]:opacity-100"}`, role: "group", children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tooltip, { @@ -48836,7 +48841,7 @@ function FindingItem({ finding, individualActionsDisabled, isSelected, listKey, finding.id, /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { "aria-label": `View details for ${displayTitle}`, - className: `ml-1 inline-flex items-center rounded border-0 bg-transparent p-0 align-text-bottom text-muted transition-opacity ${moreActionsOpen ? "opacity-100" : "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100"}`, + className: `ml-1 inline-flex items-center rounded border-0 bg-transparent p-0 align-text-bottom text-muted transition-opacity ${moreActionsOpen ? "opacity-100" : "opacity-0 group-hover:opacity-100 group-has-[:focus-visible]:opacity-100"}`, onClick: (event) => { event.stopPropagation(); onDetailsRequest(); diff --git a/extensions/github-security/client/index.html b/extensions/github-security/client/index.html index 154617128..9bddd8616 100644 --- a/extensions/github-security/client/index.html +++ b/extensions/github-security/client/index.html @@ -4,8 +4,8 @@