Skip to content

위생: 액션 핀 # vN 주석 staleness 감지 — 게이트가 구조적으로 못 잡는 무신호 드리프트 #242

Description

@pdw96

문제 — 게이트가 통과시키는 정책 위반

.semgrep/guardian.yml 은 정책을 이렇게 선언한다:

모든 uses: 는 40자 커밋 SHA 로 핀하고 # vN 주석을 단다

그런데 권위적 강제인 scripts/skills-lint.mjsscanWorkflowPins()주석을 검증하지 않는다. 주석을 ref 추출 전에 버린다:

// scripts/skills-lint.mjs
.replace(/\s+#.*$/, '')                 // L49: 주석 제거
...
if (/^[0-9a-f]{40}$/.test(ref)) return  // L57: 완전 SHA 핀 = 통과(주석 유무 무관)

이는 우발적 누락이 아니라 scripts/skills-lint.test.ts:51-54 로 고정된 의도된 동작이다(주석 유/무 양쪽 통과를 단언).

SHA 와 # vN 주석이 어긋나도 CI 신호가 0이다.

실제 발생 (2026-07-21, #234)

Dependabot 이 actions/setup-node 를 6.4.0 → 7.0.0 으로 올리며 SHA 는 갱신했으나 트레일러 주석은 # v6 그대로 뒀다 — 6곳 전부. skills:lint GREEN, PR 체크 전부 SUCCESS. 사람이 gh api repos/actions/setup-node/git/refs/tags 로 수동 대조해서야 적발했다(머지 전 6cabfba 로 정정).

주석은 6곳에서 유일한 사람-판독 버전 표식인데 거짓을 말하고 있었다. #137 이 이 관례를 도입한 목적(리뷰어가 핀 메이저를 즉시 판별) 자체가 무력화된다. 그리고 SHA 를 바꾸는 다음 범프까지 무기한 잔존한다.

scanWorkflowPins 확장이 답이 아닌가

주석 staleness 실검증은 SHA → 태그 해석이 필요하고 이는 네트워크 의존이다. scanWorkflowPins 는 zero-dep·오프라인 설계이고(Node/Electron CI 에 Python semgrep 툴체인을 더하지 않으려던 #137 의 결정과 동일 계열), 여기에 네트워크를 넣으면 그 설계가 깨진다.

제안 — 별도 주기 워크플로

.github/workflows/ 의 모든 uses: 에 대해 SHA → 태그를 GitHub API 로 해석하고 트레일러 주석과 대조하는 독립 워크플로. 불일치 시 이슈 생성 또는 실패.

  • 트리거: weekly cron (+ workflow_dispatch)
  • PR 게이트로 걸지 말 것 — 네트워크/레이트리밋 의존이라 required check 로 만들면 flaky 하다. 위생 감시자이지 관문이 아니다.
  • 롤링 태그 주의: v1·v6 같은 major alias 는 이동한다. anthropics/claude-code-action 은 의도적으로 # v1(메이저 라인 표기)을 쓰므로 정확 태그 요구는 오탐이 된다 → 정책은 "주석이 SHA 가 속한 태그 집합 중 하나와 정합" 수준이어야 한다.
  • 참고: v6 태그는 현재 v6.5.0 을 가리키는데 핀은 v6.4.0 이었다 — 롤링 태그를 베이스라인으로 쓰면 안 된다(chore(deps): bump actions/setup-node from 6.4.0 to 7.0.0 #234 조사에서 실제로 잘못된 델타를 만들었다).

대안 (더 싼 길)

Dependabot 이 트레일러 주석을 갱신하도록 설정할 수 있는지 먼저 확인. 가능하면 이 워크플로 자체가 불필요해진다. 착수 전 이것부터 조사할 것.

참고

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:devx빌드·툴체인·테스트·개발 위생type:security보안 관련

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions