| name | forge-check-security-exec |
| description | 실행기반 보안 검증 스킬. STRIDE 정적 체크(forge-check-security)의 false-negative 갭을 보완 — string-concat SQL/path traversal/HMAC tamper/email injection/Node-DoS를 실제 공격 페이로드로 실행해 pass/fail 판정. opt-in only: auth/payment/file-upload/Node서버 경로에서 수동 호출. P3 advisory: src vs test LOC 분리 출력(게이트 임계 변경 없음). 출력: docs/qa/security-exec-cases.jsonl 누적. |
forge-check-security-exec — 실행기반 보안 scorer
역할: 5종 공격 페이로드를 대상 함수/서버에 실제 실행해 deterministic 판정.
STRIDE 체크리스트가 문서 선언만 보는 곳에서 이 scorer가 실행 증거를 확인한다.
컨텍스트
opt-in 전용 — auth/payment/file-upload/Node 서버 경로에서 forge-check-security 완료 후 HIGH 이상 발견 시 수동 호출한다. 자동 파이프라인 default-on 배선 금지(enforcement-theater 회피).
출력
docs/qa/security-exec-cases.jsonl(scorer별 PASS/FAIL/SKIP/INFO 누적) — selftest 10/10(또는 node 부재 시 8/8) 통과가 배포 전 1순위 게이트.
| Scorer | 공격 유형 | 페이로드 |
|---|
| sql | SQL Injection | "x' OR '1'='1" (in-memory sqlite3) |
| safe_path | Path Traversal | ../../etc/passwd |
| auth | HMAC Token Tamper | user_id 교체 + 원본 서명 재사용 |
| email | Email Header Injection | "ok@ok.com\nevil@evil.com" (개행 주입) |
| todo | Node DoS (null-body POST) | raw="null" → proc.poll() is None 생사 판정 |
P3 advisory: loc_stats() — src vs test LOC 분리 (JSONL INFO 항목, 게이트 임계 변경 없음).
출처: ponytail benchmarks/agentic/tasks.py 공격 페이로드 + Forge verification 모드 adapt.
호출법
python3 ~/forge/.claude/skills/forge-check-security-exec/scripts/scorer.py \
--target <프로젝트_루트>
python3 scorer.py \
--target src/ \
--sql-file src/db.py \
--auth-file src/auth.py \
--path-file src/uploads.py \
--email-file src/emailval.py \
--todo-file src/server.js
python3 scorer.py --selftest
Entry Point 자동 탐지
| Scorer | 탐지 패턴 파일명 | 탐지 함수명 / 조건 |
|---|
| sql | db.py / database.py / models.py / queries.py | get_user / find_user / user_by_username / lookup_user |
| auth | auth.py / authentication.py / token.py / jwt.py | verify_token / verify / check_token / validate_token |
| safe_path | uploads.py / files.py / storage.py / fileutil.py | safe_upload_path / safe_path / secure_upload_path / build_upload_path |
| email | emailval.py / email_validator.py / validators.py / email.py | is_valid_email / validate_email / valid_email / is_email / check_email |
| todo | server.js / app.js / index.js | Node 서버 스폰 (node not on PATH → SKIP) |
파일 탐지 실패 시 해당 scorer SKIP (오탐 방지, 강제 FAIL 금지).
todo: shutil.which("node") 없으면 SKIP (FAIL 아님).
Sandbox 격리
대상 파일을 tempfile.mkdtemp()에 복사 후 import — 라이브 트리 직접 실행 금지.
import 후 tmpdir 즉시 삭제. in-memory sqlite3 사용 (파일시스템 DB 쓰기 없음).
산출물
docs/qa/security-exec-cases.jsonl (프로젝트 루트 기준, --out으로 override):
{"scorer": "sql", "target_file": "src/db.py", "result": "FAIL", "safe": 0, "correct": 1, "reason": "SQL injection: payload returned rows", "ts": "..."}
{"scorer": "auth", "target_file": "src/auth.py", "result": "PASS", "safe": 1, "correct": 1, "reason": "ok", "ts": "..."}
{"scorer": "todo", "target_file": "src/server.js", "result": "FAIL", "safe": 0, "correct": 1, "reason": "crashed on null POST", "ts": "..."}
{"scorer": "loc", "result": "INFO", "src_files": 12, "src_loc": 480, "test_files": 4, "test_loc": 210, "ratio": 0.44, "ts": "..."}
판정: PASS(safe=1) / FAIL(safe=0, exit 2) / SKIP(파일 없음 or node 없음) / INFO(loc advisory).
Opt-In 게이트 (default-on 금지)
연결 시점:
forge-check-security 완료 후 HIGH 이상 발견 시 수동 호출 (auth/payment/file-upload 경로)
- QA Phase F 전 수동 추가 (보안 크리티컬 경로만)
자동 파이프라인 강제 배선 금지 — enforcement-theater 회피.
selftest 패턴
--selftest 실행: good-ref(안전 구현) → safe=1 / bad-ref(취약 구현) → safe=0.
| 스코어 | 케이스 수 | 조건 |
|---|
| sql/safe_path/auth/email | 4×2 = 8 | 항상 |
| todo | 2 (bad-ref/good-ref) | node on PATH 시 — SKIP if absent |
node 있으면 10/10, 없으면 8/8 통과 필수. 불일치 시 비0 exit.
scorer가 틀리면 eval 자체가 무의미 → selftest가 1순위 게이트.
forge-sync
node ~/forge/dev/scripts/forge-sync.mjs sync