SignPath

Trusted Build Systems  ❯   GitHub

Prerequisites

GitHub Enterprise Server

SignPath hosts an instance of the GitHub connector which is linked to GitHub.com For integrating self-hosted GitHub Enterprise Server instances, contact our support team.

Checks performed by SignPath

The GitHub connector performs the following checks:

  • A build was actually performed by a GitHub workflow, not by some other entity in possession of the API token
  • Origin metadata is provided by GitHub, not the build script, and can therefore not be forged
  • The artifact is stored as a GitHub workflow artifact before it is submitted for signing
  • For OSS projects: All jobs of the GitHub worfklow leading up to the signing request were executed on GitHub-hosted agents

Usage

We provide a submit-signing-request action that can be integrated into a GitHub Actions workflow:

steps:
  # required for the artifact to be available on the GitHub server
- name: upload unsigned artifact
  id: upload-unsigned-artifact
  uses: actions/upload-artifact@v7
  with: 
    path: path/to/your/artifact
    
- name: submit signing request
  uses: signpath/github-action-submit-signing-request@v3
  with:
    api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
    organization-id: '<SignPath organization id>'
    project-slug: '<SignPath project slug>'
    signing-policy-slug: '<SignPath signing policy slug>'
    github-artifact-id: '${{ steps.upload-unsigned-artifact.outputs.artifact-id }}'
    wait-for-completion: true
    output-artifact-directory: '/path/to/signed/artifact/directory'
    parameters: |
      version: ${{ toJSON(some.userinput) }}
      myparam: "another param"

ZIP archives

By default, the upload-artifact action creates a ZIP archive, which requires the root element of your Artifact Configurations to be of type <zip-file>. If you want to specify your artifact type directly, specify archive: false in the upload-artifact action. See Usage.

Note that there is an open bug in GitHub’s upload-artifact action where the name parameter is ignored and the action fails if another artifact with the same filename has already been uploaded. See issues #769 and #785.

Workflow permissions

If all of the following conditions apply, the required permissions have to be enabled in the workflow definition:

  • the GitHub repository is private
  • the workflow permissions are set to the default “Read repository contents and packages permissions”
  • The SignPath GitHub App is not installed

You can use the following snippet:

  permissions:
     actions: read
     contents: read

Action input parameters

Parameter Default Value Description
connector-url https://githubactions.connectors.signpath.io The URL of the SignPath connector. Required if self-hosted.
api-token (mandatory) The Api Token for a user with submitter permissions in the specified project/signing policy.
organization-id (mandatory) The SignPath organization ID.
project-slug (mandatory) The SignPath project slug.
signing-policy-slug (mandatory) The SignPath signing policy slug.
artifact-configuration-slug default artifact configuration The SignPath artifact configuration slug.
github-artifact-id (mandatory) ID of the Github Actions artifact. Must be uploaded using the actions/upload-artifact v4+ action before it can be signed. Use ${{ steps.<step-id>.outputs.artifact-id }} from the preceding actions/upload-artifact action step.
wait-for-completion true Wait for the signing request to complete.
output-artifact-directory   Path to where the signed artifact will be extracted. If not specified, the task will not download the signed artifact from SignPath.
github-token secrets.GITHUB_TOKEN GitHub access token for reading job details and downloading the artifact. Requires the action:read and content:read permissions.
wait-for-completion-timeout-in-seconds 600 Maximum time in seconds that the action will wait for the signing request to complete.
service-unavailable-timeout-in-seconds 600 Total time in seconds that the action will wait for a single service call to succeed (across several retries).
download-signed-artifact-timeout-in-seconds 300 HTTP timeout when downloading the signed artifact.
parameters   Multiline-string of values that map to user-defined parameters in the Artifact Configuration. Use one line per parameter with the format <name>: "<value>" where <value> needs to be a valid JSON string.
skip-decompress false Set to true if the archive parameter in the upload-artifact action is set to false (i.e. the artifact is not stored as a ZIP archive)

Action output parameters

The action supports the following output parameters:

  • signing-request-id: ID of the newly created signing request
  • signing-request-web-url: URL of the signing request in SignPath
  • signed-artifact-download-url: download URL of the signed artifact

Pipeline Policies for GitHub

Available for Pipeline Integrity, Open Source Code Signing.

You can define pipeline policies that restrict source code and build settings.

The available policies specific to GitHub are listed in this section.

There are separate policy sections for GitHub’s CI sytem, GitHub Actions (github-build-policies) and GitHub’s source code management system (github-scm-policies).

Example

github-build-policies:
  version: '1.0'
  disallow_reruns: false
  runners:
    require_github_hosted: true
    allowed_groups:
      - Hardened Runners

github-scm-policies:
  version: '1.0'
  ruleset_constraints:
  - enforced_from: 2025-01-01
    allow_bypass_actors: true
    rules:
      - type: non_fast_forward
      - type: pull_request
        parameters:
          required_approving_review_count: 2
          require_last_push_approval: true

github-build-policies

Allows to restrict the GitHub Actions build with the following policies:

Top-Level Policy Description
disallow_reruns Set to true to prevent signing builds from re-runs. By enforcing this policy, old, temporarily failed builds cannot be re-run and signed under the false impression that they include recent changes, such as vulnerability fixes. These builds would still be identified by their branch name, e.g. main.
runners Runner-specific settings, see table below.

Limit to 3 re-runs

Due to performance reasons, SignPath currently allows policy evaluation for up to 3 re-runs of a build. Further re-runs with active policies will fail.

runners section

Policy Description
required_github_hosted Set to true to ensure that all jobs of the workflow are executed on Github-hosted runners.
alllowed_groups Provide a list of GitHub runner group names. Ensures that all jobs of the workflow are executed on runners from one of the listed groups.

github-scm-policies

Allows to define ruleset_constraints for GitHub branch rulesets. All specified constraints must be covered by one or multiple active branch rulesets defined in GitHub. Multiple ruleset_constraints with different parameters can be defined.

How ruleset constraints map to GitHub ruleset rules

GitHub allows you to define branch rulesets, both for repositories and at an organization level. Each branch ruleset defines a set of rules and, optionally, a set of bypass actors.

SignPath allows you to define ruleset contraints. Every rule in a ruleset constraint defined in SignPath’s policies must be fulfilled by at least one rule in a branch ruleset on GitHub. You can define whether bypass actors are allowed and whether the constraint has to be continually fulfilled (see below).

Example:

For example, the following GitHub branch rulesets would fulfill all of the defined ruleset constraints:

  1. The non_fast_forward constraint is covered by Ruleset 1
  2. The deletion constraint is covered by Ruleset 1. It would allow bypass actors, but disallowing them is stricter and therefore valid.
  3. The creation constraint is covered by Ruleset 2.
SignPath constraints GitHub branch rulesets
github-scm-policies:
   ruleset_constraints:
     - allow_bypass_actors: false
       rules:
         - type: non_fast_forward
     - allow_bypass_actors: true
       rules:
         - type: deletion
         - type: creation

Ruleset 1 (does not allow bypass actors)

  • non_fast_forward
  • deletion

Ruleset 2 (allows bypass actors)

  • creation

General parameters for ruleset_constraints

Parameter Values Description
allow_bypass_actors boolean If true, the branch ruleset is allowed to define bypassers
enforced_from CURRENT_BUILD (default), timestamp or EARLIEST By default, the constraints are only evaluated at the time of signing (CURRENT_BUILD). When another value is set for enforced_from, the constraints must have been continously fulfilled from the specified date (YAML ISO timestamp) or earliest availability of audit log entries (EARLIEST).

GitHub export

The SignPath policies are an extension and therefore compatible with the export format in GitHub. You can export a branch ruleset in GitHub, convert it to YAML and then paste the entire rules section under ruleset_constraints in your SignPath policies.

About enforced_from evaluation

Depending on your GitHub subscription, the continuous enforcement of policies is either based on:

  • Audit log events for GitHub Enterprise subscriptions. Audit log events are only available for the last 180 days, any prior policy violations will not be detected. Audit Log evaluation requires the SignPath GitHub App to be installed.
  • The last modified date of the branch rulesets for all other subscriptions. At least one branch ruleset that has not been modified since the specified timestap must implement the rule.

Supported rules

The following rules are supported:

Type Parameters Description
creation Only allow users with bypass permission to create matching refs.
update Only allow users with bypass permission to update matching refs.
deletion Only allow users with bypass permissions to delete matching refs.
required_linear_history Prevent merge commits from being pushed to matching refs.
pull_request Yes Require all commits be made to a non-target branch and submitted via a pull request before they can be merged.
non_fast_forward Prevent users with push access from force pushing to refs.
code_scanning Yes Choose which tools must provide code scanning results before the reference is updated. When configured, code scanning must be enabled and have results for both the commit and the reference being updated.
required_signatures Require commits to be signed with a GPG key that is verified by GitHub.
file_path_restriction Yes Prevent commits that include changes in specified file and folder paths from being pushed to the commit graph. This includes absolute paths that contain file names.
file_extension_restriction Yes Prevent commits that include files with specified file extensions from being pushed to the commit graph.
max_file_path_length Yes Prevent commits that include file paths that exceed the specified character limit from being pushed to the commit graph.
max_file_size Yes Prevent commits with individual files that exceed the specified limit from being pushed to the commit graph.
copilot_code_review Yes Request Copilot code review for new pull requests automatically if the author has access to Copilot code review and their premium requests quota has not reached the limit.
pull_request

Require all commits be made to a non-target branch and submitted via a pull request before they can be merged.

The following parameters are supported:

Parameter Description
dismiss_stale_reviews_on_push
(boolean)
New, reviewable commits pushed will dismiss previous pull request review approvals.
require_code_owner_review
(boolean)
Require an approving review in pull requests that modify files that have a designated code owner.
require_last_push_approval
(boolean)
Whether the most recent reviewable push must be approved by someone other than the person who pushed it.
required_approving_review_count
(integer)
The number of approving reviews that are required before a pull request can be merged.
Note: The value defines a required minimum. Higher values are accepted.
required_review_thread_resolution
(boolean)
All conversations on code must be resolved before a pull request can be merged.

Example:

  github-scm-policies:
    ruleset_constraints:
      - rules:
        - type: pull_request
          parameters: 
            dismiss_stale_reviews_on_push: true
            require_code_owner_review: true
            require_last_push_approval: true
            required_approving_review_count: 1
            required_review_thread_resolution: true
code_scanning

Choose which tools must provide code scanning results before the reference is updated. When configured, code scanning must be enabled and have results for both the commit and the reference being updated.

The following parameters are supported:

Parameter DescriptionProperties
code_scanning_tools
(object array; required)
Tools that must provide code scanning results for this rule to pass.
Property Values Description
alerts_threshold
(required)
one of
  1. none
  2. errors
  3. errors_and_warnings
  4. all

The severity level at which code scanning results that raise alerts block a reference update. For more information on alert severity levels, see “About code scanning alerts.”

Note: The value defines a required minimum. Higher values are accepted.

security_alerts_threshold
(required)
one of
  1. none
  2. critical
  3. high_or_higher
  4. medium_or_higher
  5. all

The severity level at which code scanning results that raise security alerts block a reference update. For more information on security severity levels, see “About code scanning alerts.”

Note: The value defines a required minimum. Higher values are accepted.

tool
(required)
string

The name of a code scanning tool

Example:

  github-scm-policies:
    ruleset_constraints:
      - rules:
        - type: code_scanning
          parameters: 
            code_scanning_tools: 
              - alerts_threshold: all
                security_alerts_threshold: all
                tool: CodeQL
              
file_path_restriction

Prevent commits that include changes in specified file and folder paths from being pushed to the commit graph. This includes absolute paths that contain file names.

The following parameters are supported:

Parameter Description
restricted_file_paths
(string array; required)
The file paths that are restricted from being pushed to the commit graph.

Example:

  github-scm-policies:
    ruleset_constraints:
      - rules:
        - type: file_path_restriction
          parameters: 
            restricted_file_paths: 
              - 'src/config/local.env'
file_extension_restriction

Prevent commits that include files with specified file extensions from being pushed to the commit graph.

The following parameters are supported:

Parameter Description
restricted_file_extensions
(string array; required)
The file extensions that are restricted from being pushed to the commit graph.

Example:

  github-scm-policies:
    ruleset_constraints:
      - rules:
        - type: file_extension_restriction
          parameters: 
            restricted_file_extensions: 
              - '.sql'
max_file_path_length

Prevent commits that include file paths that exceed the specified character limit from being pushed to the commit graph.

The following parameters are supported:

Parameter Description
max_file_path_length
(integer; required)
The maximum amount of characters allowed in file paths.
Note: The value defines a required maximum. Lower values are accepted.

Example:

  github-scm-policies:
    ruleset_constraints:
      - rules:
        - type: max_file_path_length
          parameters: 
            max_file_path_length: 1024 # characters
max_file_size

Prevent commits with individual files that exceed the specified limit from being pushed to the commit graph.

The following parameters are supported:

Parameter Description
max_file_size
(integer; required)
The maximum file size allowed in megabytes. This limit does not apply to Git Large File Storage (Git LFS).
Note: The value defines a required maximum. Lower values are accepted.

Example:

  github-scm-policies:
    ruleset_constraints:
      - rules:
        - type: max_file_size
          parameters: 
            max_file_size: 10 # mb
copilot_code_review

Request Copilot code review for new pull requests automatically if the author has access to Copilot code review and their premium requests quota has not reached the limit.

The following parameters are supported:

Parameter Description
review_draft_pull_requests
(boolean)
Copilot automatically reviews draft pull requests before they are marked as ready for review.
review_on_push
(boolean)
Copilot automatically reviews each new push to the pull request.

Example:

  github-scm-policies:
    ruleset_constraints:
      - rules:
        - type: copilot_code_review
          parameters: 
            review_draft_pull_requests: true
            review_on_push: true