Skip to content

feat: Add GitHub Copilot CLI as a supported tool profile #90 - #128

Draft
fipro78 wants to merge 2 commits into
eclipse-enclave:mainfrom
fipro78:main
Draft

fipro78 wants to merge 2 commits into
eclipse-enclave:mainfrom
fipro78:main

Conversation

@fipro78

@fipro78 fipro78 commented Sep 30, 2026

Copy link
Copy Markdown

What it does

This PR adds GitHub Copilot CLI as supported tool profile.

Note that this PR is work in progress. I actually need some support in finishing the contribution. I would like to add the folder trust configuration and need some additional testing from others. The setup worked for me two days ago but suddenly the authentication does not work anymore. My token is correct and freshly created, so not sure if the newest CLI version had some changes or the company guidelines changed.

How to test

Follow-ups

Breaking changes

  • This PR introduces breaking changes and has been coordinated with maintainers.

Review checklist

@fipro78
fipro78 marked this pull request as draft September 30, 2026 14:49
@fipro78

fipro78 commented Sep 30, 2026

Copy link
Copy Markdown
Author

@xai I created this draft PR to share what I have done so far. Since yesterday the authentication somehow fails, but I can't figure out why. Maybe you have some hints where to look at. But I think it is better if you can see what I have done so you can give me some suggestions to improve it.

@xai

xai commented Sep 30, 2026

Copy link
Copy Markdown
Collaborator

Thanks a lot @fipro78! I'll take a look!

@xai

xai commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

I just tested this branch (on linux). For me it works when using device code authentication!

After starting the tool the first time, I ran /login and used device code authentication. The oauth credentials work and they also persist across starts in different projects. On the host they get written to $HOME/.local/state/enclave/tools/copilot/auth/default/config.json, as it should be.

Next, I tested the browser oauth flow and it seems that copilot picks a random port for the callback (as opposed to e.g. codex' 1455), which is not great news for us. Unfortunately, copilot is closed source, so it will take some poking around to see whether we can make it use a fixed port. I'll look into this.

@xai

xai commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

@EclipseSourceAI

@xai

xai commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

Regarding the browser oauth flow: I found no (documented or undocumented) way to make it use a fixed port, so we can't do the oauthPorts: [{ port: ... }] thingy here.

I was still able to authenticate by following the flow until i get the "Firefox can’t connect to the server at 127.0.0.1:" problem in my browser, copied the full url from its location bar and then just ran enclave --tool copilot exec curl '<full-url>' and it completed. Sucks from a UX perspective, but works.

One annoying thing is that copilot still asks whether to trust a directory on each start, but I'm sure there's a way around that.

@xai

xai commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

So regarding your authentication problem: Have you tried deleting the credentials from ~/.local/state/enclave/tools/copilot/ and doing the login again?

If that fixes it, I wonder wether parallel sessions, especially long running ones could be the problem. We had a lot of trouble with this for Claude in the past.

@EclipseSourceAI EclipseSourceAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Autonomous AI review.

This review was done by an AI agent and therefore may contain mistakes. Feel free to ignore any comment you disagree with. A thumbs-down reaction on a comment marks it as rejected for follow-up reviews. Noting why in a reply helps, since replies are read too.

Resolving all AI comments does not lead to an automatic approval. A maintainer still needs to review and sign off on the overall architecture and design.

To get an updated review after pushing changes, a maintainer may re-request a review from this account.

Running in Eclipse Enclave, submitted via review-guard-mcp

Adds a copilot tool extension (draft, WIP). It installs @github/copilot through the shared npm helper and declares COPILOT_GITHUB_TOKEN as a gateway-injected credential for api.github.com and *.githubcopilot.com. It treats ~/.copilot/config.json as the shared auth file and adds a settings template, an allowlist and an enclave-help skill. Everything is spec-only except a no-op Go handler.

Main points for maintainers:

  • Auth failures: Copilot CLI falls back to GH_TOKEN/GITHUB_TOKEN. With the default github-cli feature, those env vars hold a placeholder that is never released to *.githubcopilot.com. That would also explain why device-code OAuth worked in the maintainer test. See the inline comment on credentials.
  • Auth file scope: config.json likely holds more than auth. Because it is the shared auth file, any state Copilot writes there is shared across projects, and the file_exists session check will pass after the first start even without a login. The planned folder-trust support depends on getting this right. Codex handles trust in its entrypoint.d/setup.sh behind ENCLAVE_YOLO.
  • Failing test: go test ./internal/config/ fails because the golden snapshots for copilot are missing. The README and the docs/tools.md entry are also missing.
  • Default image: maintainers should decide whether this ships in the default set or stays defaultIncluded: false like mistral-vibe until auth and the random OAuth callback port are settled.

enclave validate-extensions and make check-license-headers pass.


credentials:
sources:
copilot-github-token: { env: [COPILOT_GITHUB_TOKEN] }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot CLI falls back to GH_TOKEN/GITHUB_TOKEN when COPILOT_GITHUB_TOKEN is unset. With the default-enabled github-cli feature those vars hold a placeholder the gateway only swaps on github.com hosts (spec), so requests to *.githubcopilot.com go out with the raw ENCLAVE_SECRET_... value and the stored OAuth login is ignored. That would explain the auth failures from the description, try with GH_TOKEN/GITHUB_TOKEN unset in the container.

Comment thread extensions/tools/copilot/spec.yaml Outdated
Comment on lines +45 to +47
"*.individual.githubcopilot.com": copilot-github-token
"*.business.githubcopilot.com": copilot-github-token
"*.enterprise.githubcopilot.com": copilot-github-token

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant, *.githubcopilot.com already matches subdomains at any depth (MatchNormalizedHost).

providers:
- name: github
credentials: [copilot-github-token]
authFiles: [config.json]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is config.json auth only? If Copilot also keeps state there (trusted folders, model, first-launch flags), file_exists passes after the first start without any login, and all of that gets shared across projects via the auth store. A json_pointer check on the token key would be accurate, and this also matters for the folder trust you want to add.

Comment on lines +25 to +35
passthroughPaths: [
agents/,
copilot-instructions.md,
extensions/,
hooks/,
instructions/,
lsp-config.json,
mcp-config.json,
providers.json,
settings.json,
skills/]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: trailing whitespace on each of these lines, and most new files lack a final newline. A block list like pi/opencode use reads better here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing from the tool checklist: extensions/tools/copilot/README.md (required per AGENTS.md), a row in docs/tools.md, and the golden snapshots. go test ./internal/config/ currently fails with read golden tool-copilot ... no such file or directory, regenerate with -update-golden.

address=/#/

# Copilot
server=/githubcopilot.com/8.8.8.8

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant, the github.conf fragment included below already has githubcopilot.com (fragment).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only embeds BaseHandler, which tools.Resolve already returns for unregistered tools (registry). Drop go/ like mistral-vibe and pi. As is, cmd/enclave/tool_imports.go wasn't regenerated, so the package isn't linked anyway.

@@ -0,0 +1,9 @@
{
// Keep sessions local; this also disables remote control.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No other JSON template has comments, and JSON patches are merged with strict json.Unmarshal on the copied template (readJSONValue). Any patches/copilot/settings.json will fail with invalid character '/', so drop the comment (move it to the README).

---
name: enclave-help
description: Answer questions about Enclave by reading the bundled documentation
allowed-tools: Read, Glob, Grep

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are Claude's tool names. The codex/opencode/pi copies drop this line (codex), do the same here.

Comment thread extensions/tools/copilot/install.sh Outdated
Comment on lines +11 to +12
enclave-install-npm-tool @github/copilot copilot Copilot
copilot --version No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The helper already fails when the binary isn't on PATH (helper), so copilot --version is redundant. Also check if @github/copilot needs its lifecycle scripts, otherwise pass --ignore-scripts like codex and pi (guide).

@fipro78

fipro78 commented Oct 1, 2026

Copy link
Copy Markdown
Author

So regarding your authentication problem: Have you tried deleting the credentials from ~/.local/state/enclave/tools/copilot/ and doing the login again?

If that fixes it, I wonder wether parallel sessions, especially long running ones could be the problem. We had a lot of trouble with this for Claude in the past.

I will try tomorrow. But I used the approach with the environment variable and not oauth. Tested today a BYOK setup which worked fine.

@xai

xai commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

So regarding your authentication problem: Have you tried deleting the credentials from ~/.local/state/enclave/tools/copilot/ and doing the login again?
If that fixes it, I wonder wether parallel sessions, especially long running ones could be the problem. We had a lot of trouble with this for Claude in the past.

I will try tomorrow. But I used the approach with the environment variable and not oauth. Tested today a BYOK setup which worked fine.

Using the env (with a restrictively scoped token) is probably the safer way. I wonder what the scope of the oauth token really is. I am going to poke around with it a bit to see if it is actually safe for enclave users to authenticate via oauth flow in copilot or if that would mean that someone who snatches the auth token can do write stuff on github. Hopefully that poking around won't get me banned ;)

@xai

xai commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

So regarding your authentication problem: Have you tried deleting the credentials from ~/.local/state/enclave/tools/copilot/ and doing the login again?
If that fixes it, I wonder wether parallel sessions, especially long running ones could be the problem. We had a lot of trouble with this for Claude in the past.

I will try tomorrow. But I used the approach with the environment variable and not oauth. Tested today a BYOK setup which worked fine.

Using the env (with a restrictively scoped token) is probably the safer way. I wonder what the scope of the oauth token really is. I am going to poke around with it a bit to see if it is actually safe for enclave users to authenticate via oauth flow in copilot or if that would mean that someone who snatches the auth token can do write stuff on github. Hopefully that poking around won't get me banned ;)

Oh ffs!!! Don't use oauth flows with copilot. That token is quite powerful: Token scopes: 'codespace', 'gist', 'read:org', 'read:user', 'repo', 'write:plugin_gateway_connections'

Especially the repo scope (including read and write) is a real danger. I used copilots token to clone a private repo and do stuff with it.

We should document how users should use copilot in enclave, i.e., what it actually needs as a minimum scope to function and the recommend the env approach you are using. We should still allow the oauth login method of course, because if users want to do dangerous things they should be able to, but we should make them aware of it.

I am really a bit shocked right now that they would issue such a broad token for a simple /login and a tool that is supposed to do some llm queries.

Edit: github/copilot-cli#953. January. What in the world is wrong with people? In github/copilot-cli#953 (comment), they recommend using COPILOT_GITHUB_TOKEN with a fine-grained token, and so should we.

@fipro78

fipro78 commented Oct 2, 2026

Copy link
Copy Markdown
Author

@xai
I still don't get the COPILOT_GITHUB_TOKEN to work. With the setup in this draft, the provided token doesn't seem to work in the enclave container.

In the network logs I see several entries like this:

07:07:23  ✗  GET   api.individual.githubcopilot.com /models              403  secret-injection

To verify if there is an issue with the token itself I started the container and connected to the shell like this:

enclave --tool copilot shell

Then I checked if the COPILOT_GITHUB_TOKEN is set:

agent@e161878e6c43:/home/<user>/<project_folder>$ echo $COPILOT_GITHUB_TOKEN
ENCLAVE_SECRET_cf9b7e5b20bcc533596aeb389085357a46786066453e2b53

If I change this to the real token value and not the enclave secret one, I can call copilot in that session and it works.

The folder ~/.local/state/enclave/tools/copilot/auth/ doesn't actually contain anything despite the config.json. Probably because I want to login via environment variable and not OAuth. So clearing the directory didn't change anything.

I also checked the entries in ~/.local/state/enclave/projects/<project_id>/copilot/env/env, where I see the environment variables with the correct values, which I guess are used to resolve the ENCLAVE_SECRET_ entries.

Is it possible that the resolving of the enclave secret is not working correctly in the copilot tool as I have it configured at the moment?
Could it be some timing issue, something like copilot is started BEFORE the enclave secret is resolved?

@fipro78

fipro78 commented Oct 2, 2026

Copy link
Copy Markdown
Author

@xai
I have updated the PR to address the findings of the review agent and I think I have added the handling of the folder trust.

@xai

xai commented Oct 2, 2026

Copy link
Copy Markdown
Collaborator

Thanks a lot for the update!

I'll look into the secret release problem and get back to you.

@xai

xai commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

I can reproduce it.

  1. Enclave puts a placeholder in the container's environment: COPILOT_GITHUB_TOKEN=ENCLAVE_SECRET_<hex>. The fixed ENCLAVE_SECRET_ prefix comes from internal/auth/secret_injection.go:17.
  2. Copilot (i.e., the client tool) only accepts known GitHub token prefixes. It refuses classic ghp_ tokens outright and silently skips values with an unknown prefix like ENCLAVE_SECRET_.
  3. It then falls back to GH_TOKEN/GITHUB_TOKEN, which hold the github-cli feature's placeholder. That placeholder is only released to api.github.com, *.github.com and *.githubusercontent.com.
  4. So api.github.com works and Copilot logs in, but the first request to *.githubcopilot.com carries the gh placeholder. The gateway blocks it because a secret is going to a host it isn't released to. That's the 403 secret-injection in your log.

With only COPILOT_GITHUB_TOKEN=ENCLAVE_SECRET_... set and GH_TOKEN/GITHUB_TOKEN removed, copilot made no requests at all. The gateway log stayed empty, and Copilot printed its "To authenticate, you can use any of the following methods ..." message, as if no token were set.

This is a bit annoying of course. I guess we just have to hack our way around the check. I could imagine doing something like this (as an enclave core change):
We could allow a credential to declare a custom placeholder prefix in its spec, something like this: copilot-github-token: { env: [COPILOT_GITHUB_TOKEN], placeholderPrefix: github_pat_ }.

The placeholder would then be github_pat_ENCLAVE_SECRET_<hex>, copilot thinks it's a valid token and the gateway replaces the string as it does now. In a first test, copilot accepted a github_pat_ value with the placeholder appended, so I am pretty sure that currently they only check the prefix. It might break at any point though when they tighten their check, at which i would really just produce "fake" tokens that are not distinguishable from real one by the client ... would be another core change, but nothing that will stop us.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants