aem-eds-kit / Secure GitHub sandboxes
Security guideSecure GitHub sandboxes
eds sandbox creates throwaway EDS repos on GitHub and tears them down in seconds. This guide shows how to authorize GitHub with least privilege, so the token you give the CLI can only ever see the repo you are building - and nothing else in your account.
The goal: only this repo, never the others
The safest setup is one where the GitHub credential the CLI holds can touch only your sandbox repos. GitHub's fine-grained personal access tokens make that possible - but there is one rule that shapes everything below:
You cannot scope a token to a repo that does not exist yet. Creating a repository is an account- or organization-level action. So "limit to one repo" and "create new repos" need slightly different setups.
Two setups, depending on what you need
| You want to… | Setup | What the token can see |
|---|---|---|
| Manage one existing sandbox | Fine-grained token → Only select repositories → pick that one repo | Exactly that repo. Nothing else. |
| Create new sandboxes | Fine-grained token → Resource owner: a dedicated sandbox org → All repositories (in that org) | Only repos in that org. Your personal account and other orgs stay invisible. |
Setup A - lock a token to a single repo
Best for working on one sandbox that already exists (list, rm, pushing code):
- Open github.com/settings/personal-access-tokens/new.
- Repository access → Only select repositories → choose the one sandbox repo.
- Permissions → set the minimum below.
- Set a short expiry (e.g. 7 or 30 days).
- Generate, copy, then run
eds sandbox loginand paste it.
This token literally cannot read or write any other repository - GitHub enforces it server-side.
Setup B - a dedicated sandbox org for new repos
Best when you want to keep spinning up fresh sandboxes without ever exposing your real repos. Because creation is an account-level action, you isolate it by giving the token its own container:
- Create a free GitHub organization, e.g.
my-sandboxes(Settings → Organizations → New). - Open github.com/settings/personal-access-tokens/new.
- Resource owner → select
my-sandboxes(not your personal account). - Repository access → All repositories (this means all repos in that org only).
- Permissions → set the minimum below.
- Set a short expiry, generate, and
eds sandbox login. - Always pass the org:
eds sandbox new my-test --org my-sandboxes.
With this token, your personal account and every other organization are completely invisible - it can only create, read, and delete repos inside my-sandboxes. This is the cleanest way to satisfy "nothing else, ever".
Minimum permissions
Grant only these three repository permissions - nothing more:
| Permission | Level | Why |
|---|---|---|
| Administration | Read and write | Create a repo from a boilerplate, set its topic, and delete it |
| Contents | Read and write | Clone and push code to the sandbox |
| Metadata | Read | Mandatory baseline GitHub requires for any fine-grained token |
Fine-grained token vs. OAuth Device Flow
eds sandbox login supports two paths:
- Fine-grained PAT (recommended for least privilege): the only way to scope access to specific repos or a single org. Use this when "only this repo" matters.
- OAuth Device Flow: you authorize in the browser on github.com - the CLI never sees your password - but OAuth apps use classic scopes (
repo,delete_repo), which are account-wide. Convenient, but broader than a fine-grained token.
For the tightest blast radius, prefer the fine-grained token.
What the CLI itself touches
Independent of the token's scope, aem-eds-kit is deliberately narrow in what it ever does on GitHub:
sandbox listsearches only for repos tagged with theeds-sandboxtopic under your login - it never enumerates your other repositories.sandbox rmdeletes only the named repo, and always confirms first (default: No).sandbox newcreates the single repo you asked for and tags iteds-sandbox.
Where the token is stored
After login, the token is written to ~/.eds/github.json with owner-only permissions (mode 0600, directory 0700) - the same convention gh and npm use. It never enters your project or git history. Remove it any time:
$ eds sandbox logout # deletes the stored token
You can also revoke the token itself on GitHub → Settings → Developer settings → Personal access tokens (or Authorized OAuth Apps for the device flow).
Quick start
$ eds sandbox login # paste a fine-grained token $ eds sandbox new my-test --org my-sandboxes # isolated in the org $ eds sandbox list # only eds-sandbox repos $ eds sandbox rm my-test # confirmed teardown
FAQ
Can I give the token access to only one GitHub repository?
Yes. Create a fine-grained personal access token with Repository access → Only select repositories and choose that single repo. The token cannot read or write any other repository - GitHub enforces this on the server. This works for an existing repo; to create a new one, use a dedicated sandbox org instead.
Why can't a token be scoped to a repo I'm about to create?
Creating a repository is an account- or organization-level action, and you cannot select a repository that does not exist yet. The clean workaround is a dedicated sandbox organization: scope the token to that org, and it can only ever touch repos inside it.
Is the OAuth Device Flow safe?
Yes. You authorize in the browser on github.com, so the CLI never sees your password, and it only ever talks to github.com. The trade-off is scope: OAuth apps use account-wide classic scopes, so for the narrowest access, a fine-grained token scoped to specific repos or one org is tighter.
What permissions does the token actually need?
Only three, all repository-level: Administration (Read and write) to create/tag/delete the repo, Contents (Read and write) to clone and push, and Metadata (Read), which GitHub requires on every fine-grained token.
Where is my token stored and how do I remove it?
In ~/.eds/github.json with owner-only permissions (mode 0600). Run eds sandbox logout to delete it, and revoke it on GitHub under Settings → Developer settings for good measure.
Is deleting a sandbox reversible?
No. eds sandbox rm permanently deletes the repository, so it always asks for confirmation first (defaulting to No). Keep sandboxes public and disposable, and tear them down when you are done.
eds sandbox reference → Document Authoring vs Universal Editor →