diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7282b641d..d83efcc04 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ concurrency: jobs: verify: name: verify - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 15 permissions: contents: read diff --git a/.github/workflows/patch-validator-image.yml b/.github/workflows/patch-validator-image.yml index 8a155b759..89ed4139b 100644 --- a/.github/workflows/patch-validator-image.yml +++ b/.github/workflows/patch-validator-image.yml @@ -23,7 +23,7 @@ env: jobs: verify_image: name: verify-patch-validator-image - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 180 permissions: contents: read diff --git a/.github/workflows/reviewer-ci.yml b/.github/workflows/reviewer-ci.yml index c999450a2..f5212251a 100644 --- a/.github/workflows/reviewer-ci.yml +++ b/.github/workflows/reviewer-ci.yml @@ -16,7 +16,7 @@ permissions: jobs: reviewer: name: reviewer - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 timeout-minutes: 30 env: NOEMA_CODEGRAPH_SANDBOX_SOURCE_IMAGE: gcr.io/distroless/java-base-debian13:nonroot diff --git a/CHANGELOG.md b/CHANGELOG.md index 589afeda7..11519b54d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased +- Noema의 필수 PR 워크플로 `ci`, `reviewer-ci`, `patch-validator-image`를 부동 `ubuntu-latest` 대신 명시적 `ubuntu-24.04` GitHub-hosted runner에 고정하고, 인용 여부와 무관하게 `ubuntu-latest` 회귀를 탐지하는 계약 테스트를 추가해 pre-checkout runner-assignment stall의 repository-owned selector 원인을 제거한다. 중앙 `Security Scan`의 runner/control-plane 권한은 별도 `.github` owner 경계에 유지한다. - 비공개 취약점 보고 감사가 16 KiB 응답 상한, bounded stream 취소, canonical repository/source identity의 독립 검증, SHA-1/SHA-256 exact revision, symlink·retained-path 보호를 실패-폐쇄로 강제한다. 이 감사 결과는 live private reporting 활성화, notification staffing, 실제 advisory 대응 또는 release/deployment 완료 증거를 대신하지 않는다. - External scheduler evidence audits now retain source authority through final report publication: reports are owner-only, no-follow, exclusive one-shot receipts, so a concurrent rename cannot move the accepted source inode onto the report pathname and have it replaced. Source/report path and inode alias checks, single-link retained-source validation, and Unicode control sanitization remain fail closed. - production runtime credential envelope parsing을 fail-closed로 강화한다. GitHub App PKCS#1 key의 canonical PKCS#8 변환은 유지하되, bare carriage return처럼 비정규 body bytes가 포함된 PKCS#8 PEM은 readiness/import 단계의 암묵적 정규화에 넘기지 않고 즉시 거부해 malformed secret이 ready 상태로 승인되지 않게 한다. diff --git a/test/workflow-runner-selector.test.ts b/test/workflow-runner-selector.test.ts new file mode 100644 index 000000000..f3bbacaa1 --- /dev/null +++ b/test/workflow-runner-selector.test.ts @@ -0,0 +1,32 @@ +import { readFileSync } from "node:fs"; + +import { describe, expect, it } from "vitest"; + +const requiredRunnerBackedWorkflows = [ + ".github/workflows/ci.yml", + ".github/workflows/reviewer-ci.yml", + ".github/workflows/patch-validator-image.yml", +] as const; + +const runsOnSelector = /^\s*runs-on:\s*(["']?)([^\s"']+)\1\s*$/m; + +describe("required workflow runner selector", () => { + it.each(requiredRunnerBackedWorkflows)( + "%s uses the explicit supported Ubuntu runner image", + (workflowPath) => { + const workflow = readFileSync(workflowPath, "utf8"); + const match = workflow.match(runsOnSelector); + + expect(match?.[2]).toBe("ubuntu-24.04"); + expect(match?.[2]).not.toBe("ubuntu-latest"); + }, + ); + + it.each([ + "runs-on: ubuntu-latest", + 'runs-on: "ubuntu-latest"', + "runs-on: 'ubuntu-latest'", + ])("rejects floating runner selector syntax: %s", (workflowLine) => { + expect(workflowLine.match(runsOnSelector)?.[2]).toBe("ubuntu-latest"); + }); +});