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@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
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@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
- uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8
4 changes: 2 additions & 2 deletions .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@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8; immutable SHA pinning retained as supply-chain attack mitigation.
with:
sarif_file: normalized-scorecard-results.sarif
sarif_file: normalized-scorecard-results.sarif
4 changes: 2 additions & 2 deletions .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@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8; immutable SHA pinning retained as supply-chain attack mitigation.
if: always()
with:
sarif_file: trivy-results.sarif
sarif_file: trivy-results.sarif
6 changes: 5 additions & 1 deletion 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.8` revision, with a regression contract that prevents mixed `init`, `autobuild`, `analyze`, and `upload-sarif` versions.

## [0.1.3] - 2026-04-29

### Fixed
Expand Down Expand Up @@ -65,4 +69,4 @@

- `ChordsFeature` (코드 분석) 화면에서 각 파트(Role)의 `transpositionPlan`(이조/조옮김 계획)을 표시하는 기능을 추가했습니다.
- `RangesFeature` (음역대 분석) 화면에서 겹침 경고(Overlap warning) 외에 해당 파트의 채보(Transcription) 가능 노드 수를 요약하여 보여주는 기능을 추가했습니다.
- 신규 UI 요소에 대한 100% 테스트 커버리지를 보장하는 단위 테스트를 추가했습니다 (`apps/desktop/src/features/chords/index.test.tsx`, `apps/desktop/src/features/ranges/index.test.tsx`).
- 신규 UI 요소에 대한 100% 테스트 커버리지를 보장하는 단위 테스트를 추가했습니다 (`apps/desktop/src/features/chords/index.test.tsx`, `apps/desktop/src/features/ranges/index.test.tsx`).
65 changes: 65 additions & 0 deletions docs/doctoring/codeql-action-atomic-revision.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# 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.8` at commit `db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28`. The upstream annotated tag object `37f2634a92ba38a0926ef79a0748ac8ae7d95ab2` resolves to that commit. The release was published on August 21, 2026 and reports no user-facing changes; it retains the v4.37.7-era default CodeQL bundle `2.26.3`.

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.8` annotation; and
3. `codeql.yml` keeps `init`, `autobuild`, and `analyze` on that same revision.

The scanner intentionally recognizes mutable and malformed revision tokens such as `@v4` before enforcing the exact-SHA invariant. A tag-style reference therefore becomes a failing value instead of disappearing from the evidence set because it did not already look like a 40-character SHA.

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.8* [Software release]. https://github.com/github/codeql-action/releases/tag/v4.37.8

GitHub. (2026). *CodeQL Bundle v2.26.3* [Software release]. https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.26.3

GitHub. (n.d.). *CodeQL code scanning for compiled languages*. GitHub Docs. Retrieved August 25, 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 25, 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,63 @@
"""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 = "db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28"
_EXPECTED_CODEQL_ACTION_VERSION = "v4.37.8"
_CODEQL_ACTION_REFERENCE = re.compile(
r"github/codeql-action/(init|autobuild|analyze|upload-sarif)@([^\s#]+)([^\n]*)"
)


def _codeql_action_references() -> list[tuple[Path, str, str, str]]:
"""Return every 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")
matches = _CODEQL_ACTION_REFERENCE.findall(workflow_text)
for action_name, revision_ref, suffix in matches:
reference = (workflow_path, action_name, revision_ref, suffix.strip())
references.append(reference)
return references


def test_reference_scanner_detects_non_sha_codeql_references() -> None:
"""Mutable CodeQL refs must be visible to the guard instead of being skipped."""
workflow_line = "uses: github/codeql-action/init@v4 # mutable reference"

matches = _CODEQL_ACTION_REFERENCE.findall(workflow_line)

assert matches == [("init", "v4", " # mutable reference")]


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_ref for _, _, revision_ref, _ in references
} == {_EXPECTED_CODEQL_ACTION_SHA}
expected_version = f"# {_EXPECTED_CODEQL_ACTION_VERSION}"
assert all(expected_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_ref
for action_name, revision_ref, _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