Questa pagina è disponibile solo in inglese.
GitHub Action
Scan a branch from a GitHub workflow with a service account, fail the job on findings at or above a severity or on actively exploited findings, and read the results in the job summary.
The Vulnara GitHub Action starts a Vulnara scan on the branch your workflow runs on, waits for it to finish, and fails the job when it finds something at or above the severity you choose. It signs in with a service account, so no person's credentials are stored in GitHub.
What it is for
- Checking every push and pull request before it merges, without anyone opening the web app.
- Blocking a merge when a scan finds a Critical or High finding.
- Keeping a link from each CI run to the full scan in Vulnara.
How it works
- The action exchanges your service account name and token for a short-lived access token. It renews the token by itself during a long scan.
- It looks up the repository in your workspace by its GitHub
owner/name. The repository must already be in Vulnara. - It checks every entry in
scan-toolsagainst the scanners your workspace can run, and stops if one is not a valid id. - It starts one scan per scanner on the branch, then checks each scan's status every
poll-intervalseconds until it finishes. - It counts the findings per severity, writes a job summary, sets its outputs, and passes or fails the job.
The scan itself runs in Vulnara, not on your runner. The action runs on Linux runners only.
What you can set
These are the inputs you will use most. The full list, with defaults, and an interactive workflow builder are on the GitHub Action reference.
- service-account (required): the service account name, as shown in the Service Accounts list.
- token (required): the service account token. Pass it from a GitHub secret.
- tenant (required): the id of the workspace the service account and the repository belong to.
- scan-tools: what to run on the repository, as a comma-separated list of scan tool ids. Required unless the run only scans a web application.
- web-target-id: also scan this web application. See Scan a web application.
- web-url: also scan this web application by its address, reusing the web application with that address or adding it as a new one. Use either
web-target-idorweb-url, not both. - web-ownership-consent: must be exactly
truewithweb-url. It is your confirmation that you own the application or may scan it; the action never gives it for you. - fail-on: the lowest severity that fails the job:
none,low,medium,highorcritical. The default iscritical. - fail-on-exploited: also fail the job on actively exploited findings:
none,kevorlikely. The default isnone. See The exploited gate. - epss-threshold: the EPSS probability, from 0 to 1, at or above which
fail-on-exploited: likelyfails the job. The default is0.1. - branch: the branch to scan. By default, the branch that triggered the workflow.
- repository: the
owner/nameto look up in Vulnara. By default, the repository the workflow runs in. For an Azure DevOps repository, useorganization/project/name,project/nameororganization/name. - git-token-id: the id of a Vulnara git token that can clone the repository. Needed for private repositories.
- create-issue: open an issue in the repository for the findings. Off by default.
- auto-remediate: open a pull request that fixes the findings. Meant to be used with
create-issue. Off by default. - wait-timeout: how many seconds to wait for each scan before failing. The default is 1800.
- poll-interval: how many seconds between status checks. The default is 15.
create-issue and auto-remediate are on only when the value is exactly true, in lower case. Anything else, including TRUE, True, yes or 1, turns them off without a warning.
Outputs
- scan-result-ids: the ids of the scans that were started, separated by spaces.
- highest-severity: the highest severity found, in lower case, or
none. It covers the web application scan too. - web-target-id and web-scan-result-id: the web application and its scan, when a web application was scanned.
- passed:
trueif the job passed both thefail-onand thefail-on-exploitedgates,falseif it did not. - exploited-count: how many actively exploited findings the
fail-on-exploitedgate counted. It is 0 when the gate is off. - kev-count: how many of those are in the CISA Known Exploited Vulnerabilities catalogue.
The outputs are written before the job fails, so a later step with if: always() can still read them.
Do it
Add the repository to Vulnara
Connect the git workspace and make sure the repository is imported and enabled. See Connect a git provider and Repositories. The action finds the repository by name and matches the owner, so the git workspace name in Vulnara should match the GitHub owner.
Create a service account
In the workspace that owns the repository, go to Access & Security, then Service Accounts, and create one. Copy the token when it is shown: you will not see it again. See Service accounts.
Store the credentials in GitHub
In your repository settings, add the token as an Actions secret, for example
VULNARA_TOKEN. The service account name is not secret, so you can store it as a variable, for exampleVULNARA_SERVICE_ACCOUNT.Find your scanner ids
List the ids your workspace can run with the Vulnara CLI,
vulnara docker_scan_tools, or with the GraphQL querydockerScanTools { items { id categories } }(dockerScanTools); the MCP tool docker_scan_tools returns the same list. Each entry is an id and the categories it serves, never a name: the ids are opaque identifiers. See Scan categories.Add the workflow
Save this as
.github/workflows/vulnara.ymland fill in your workspace id and scanner ids.yamlname: Vulnara Scan on: push: branches: [main] pull_request: jobs: vulnara: runs-on: ubuntu-latest timeout-minutes: 45 steps: - uses: theorigamicorporation/vulnara-action@v1 id: vulnara with: service-account: ${{ vars.VULNARA_SERVICE_ACCOUNT }} token: ${{ secrets.VULNARA_TOKEN }} tenant: my-workspace scan-tools: '<scanner id>,<scanner id>' fail-on: high # git-token-id: ${{ vars.VULNARA_GIT_TOKEN_ID }} # for private repositories
The fail-on gate
The job fails when the highest severity found is at or above fail-on.
fail-on: highfails on High and Critical findings, and passes on Medium and Low.fail-on: criticalfails only on Critical findings.fail-on: nonenever fails the job on findings. Use it to report without blocking.
The value is not case sensitive. Any other value stops the run before it scans, with an error naming the accepted values.
The exploited gate
Severity says how bad a finding could be. fail-on-exploited also fails the job when a finding in this run is being exploited in the wild, whatever its severity:
kevfails on a finding whose CVE is in the CISA Known Exploited Vulnerabilities catalogue (KEV).likelyfails on those, and also on a finding whose CVE has an EPSS score at or aboveepss-threshold.none, the default, turns the gate off.
- uses: theorigamicorporation/vulnara-action@v1
with:
service-account: ${{ vars.VULNARA_SERVICE_ACCOUNT }}
token: ${{ secrets.VULNARA_TOKEN }}
tenant: my-workspace
scan-tools: '<scanner id>'
fail-on: critical
fail-on-exploited: likely
epss-threshold: '0.3'- Only findings of this run's repository and web application count. They come from the same data as the Actively exploited tab of the risk register.
- A finding with a recorded triage decision is skipped. Record a decision in Vulnara to let a known, handled finding through.
- The job summary gets an Actively exploited section listing each CVE with its KEV details and EPSS score.
- If Vulnara has never synced the KEV and EPSS feeds, the gate fails the job rather than passing it unchecked.
- Any other value of
fail-on-exploited, or anepss-thresholdthat is not a number from 0 to 1, stops the run before it scans, with an error naming the input.
The job summary
After the scans, the action writes a summary to the workflow run:
- a Passed or Failed heading;
- the repository, provider, visibility, branch, languages, gate setting, highest severity and total time;
- the number of findings per severity;
- one row per scan, with the category it ran, its duration, its finding count and a link to the scan in Vulnara;
- a table of up to 50 findings, highest severity first, each linking to the exact line of code at the commit that was scanned.
The summary and the log label each scan by the categories its scanner covers, for example Dependencies, Secrets. They never print a scanner's name, because a workflow log is world-readable on a public repository. A scan of the web application category is labelled Web application. A scan whose categories cannot be read is labelled Uncategorised; that is a display label, not a category.
Finding locations link in the shape of the repository's own provider: GitHub, GitLab, Bitbucket, Azure DevOps or Forgejo.
Scan a web application
The action can also scan a running web application, for example a preview environment right after it is deployed. Its findings count towards the same fail-on gate, and the job summary gets a Web application section with the target, its address, the findings by severity and the most severe ones.
- uses: theorigamicorporation/vulnara-action@v1
with:
service-account: ${{ vars.VULNARA_SERVICE_ACCOUNT }}
token: ${{ secrets.VULNARA_TOKEN }}
tenant: ${{ vars.VULNARA_TENANT }}
web-url: https://preview.example.com
web-ownership-consent: true
fail-on: high- Leave out
scan-toolsto scan only the web application, or set it to scan the repository as well. Both kinds of scan then run side by side. - With
web-target-id, the target already carries your ownership confirmation and its sign-in, soweb-ownership-consentis not needed. - Web application scanning must be enabled for your workspace. If it is not, the run fails and says so before anything is scanned. See Scan a web application.
- An address with a username or password in it is refused. Give the target a sign-in in the web app instead.
Private repositories
Vulnara needs a git token to clone a private repository. Add one in Vulnara (see Connect a git provider) and pass its id as git-token-id. Without it, the action warns that cloning may fail and starts the scan anyway. The scan then fails, and so does the job.
Issues and fix pull requests
Set create-issue: true to have Vulnara open an issue in the repository for the findings. Add auto-remediate: true to also have it open a pull request that fixes them. See AI remediation. Set both.
Good to know
scan-toolstakes ids, and only ids: an entry that is not an id is refused, with a message pointing you tovulnara docker_scan_toolsand thedockerScanToolsquery, which list the ids. The web app has no screen that shows them. A scanner name or a category label is not accepted. An id your workspace cannot run is refused too.- A refused
scan-toolsentry fails the job: the action stops before it starts any scan, so a typo is loud rather than a green job that scanned nothing. Earlier versions of this page advised a defensiveFail if no scan ranstep for that case. It is no longer needed. - Permissions: starting a scan needs the editor role in the workspace. A service account has the viewer role, which is read-only. If a scan is refused with an authorization error, the account is missing that role. See Teams and roles.
- The repository must exist: if Vulnara has no repository with that name in the workspace, the action fails and tells you to add it first. A disabled repository gets a warning, and the scan is usually refused.
- Same name under two owners: the action prefers the repository whose owner matches. If none matches, it uses the first repository with that name, which may be the wrong one. The job log and summary show which repository was scanned.
- Same name in two Azure DevOps projects:
organization/namematching more than one project fails the job and lists the candidates. Name the project as well. - Timeouts add up:
wait-timeoutapplies to each scan, not to the whole run. With several scanners, set a limit for the whole job withtimeout-minutes. - A timed-out scan keeps running: when the action gives up waiting, the scan continues in Vulnara. Open it from the link in the log.
- Failed scans fail the job: a scan that ends as failed or cancelled fails the job, whatever
fail-onsays. - Findings with no file: they count towards the totals and the gate, but are left out of the table of located findings.
- Plan limits apply: CI scans use your plan's scan minutes like any other scan. See Plans, usage and billing.
- Your token stays private: the service account token is never shown in the job summary, the step outputs or the log.
- Wrong credentials: the action prints the reason from the sign-in response and fails with "could not authenticate the service account". Check the service account name, the token, and that
tenantis the workspace the account belongs to.