Skip to content

Commit 07dbb68

Browse files
committed
feat(gha): ensure action sources use commit hash
resolves: #7057
1 parent 79e8fb8 commit 07dbb68

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from __future__ import annotations
2+
3+
import re
4+
from typing import Any
5+
6+
from checkov.common.models.enums import CheckResult
7+
from checkov.github_actions.checks.base_github_action_check import BaseGithubActionsCheck
8+
from checkov.yaml_doc.enums import BlockType
9+
10+
# Matches @ followed by a 40-character SHA-1 commit hash with optional trailing comment
11+
COMMIT_ID_PATTERN = re.compile(r"@[0-9a-f]{40}\s*(#.*)?$")
12+
13+
14+
class RevisionHash(BaseGithubActionsCheck):
15+
def __init__(self) -> None:
16+
name = "Ensure GitHub Action sources use a commit hash"
17+
id = "CKV_GHA_8"
18+
super().__init__(
19+
name=name,
20+
id=id,
21+
block_type=BlockType.ARRAY,
22+
supported_entities=('jobs', 'jobs.*.steps[]')
23+
)
24+
25+
def scan_conf(self, conf: dict[str, Any]) -> tuple[CheckResult, dict[str, Any] | None]:
26+
if not isinstance(conf, dict):
27+
return CheckResult.UNKNOWN, conf
28+
uses = conf.get("uses", None)
29+
30+
if uses is None or re.search(COMMIT_ID_PATTERN, uses):
31+
return CheckResult.PASSED, conf
32+
33+
return CheckResult.FAILED, conf
34+
35+
36+
check = RevisionHash()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Checkov
2+
on:
3+
push:
4+
branches:
5+
- master
6+
7+
permissions: {}
8+
9+
jobs:
10+
checkov-job:
11+
runs-on: ubuntu-latest
12+
name: checkov-action
13+
steps:
14+
- name: Checkout with master version of action
15+
uses: actions/checkout@master
16+
17+
- name: Checkout with tagged version
18+
uses: actions/checkout@v3
19+
20+
- name: Checkout with hash
21+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
22+
23+
- name: Checkout with hash and comment on the same line
24+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
25+
26+
- name: Run Checkov action
27+
id: checkov
28+
# checkov:skip=CKV_GHA_8:Trust our own stuff?
29+
uses: bridgecrewio/checkov-action@master
30+
with:
31+
directory: terraform/
32+
framework: terraform

tests/github_actions/test_runner.py

+17
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,23 @@ def test_runner_on_workflows_dispatch(self):
301301
assert len(report.skipped_checks) == 0
302302
assert len(report.parsing_errors) == 0
303303

304+
def test_runner_revision_hash(self):
305+
# given
306+
file_path = Path(__file__).parent / "gha/.github/workflows/revision_hash.yaml"
307+
file_dir = [str(file_path)]
308+
checks = ["CKV_GHA_8"]
309+
310+
# when
311+
report = Runner().run(
312+
files=file_dir, runner_filter=RunnerFilter(framework=["github_actions"], checks=checks)
313+
)
314+
315+
# then
316+
assert len(report.failed_checks) == 2
317+
assert len(report.passed_checks) == 2
318+
assert len(report.skipped_checks) == 2
319+
assert len(report.parsing_errors) == 0
320+
304321

305322
if __name__ == "__main__":
306323
unittest.main()

0 commit comments

Comments
 (0)