Frequently Asked Questions¶
Why does my scan show no findings?¶
A scan returning Overall Risk: ℹ️ INFO with no detector hits is
usually correct — your repo probably doesn't use any of the patterns
ActionScope looks for. Specifically:
- No
aws-actions/configure-aws-credentialsstep in any workflow (so there's no AWS surface to analyse) - No
uses:reference matches the compromised-actions database - No
${{ github.event.* }}interpolation inrun:blocks - No
pull_request_targetjobs with write-capable token permissions - No
workflow_runjobs downloading and executing artifacts - All external action references are pinned to full 40-char SHAs
If you expected a finding and didn't get one, sanity-check with:
actionscope scan . --output-format json | python3 -m json.tool | head -40
If workflow_count is 0, ActionScope didn't see any workflow file. Make
sure you're running from the repo root and the workflows live in
.github/workflows/. ActionScope only scans that path by default.
If you think you've found a true false-negative — a known issue ActionScope should have caught but didn't — please open an issue. False negatives are the most important class of bug for a security tool.
What does policy_source: not_found mean?¶
It means ActionScope detected an aws-actions/configure-aws-credentials
step that assumes an IAM role, but couldn't find the IAM policy attached
to that role anywhere in the repository.
This isn't a bug — it just means the policy isn't co-located with the workflow. Common reasons:
- IAM is managed in a separate "infrastructure" repository (Terraform monorepo, terragrunt, AWS CDK, CloudFormation in a different repo, …)
- IAM is created out-of-band (ClickOps, AWS Console, scripts you ran once and don't keep in version control)
- The role is in a different AWS account and you don't have the policy source
Three ways to get a populated blast radius despite this:
| Approach | Command |
|---|---|
| Scan the infra repo separately | actionscope scan /path/to/infra-repo |
| Use live AWS verification | actionscope scan . --aws-verify |
| Add a JSON policy snapshot to your repo | Drop the policy JSON in iam/ or policies/ |
ActionScope looks for IAM policies in these paths:
*.tf(Terraform files withaws_iam_role,aws_iam_role_policy,aws_iam_policyresources)**/iam/*.json(raw IAM policy JSON)**/policies/*.json(same)
How do I get the most from --aws-verify?¶
--aws-verify switches the tool from "what does the repo say about the
role" to "what does AWS actually say about the role." It makes read-only
IAM API calls to fetch:
- The role's trust policy (who can assume it)
- The list of attached managed policies
- Each attached managed policy's current version document
- The list of inline policies on the role
- Each inline policy's document
Use it when:
- The repo doesn't have the IAM source (see above)
- You want to verify that the live AWS state matches what your IaC says
- You're auditing a role created out-of-band
Required IAM permissions are minimal and read-only:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:GetRole",
"iam:ListAttachedRolePolicies",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:ListRolePolicies",
"iam:GetRolePolicy"
],
"Resource": "*"
}
]
}
ActionScope uses standard AWS credential resolution (env vars, profiles, IAM Instance Profile, IMDS, SSO). The most common setup:
export AWS_PROFILE=my-audit-profile
actionscope scan . --aws-verify
Full reference at AWS Verification Permissions.
Is ActionScope safe to run? Does it make network calls?¶
Static analysis (the default) makes zero network calls. ActionScope reads files from your local filesystem, parses YAML and HCL/JSON, correlates them in memory, and writes output. No telemetry, no remote service, no analytics — none of it. You can run it on an air-gapped machine.
There are exactly three flags that change this:
| Flag | What it does | Network calls |
|---|---|---|
--aws-verify |
Fetches live IAM policies from AWS | Only AWS IAM API, read-only |
--resolve-pins |
Looks up current SHA for unpinned action refs | Only GitHub API (uses GITHUB_TOKEN env var if set, otherwise unauthenticated) |
(GitHub Action) comment-pr: true |
Posts a comment on the PR | Only GitHub API for the comment |
If you're scanning a sensitive repo and want to be extra cautious, run without any of those flags. The default mode never leaves your machine.
ActionScope is open-source under MIT. The full source for what runs on your machine is in github.com/r12habh/ActionScope — audit it before running if your environment requires that.
How often is the compromised actions database updated?¶
The database lives in
actionscope/data/compromised_actions.json
and ships with each ActionScope release. When a new GitHub Actions
supply-chain compromise becomes public, the typical update cadence is
within 24-48 hours of the advisory being published, via a patch
release (e.g. 0.3.1).
To stay current:
pip install --upgrade actionscope
The CHANGELOG entry for each release lists added compromise entries.
You can also see the current full list at Compromised Actions Database, which is auto-generated from the bundled JSON on every docs deploy — so the site always reflects the latest released version.
A future actionscope update-db subcommand
(issue #25) will
fetch updates between releases from a curated upstream feed, with a
local cache and --offline fallback.
Found a compromise that isn't in the database? Please open a Report Compromised Action issue. We aim to land it within a few hours.
How is ActionScope different from actionlint, zizmor, Checkov?¶
| Question | actionlint | zizmor | Scorecard | Checkov | ActionScope |
|---|---|---|---|---|---|
| Workflow YAML validation | ✅ | partial | ❌ | ❌ | partial |
| Security pattern detection | ❌ | ✅ | ✅ | ❌ | ✅ |
GITHUB_TOKEN permission review |
❌ | ✅ | ✅ | ❌ | ✅ |
| Unpinned action detection | ❌ | ✅ | ✅ | ❌ | ✅ |
| Known-compromised action database | ❌ | ❌ | ❌ | ❌ | ✅ |
| AWS credential source detection | ❌ | ❌ | ❌ | ❌ | ✅ |
| Workflow → IAM role correlation | ❌ | ❌ | ❌ | ❌ | ✅ |
| Live AWS IAM policy verification | ❌ | ❌ | ❌ | ❌ | ✅ |
| Plain-English blast radius | ❌ | ❌ | ❌ | ❌ | ✅ |
| OIDC trust policy analysis | ❌ | ❌ | ❌ | partial | ✅ |
| GitHub Environment hardening | ❌ | ❌ | ❌ | ❌ | ✅ |
| Static IAM policy analysis | ❌ | ❌ | ❌ | ✅ | ✅ |
| SARIF / Code Scanning output | ❌ | ✅ | ✅ | ✅ | ✅ |
The short version: actionlint validates YAML, zizmor and Scorecard find risky workflow patterns, Checkov audits IAM in isolation. ActionScope crosses the boundary — it ties a specific workflow to a specific IAM role to a specific blast radius and emits one correlated report.
They're complementary; run multiple if you can.
Can I scan private repos?¶
Yes. Everything except --resolve-pins and comment-pr (the
GitHub-Action-only flag) runs entirely against the local filesystem and
doesn't care whether the repo is public or private. If you use
--resolve-pins, set GITHUB_TOKEN to a token with public_repo
scope (private repo metadata isn't needed for resolving public actions).
How long does a scan take?¶
Sub-second on a typical repo. The largest factor is the number of .tf
files (Terraform HCL parsing is the dominant cost). ActionScope is
designed to feel free — it's intentionally cheap enough to put in
pre-commit hooks if you want to.
How do I report a bug or a false positive?¶
Open an issue. There are dedicated templates for:
- False positives — finding raised but the workflow is actually safe
- False negatives — known issue ActionScope should have caught
- New compromised actions to add to the database
- New IAM privilege-escalation paths to detect
False positives erode trust; false negatives miss real attacks. Both are the most important class of bug for a security tool — your reports make ActionScope better.