-
Notifications
You must be signed in to change notification settings - Fork 148
Description
[SECURITY] VS Code GitHub Actions extension exposes organization variables to non-admin users
Summary
The GitHub Actions extension for VS Code exposes organization-level Actions variable values (names + values) to non-admin users via the “Settings → Variables → Organization Variables” view.
This is a privilege escalation:
- GitHub Web UI correctly blocks non-admins from viewing org variables
gh api repos/{owner}/{repo}/actions/organization-variablescorrectly fails for non-admins- Direct REST calls with a non-admin token also fail
- But the VS Code extension shows the full values to the same non-admin users
Impact
Severity: Critical – privilege escalation & credential disclosure
For any repo where org variables are shared:
- Non-admin users with only read access to the repo can see:
- All shared org variable names
- Their plain-text values in the VS Code sidebar
- In our case this exposed (now rotated and moved to Secrets):
GITLAB_API_TOKEN(full access to GitLab Package Registry)GITLAB_API_READ_TOKEN- Multiple third‑party service passwords
How to Reproduce
-
Setup
- In a GitHub organization:
- Create organization-level Actions variables with sensitive values
- Share them with a repository
- Add a non-admin user with read access to that repository
- In a GitHub organization:
-
As the non-admin user
-
Confirm that the org variables are not visible elsewhere:
-
Web: Org Settings → Actions → Variables → access denied
-
CLI:
gh api repos/{owner}/{repo}/actions/organization-variables # => “Must have admin rights to Repository”
-
-
In VS Code:
- Install
github.vscode-github-actions - Open the repo
- Open “GitHub Actions” view → “Settings” → “Variables” → “Organization Variables”
- Install
Observed: All organization variables and their values appear in plain text.
-
Suspected Source
From the public repo:
-
src/treeViews/settings/orgVariablesNode.ts:variables = await this.gitHubRepoContext.client.paginate( "GET /repos/{owner}/{repo}/actions/organization-variables", { owner: this.gitHubRepoContext.owner, repo: this.gitHubRepoContext.name, per_page: 100 } ); return variables.map(v => new VariableNode(this.gitHubRepoContext, v, undefined, true));
-
src/treeViews/settings/variableNode.ts:export class VariableNode extends vscode.TreeItem { constructor(/* ... */, public readonly variable: OrgVariable, /* ... */) { super(variable.name); this.description = variable.value; // shown directly in tree view } }
So the extension:
- Calls the org variables API for the current repo
- Wraps each result in a
VariableNode - Sets
description = variable.value, which is rendered in the tree view
The critical question: why does this succeed for non-admin users when the same endpoint fails via gh api and curl?
Expected Behavior
- For non-admins:
- Either:
- Do not show “Organization Variables” at all, or
- Show only names, with values masked / hidden
- Either:
- Enforce the same permission checks as:
- GitHub Web UI
- GitHub CLI
- Direct REST calls
Mitigations (for other users)
Until fixed, organizations should:
- Rotate any secrets stored in organization variables that may have been exposed
- Move sensitive values to GitHub Secrets
- Avoid using this extension, or at least hide “Settings → Variables” from non-admins
Request
Can the team:
- Confirm the behavior with a non-admin test account?
- Clarify which endpoint + auth flow the extension uses here?
- Align the extension’s behavior with GitHub’s documented and enforced permission model for org variables?
Metadata
Metadata
Assignees
Labels
Type
Projects
Status