Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
2 changes: 2 additions & 0 deletions .github/workflows/bandit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2
with:
version: "0.8.6"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
contents: read
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22.22.3
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/security-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22.22.3
Expand Down
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 컨트롤(슬라이더 및 +/- 버튼)과 한/영 다국어 지원 포함.

### Fixed

- Disable persisted GitHub checkout credentials before dependency lifecycle execution in the `security-audit`, `release`, and `bandit` workflows.

## [0.1.3] - 2026-04-29

### Fixed
Expand Down
1 change: 1 addition & 0 deletions docs/security/dependency-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Because of that, dependency review, security audit, SBOM generation, and supply-
- dependency graph or dependency submission coverage must stay enabled wherever GitHub supports it for the repository state
- GitHub dependency review must gate PRs into `develop` and `main`
- GitHub Actions workflows that affect the supply chain must stay SHA pinned and least-privilege
- dependency-install and audit jobs must disable persisted checkout credentials before untrusted dependency lifecycle code can execute
- third-party actions require source-trust review, maintenance review, permission review, and commit-SHA pinning before admission

## New dependency admission rule
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""Dependency-workflow checkout credential-boundary regression tests."""

from pathlib import Path

REPOSITORY_ROOT = Path(__file__).resolve().parents[3]
CHECKOUT_MARKER = "- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0"
DEPENDENCY_LIFECYCLE_WORKFLOWS = (
".github/workflows/security-audit.yml",
".github/workflows/release.yml",
".github/workflows/bandit.yml",
)


def _checkout_step(workflow_text: str) -> str:
"""Return the first checkout step without accepting options from later steps."""
checkout_offset = workflow_text.index(CHECKOUT_MARKER)
checkout_tail = workflow_text[checkout_offset:]
next_step_offset = checkout_tail.find("\n - ", len(CHECKOUT_MARKER))
if next_step_offset == -1:
return checkout_tail
return checkout_tail[:next_step_offset]


def test_dependency_workflow_checkout_does_not_persist_github_credentials() -> None:
"""Dependency lifecycle code must not inherit persisted checkout credentials."""
for workflow_path in DEPENDENCY_LIFECYCLE_WORKFLOWS:
workflow_text = (REPOSITORY_ROOT / workflow_path).read_text(encoding="utf-8")
checkout_step = _checkout_step(workflow_text)

assert "persist-credentials: false" in checkout_step, workflow_path


def test_checkout_step_does_not_accept_credentials_from_a_later_step() -> None:
"""A later step option must not satisfy the checkout credential contract."""
workflow_text = f"""steps:
{CHECKOUT_MARKER}
- uses: actions/setup-node@example
with:
persist-credentials: false
"""

assert "persist-credentials: false" not in _checkout_step(workflow_text)
Loading