@idogee/permissio
v0.2.2
Published
GitHub Actions permission minimizer for least privilege GITHUB_TOKEN settings.
Downloads
0
Maintainers
Readme
Permissio
Least privilege for GitHub Actions tokens in one command.
Find overly broad GitHub Actions permissions and replace them with explicit least privilege settings.
Permissio scans .github/workflows and recommends the smallest likely GITHUB_TOKEN permissions for each job.
It helps replace implicit defaults, read-all, write-all, and broad workflow-level permissions with clear job-level permissions.

npx @idogee/permissio check .npx @idogee/permissio demoPermissio
Permission score 54 out of 100
Workflows scanned 3
Jobs scanned 8
Jobs with write-all 1
Jobs missing explicit permissions 5
Jobs with recommended changes 6
High findings 2
Top findings
write-all used at workflow level
pull_request_target has write permissions
id-token write is set but no OIDC use was detected
contents write appears broader than needed
job can use permissions: {}
Suggested snippet
jobs:
test:
permissions:
contents: readnpx @idogee/permissio demo --format html --output permissio-demo.htmlPreview the demo output:
- Terminal output: docs/assets/demo-output.txt
- Markdown report: docs/assets/demo-output.md
- HTML report: docs/assets/demo-report.html
What is Permissio
Permissio is a focused static analyzer for GitHub Actions GITHUB_TOKEN permissions.
It scans workflow YAML and recommends explicit job-level permissions blocks such as contents: read, pages: write, id-token: write, or permissions: {}.
Permissio is not a full GitHub Actions security scanner, and it does not prove that a workflow is safe.
Why this exists
Many GitHub Actions workflows still rely on implicit token defaults, read-all, write-all, or workflow-level write permissions when only one job needs them.
Those broad defaults make CI/CD permissions harder to review.
Permissio helps teams review and reduce the token permissions available to each job.
Quickstart
npx @idogee/permissio check .Common options:
permissio check --show-snippets
permissio check --format markdown
permissio check --format json
permissio check --format html --output permissio-report.html
permissio check --badge
permissio check --fail-on highDemo
The demo command scans a bundled risky example, so you can try Permissio before pointing it at a repo.
npx @idogee/permissio demo
npx @idogee/permissio demo --format markdown
npx @idogee/permissio demo --format json
npx @idogee/permissio demo --format html --output permissio-demo.html
npx @idogee/permissio demo --show-snippets
npx @idogee/permissio demo --badgeDemo assets:
Example output
Permissio
Permission score 54 out of 100
Workflows scanned 3
Jobs scanned 8
Jobs with write-all 1
Jobs missing explicit permissions 5
Jobs with recommended changes 6
High findings 2
Top findings
write-all used at workflow level
pull_request_target has write permissions
id-token write is set but no OIDC use was detected
contents write appears broader than needed
job can use permissions: {}
Suggested snippet
jobs:
test:
permissions:
contents: readWhat it detects
Permissio uses deterministic static rules for common GitHub Actions permission needs. See docs/rules.md for the full rule reference.
actions/checkout->contents: read- GitHub Pages deployment ->
pages: write,id-token: write - artifact attestations ->
attestations: write,artifact-metadata: write,id-token: write,contents: read - OIDC cloud authentication ->
id-token: write - GitHub Packages and
ghcr.iopublishing ->packages: write - release creation or asset upload ->
contents: write - issue and pull request writes ->
issues: writeorpull-requests: write - checks, statuses, deployments, security events, actions, discussions, models, and vulnerability alert reads
- risky
pull_request_targetpermission patterns - broad
write-all, broadread-all, implicit permissions, unknown scopes, and unknown third-party actions
How recommendations work
Permissio infers the smallest likely permission set from workflow structure, known actions, and recognizable command patterns. Recommendations are conservative and explainable: every inferred permission includes a reason and evidence.
When no GITHUB_TOKEN permission appears necessary, Permissio recommends:
permissions: {}Review every recommendation before applying it, especially for complex scripts or third-party actions.
GitHub Actions usage
name: Check GitHub Actions permissions
on:
pull_request:
push:
branches:
- main
permissions:
contents: read
jobs:
permissio:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: 24
- run: npx @idogee/permissio check . --ci --format markdown --output permissio-report.md --fail-on highHow Permissio is different
zizmor is a GitHub Actions security linter. StepSecurity Harden Runner focuses on runtime hardening and egress control. Permissio is a focused static analyzer for GITHUB_TOKEN permissions.
Use them together.
Install
The npm package is @idogee/permissio.
The CLI binary remains permissio.
For one-off runs without a local or global install:
npx @idogee/permissio check .
npx @idogee/permissio demoFor a local dev dependency:
npm install --save-dev @idogee/permissio
npx permissio check .For a global install:
npm install -g @idogee/permissio
permissio check .For local development:
git clone https://github.com/iDogRoag/permissio.git
cd permissio
npm install
npm run buildConfiguration
Permissio scans .github/workflows/*.{yml,yaml} by default.
Use --include to add extra workflow globs:
permissio check . --include "examples/**/*.yml"Exit codes:
0: scan completed and the selected fail policy did not trigger1: findings triggered--fail-on highor--fail-on changes2: internal error, invalid CLI input, or unreadable workflow file
If no workflows are found, Permissio exits 0 by default and suggests permissio demo.
Report formats
permissio check --format table
permissio check --format markdown
permissio check --format json
permissio check --format html --output permissio-report.htmlJSON output includes a stable top-level schemaVersion, summary, score, workflows, and findings.
Each finding includes id, category, severity, message, and location fields.
Permissio can print badge Markdown, but it does not host badges in v1.
permissio check --badgePermission score
The permission score is a heuristic from 0 to 100, not proof of safety.
It starts at 100 and subtracts points for broad or risky permission patterns.
Labels:
90to100: strong70to89: good50to69: risky0to49: critical
JSON output includes:
{
"score": {
"value": 54,
"label": "risky",
"penalties": []
}
}With --badge, JSON also includes:
{
"badge": {
"markdown": "",
"label": "permissio 54/100",
"color": "orange"
}
}Security model
Permissio is offline and read-only. It does not call the GitHub API by default, require credentials, execute workflows, run shell scripts, or modify files.
Limitations
Because Permissio uses static analysis, it may miss behavior hidden inside complex shell scripts, remote reusable workflows, organization settings, or third-party actions it does not recognize. It intentionally does not try to model repository or organization default token settings.
Roadmap
- Autofix mode
- PR comment mode
- SARIF output
- GitHub App
- Organization-wide scan
- Integration with gha-bom
- Integration with zizmor output
- More third-party action permission rules
- Reusable workflow permission analysis
- VS Code extension
- Hosted badge service
Contributing
Issues and pull requests are welcome. New rules should be deterministic, explainable, and covered by fixtures.
Good first contributions
- Add a new permission inference rule
- Improve
pull_request_targetdetection - Add fixtures for real world workflows
- Improve Markdown report formatting
- Add detection for another release action
- Add tests for unusual YAML forms
License
MIT
