Skip to content

Commit 383da33

Browse files
committed
ci(final-check): sanitize the report in the comment job
The check job runs the PR's code, so the report it outputs is untrusted. The comment job now drops every @ and breaks issue references (#12, owner/repo#12, GH-7) and issue, PR and discussion links before TechEngineBot posts, and caps the body at 65,000 characters. Markers, tables, run links, hex colours and HTML entities pass through unchanged, and applying it twice changes nothing. Docs: ADR-017 exception 6 lists all five GetTechAPI repos that carry a final-check.yml, and the README paragraph is re-wrapped to 80 columns.
1 parent 55ba700 commit 383da33

3 files changed

Lines changed: 20 additions & 11 deletions

File tree

‎.github/workflows/final-check.yml‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,16 @@ jobs:
189189
github-token: ${{ secrets.TECHENGINEBOT_TOKEN }}
190190
script: |
191191
const marker = '<!-- techengine-final-check -->';
192-
const body = process.env.BODY || '';
192+
// The check job ran the PR's code, so its report is untrusted here:
193+
// drop every @ and break issue references and issue/PR links, so the
194+
// comment can neither mention anyone nor cross-reference anything.
195+
const zw = '\u200b';
196+
const body = (process.env.BODY || '')
197+
.replace(/@/g, '')
198+
.replace(/(?<!&)#(?=\d+\b)/g, `#${zw}`)
199+
.replace(/\bgh-(?=\d+\b)/gi, `$&${zw}`)
200+
.replace(/\/(issues|pull|discussions)\/(?=\d)/g, `/$1/${zw}`)
201+
.slice(0, 65000);
193202
if (!body.startsWith(marker)) {
194203
core.setFailed('The check job produced no report; nothing posted.');
195204
return;

‎README.md‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ TechAPI/ # submodule -> GetTechAPI/TechAPI (clickable @ <sha> link
4040
ingest.yml # workflow_call: draft new SKUs -> one PR on TechAPI
4141
refresh.yml # workflow_call: re-scrape benchmarks -> one PR on TechAPI
4242
verify-promote.yml # workflow_call: Tier 1-3 checks + verified promotion PR
43-
final-check.yml # `final-check` label: test.yml's checks, one TechEngineBot comment
43+
final-check.yml # label-triggered checks + one TechEngineBot comment
4444
```
4545

4646
## How The Two Repos Connect
@@ -49,14 +49,14 @@ Both repos live in the **GetTechAPI** org and each includes the other as a git
4949
**submodule** (a clickable `@ <sha>` pin). Nothing syncs them automatically.
5050

5151
No workflow here runs on a schedule or uses a personal access token (ADR-017).
52-
The one comment any workflow posts is TechEngineBot's final check, and only
53-
when a maintainer adds the `final-check` label to a PR (`final-check.yml`). Collection runs only when a maintainer dispatches
54-
TechAPI's `collect.yml`, which calls `ingest.yml`, `refresh.yml` or
55-
`verify-promote.yml` with TechAPI's own `GITHUB_TOKEN`. Each task keeps at most
56-
one open PR on a fixed `collect/*` branch, updated in place, after
57-
`app.validate` and `integrity_check.py --strict` pass. The engine that runs is
58-
the TechEngine commit TechAPI pins as its submodule. Crawlers identify
59-
themselves with a `TechEngine-*` User-Agent.
52+
The one comment any workflow posts is TechEngineBot's final check, and only when
53+
a maintainer adds the `final-check` label to a PR (`final-check.yml`).
54+
Collection runs only when a maintainer dispatches TechAPI's `collect.yml`, which
55+
calls `ingest.yml`, `refresh.yml` or `verify-promote.yml` with TechAPI's own
56+
`GITHUB_TOKEN`. Each task keeps at most one open PR on a fixed `collect/*`
57+
branch, updated in place, after `app.validate` and `integrity_check.py --strict`
58+
pass. The engine that runs is the TechEngine commit TechAPI pins as its
59+
submodule. Crawlers identify themselves with a `TechEngine-*` User-Agent.
6060

6161
Every Python entry point reads data from a **TechAPI checkout**. The location
6262
can be overridden via `TECHAPI_DATA_DIR`; by default TechEngine supports both

‎docs/SPEC.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2005,7 +2005,7 @@ TechAPI의 **핵심 목표 중 하나**. TechPicks 외에 다양한 앱·플랫
20052005
3. 레포 간 `repository_dispatch` 중계와 서브모듈 자동 bump(`notify-*`, `bump-*`)는 없앤다.
20062006
4. `verify-status`는 TechAPI `dump-develop`에 합치고, `dump-refresh`는 `dump-develop`의 수동 전체 재생성으로 대체한다. 커버리지 리포트는 주 1회, TechEngine 레포 이슈만 갱신한다.
20072007
5. 스크레이핑 워크플로(`weekly-data.yml`)는 수동 실행으로 검증한 뒤에 cron을 켠다.
2008-
6. **예외 — TechEngineBot 최종 확인**: TechEngineBot 계정은 중요한 PR의 최종 확인자 역할로만 쓴다. 메인테이너가 PR에 `final-check` 라벨을 붙일 때만 각 레포의 `final-check.yml`(TechAPI, TechEngine)이 돌고, PR 하나에 댓글 하나(재실행 시 같은 댓글 수정)만 남긴다. 검사 작업은 시크릿 없이 읽기 전용 토큰으로 돌고, `TECHENGINEBOT_TOKEN`(TechEngineBot의 fine-grained 토큰, Pull requests: read and write)은 그 댓글 작업에만 쓴다. Copilot 리뷰는 쓰지 않는다. 스케줄·push·PR 이벤트로 TechEngineBot이 움직이는 워크플로는 만들지 않는다.
2008+
6. **예외 — TechEngineBot 최종 확인**: TechEngineBot 계정은 중요한 PR의 최종 확인자 역할로만 쓴다. 메인테이너가 PR에 `final-check` 라벨을 붙일 때만 각 GetTechAPI 레포(TechAPI, TechEngine, TechMachine, game-catalog, cpu-engineering-samples)의 `final-check.yml`이 돌고, PR 하나에 댓글 하나(재실행 시 같은 댓글 수정)만 남긴다. 검사 작업은 시크릿 없이 읽기 전용 토큰으로 돌고, `TECHENGINEBOT_TOKEN`(TechEngineBot의 fine-grained 토큰, Pull requests: read and write)은 그 댓글 작업에만 쓴다. Copilot 리뷰는 쓰지 않는다. 스케줄·push·PR 이벤트로 TechEngineBot이 움직이는 워크플로는 만들지 않는다.
20092009
- **개정 (2026-11-01)**: TechAPI는 PR 검증을 자체 검증기로 직접 돌리므로, 2·4·5번을 다음으로 대체한다.
20102010
- PR 댓글 워크플로(`techapi-pr-validation-comment`, `techapi-verify-comment`)와 `refresh-data`를 삭제한다. `coverage-report`는 수동 실행·읽기 전용으로 바꾼다.
20112011
- 수집·검증(`weekly-ingest`, `weekly-refresh`, `verify-network`)은 `ingest.yml`, `refresh.yml`, `verify-promote.yml`로 바꾼다. TechAPI `collect.yml`이 `workflow_dispatch`로만 호출하는 PR 생성기다. 작업마다 고정 브랜치(`collect/*`)에 열린 PR을 최대 1개만 두고 제자리에서 갱신한다. 댓글은 달지 않으며, 게이트(`app.validate`, `integrity_check.py --strict`) 결과와 Tier 0 보고서는 PR 본문에 남긴다. 덤프는 커밋하지 않는다. 실행되는 엔진은 TechAPI가 서브모듈로 고정한 TechEngine 커밋이다.

0 commit comments

Comments
 (0)