Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ jobs:
- python
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: github/codeql-action/init@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
- uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
with:
languages: ${{ matrix.language }}
- uses: github/codeql-action/autobuild@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
- uses: github/codeql-action/analyze@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0
- uses: github/codeql-action/autobuild@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
- uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
2 changes: 1 addition & 1 deletion .github/workflows/ossf-scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,6 @@ jobs:
python3 trusted-scorecard-scripts/scripts/checks/normalize_scorecard_sarif.py
scorecard-sarif/results.sarif
normalized-scorecard-results.sarif
- uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0 peeled commit; SHA pinning retained as supply-chain attack mitigation.
- uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6; immutable SHA pinning retained as supply-chain attack mitigation.
with:
sarif_file: normalized-scorecard-results.sarif
2 changes: 1 addition & 1 deletion .github/workflows/trivy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
skip-dirs: 'services/analysis-engine/.venv'
trivyignores: ./.trivyignore
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@99df26d4f13ea111d4ec1a7dddef6063f76b97e9 # v4.37.0 peeled commit; SHA pinning retained as supply-chain attack mitigation.
uses: github/codeql-action/upload-sarif@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6; immutable SHA pinning retained as supply-chain attack mitigation.
if: always()
with:
sarif_file: trivy-results.sarif
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
- Display the analyzed song tempo (BPM) as a badge in the rehearsal workspace.
- 각 합주 역할(Role)별 개인 연습 진행도를 0~100% 범위로 기록 및 시각화할 수 있는 연습 진척도(`practiceProgress`) 트래커 기능 추가. UI 컨트롤(슬라이더 및 +/- 버튼)과 한/영 다국어 지원 포함.

### Changed

- Updated every CodeQL Action phase and SARIF uploader together to the reviewed immutable `v4.37.6` revision, with a regression contract that prevents mixed `init`, `autobuild`, `analyze`, and `upload-sarif` versions.

## [0.1.3] - 2026-04-29

### Fixed
Expand Down
61 changes: 61 additions & 0 deletions docs/doctoring/codeql-action-atomic-revision.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Atomic CodeQL Action revision policy

## Decision

BandScope treats the CodeQL Action lifecycle as one supply-chain dependency. Every checked-in reference to `github/codeql-action/init`, `autobuild`, `analyze`, and `upload-sarif` must use the same reviewed full-length commit SHA and matching release annotation.

The current reviewed revision is CodeQL Action `v4.37.6` at commit `5595ccaf912efad79be6eef63a5619ff05969be3`.

GitHub documents `init` as the phase that initializes CodeQL, `autobuild` as the optional automatic build phase, and `analyze` as the phase that finalizes the database, runs queries, and uploads results. `upload-sarif` publishes SARIF generated by other tools. These phases exchange state and therefore move together in this repository rather than through independent dependency pull requests.

## Threat and compatibility boundary

A full commit SHA is the immutable execution identity. Tags remain useful release labels, but they are not accepted as the workflow execution reference. GitHub identifies a full-length commit SHA as the strongest immutable action reference and supports organization policy requiring that form.

Independently updating one phase can leave the repository with mixed JavaScript bundles, CodeQL CLI expectations, feature flags, or SARIF transport behavior. Even when each individual release is valid, the mixed lifecycle has not been reviewed or tested as a unit. The atomic policy prevents both persistent drift and the transient mixed state that can occur when several Dependabot pull requests merge at different times.

```mermaid
flowchart LR
A[CodeQL init] --> B[CodeQL autobuild]
B --> C[CodeQL analyze]
C --> D[GitHub code scanning]
E[Trivy and Scorecard SARIF] --> F[CodeQL upload-sarif]
R[One reviewed release SHA] --> A
R --> B
R --> C
R --> F
```

The change does not alter workflow triggers, language selection, build behavior, SARIF paths, permissions, or failure handling. It changes only the immutable CodeQL Action implementation identity and version comments.

## Verification contract

`services/analysis-engine/tests/test_codeql_action_revision_contract.py` scans every workflow and fails unless:

1. all CodeQL Action phases use one exact reviewed SHA;
2. every reference carries the matching `v4.37.6` annotation; and
3. `codeql.yml` keeps `init`, `autobuild`, and `analyze` on that same revision.

Repository CI, CodeQL, SAST, dependency/security scans, SBOM generation, central coverage evidence, automated review, independent approval, and branch protection must all validate the final exact head. Results from split predecessor pull requests are not transferable.

## Update procedure

1. Identify the newest supported CodeQL Action v4 release from the upstream GitHub repository.
2. Verify the tag resolves to the intended upstream commit and inspect the release notes.
3. Add or update the contract expectation first and observe the RED failure against the old revision.
4. Update every `init`, `autobuild`, `analyze`, and `upload-sarif` reference in one branch.
5. Run the focused contract, workflow/static checks, and the complete repository gates.
6. Merge only after exact-current-head review and branch protection succeed without bypass.
7. Close split dependency pull requests as superseded; do not reuse their checks or approvals.

## Rollback

Rollback restores the previously accepted full-length SHA across every CodeQL Action phase in one reviewed commit. A partial rollback is prohibited. After rollback, rerun the same exact-head security, quality, SARIF publication, and review gates before accepting the branch.

## References

GitHub. (2026). *CodeQL Action v4.37.6* [Software release]. https://github.com/github/codeql-action/releases/tag/v4.37.6

GitHub. (n.d.). *CodeQL code scanning for compiled languages*. GitHub Docs. Retrieved August 7, 2026, from https://docs.github.com/en/code-security/how-tos/find-and-fix-code-vulnerabilities/manage-your-configuration/codeql-for-compiled-languages

GitHub. (n.d.). *Secure use reference*. GitHub Docs. Retrieved August 7, 2026, from https://docs.github.com/en/actions/reference/security/secure-use
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""Supply-chain contracts for a coherent GitHub CodeQL Action revision."""

from __future__ import annotations

import re
from pathlib import Path

_REPOSITORY_ROOT = Path(__file__).resolve().parents[3]
_WORKFLOW_ROOT = _REPOSITORY_ROOT / ".github" / "workflows"
_EXPECTED_CODEQL_ACTION_SHA = "5595ccaf912efad79be6eef63a5619ff05969be3"
_EXPECTED_CODEQL_ACTION_VERSION = "v4.37.6"
_CODEQL_ACTION_REFERENCE = re.compile(
r"github/codeql-action/(init|autobuild|analyze|upload-sarif)@([0-9a-f]{40})([^\n]*)"
)


def _codeql_action_references() -> list[tuple[Path, str, str, str]]:
"""Return every pinned CodeQL Action reference from checked-in workflows."""
references: list[tuple[Path, str, str, str]] = []
for workflow_path in sorted(_WORKFLOW_ROOT.glob("*.y*ml")):
workflow_text = workflow_path.read_text(encoding="utf-8")
for action_name, revision_sha, suffix in _CODEQL_ACTION_REFERENCE.findall(workflow_text):
references.append((workflow_path, action_name, revision_sha, suffix.strip()))
return references


def test_every_codeql_action_step_uses_the_same_reviewed_revision() -> None:
"""Prevent independently updated phases from creating mixed CodeQL runtimes."""
references = _codeql_action_references()

assert references
assert {revision_sha for _, _, revision_sha, _ in references} == {
_EXPECTED_CODEQL_ACTION_SHA
}
assert all(
f"# {_EXPECTED_CODEQL_ACTION_VERSION}" in suffix
for _, _, _, suffix in references
)


def test_analysis_workflow_keeps_init_autobuild_and_analyze_atomic() -> None:
"""Require the analysis lifecycle to move as one immutable dependency unit."""
workflow_path = _WORKFLOW_ROOT / "codeql.yml"
workflow_text = workflow_path.read_text(encoding="utf-8")
references = {
action_name: revision_sha
for action_name, revision_sha, _suffix in _CODEQL_ACTION_REFERENCE.findall(workflow_text)
}

assert references == {
"init": _EXPECTED_CODEQL_ACTION_SHA,
"autobuild": _EXPECTED_CODEQL_ACTION_SHA,
"analyze": _EXPECTED_CODEQL_ACTION_SHA,
}
Loading