# task-900.1 완료 보고서: injection_guard.py + notify-completion.py 보안 패치
> 팀: dev1-team | 팀장: 헤르메스 | 작업일: 2026-03-24

---

## SCQA

**S**: task-899.1(자동화 오케스트레이터 설계) 에이전트 미팅에서 펜리르가 P0 보안 위협 2건을 식별했다. (1) injection_guard.py가 인젝션 탐지 시 로그만 남기고 차단하지 않아 호출자가 결과를 무시하면 인젝션이 통과되며, (2) notify-completion.py의 dispatch 코드가 `bash -c` 문자열 조립으로 셸 인젝션 RCE가 가능하다.

**C**: 두 취약점 모두 CRITICAL 등급으로, 자동화 오케스트레이터 MVP 구현 전에 반드시 패치해야 한다. injection_guard는 파이프라인 YAML의 task_desc 검증에 사용되므로, 하드블록 없이는 악성 프롬프트가 파이프라인을 통해 주입될 수 있다.

**Q**: 기존 하위호환을 유지하면서 두 보안 취약점을 차단할 수 있는가?

**A**: 두 패치 모두 구현 완료. (1) injection_guard.py에 `check_content()` 하드블록 함수와 `InjectionBlockedError` 예외 추가 — high severity 위협 시 즉시 예외 발생, 기존 `scan_content()`는 소프트 체크로 유지. (2) notify-completion.py의 dispatch 블록을 `bash -c` → `subprocess.run(list, shell=False, env=merged_env)` 방식으로 전환하고, 인자값 정규식 검증(`_validate_dispatch_args`) + env 파일 파싱(`load_env_keys`) 추가. pytest 51건 전체 통과, pyright 에러 0건.

---

## 작업 내용

### 패치 1: injection_guard.py 하드블록 (펜리르 P0 1-A 대응)

- `InjectionBlockedError` 예외 클래스 추가 — `threats` 속성으로 위협 목록 보유
- `check_content(text)` 함수 추가 — `scan_content()` 호출 후 high severity 위협 시 예외 발생
- 기존 `scan_content()` 완전 보존 (하위호환)
- `__all__` 선언 추가

### 패치 2: notify-completion.py shell=False (펜리르 P0 1-B 대응)

- `bash -c "source .env.keys && python3 dispatch.py --team {team} ..."` → `subprocess.run(["python3", "dispatch.py", "--team", team, ...], env=merged_env)` 전환
- `load_env_keys()` 함수 추가 — .env.keys 파일을 Python에서 직접 파싱 (export/따옴표 지원)
- `_validate_dispatch_args()` 함수 추가 — team, task_file, level, next_task_id 정규식 검증
- 검증 실패 시 `ValueError` + 로그 기록 후 dispatch 중단

---

## 생성/수정 파일 목록

| # | 파일 | 변경 |
|---|------|------|
| 1 | utils/injection_guard.py | `InjectionBlockedError` + `check_content()` + `__all__` 추가 |
| 2 | utils/tests/test_injection_guard.py | `TestHardBlock` 5개 테스트 추가 (기존 29개 → 34개) |
| 3 | scripts/notify-completion.py | `load_env_keys()` + `_validate_dispatch_args()` 추가, dispatch 블록 shell=False 전환 |
| 4 | scripts/tests/test_notify_completion.py | `TestShellInjectionPrevention` 11개 테스트 추가 (기존 6개 → 17개) |

---

## 발견 이슈 및 해결

### 자체 해결 (3건)

1. **기존 테스트가 `cokacdir` 호출을 검증** — dispatch 부분만 수정하고 `cokacdir` 알림 로직은 미변경하여 기존 테스트 호환 유지
2. **`source .env.keys` 대체 방식** — Python에서 직접 파싱하는 `load_env_keys()` 구현, `export KEY=VALUE` / `KEY="VALUE"` 형식 모두 지원
3. **check_content()의 medium-only 위협 처리** — medium severity만 있을 때는 예외 발생 안 하고 ScanResult 반환 (과차단 방지)

---

## 셀프 QC 체크리스트

- [x] 1. 영향 파일: injection_guard.py는 pipeline_validator.py에서 사용 예정, notify-completion.py는 finish-task.sh에서 호출됨. 기존 인터페이스 유지.
- [x] 2. 엣지 케이스: medium-only 위협 (하드블록 안 됨), .env.keys 파일 없음 (빈 딕셔너리 반환), next_task_id=None (검증 스킵)
- [x] 3. 작업 지시 일치: task-900.1 요구사항(injection_guard 하드블록 + notify-completion.py shell=False) 정확 이행
- [x] 4. 보안 확인: 셸 인젝션 차단 (정규식 검증 + 리스트 방식 subprocess), 프롬프트 인젝션 하드블록 (예외 발생)
- [x] 5. 테스트 커버리지: 51건 전체 통과 (injection_guard 34건, notify-completion 17건)
- [x] 6. 이슈 전부 해결: 3건 자체 해결

---

## 테스트 결과

- **pytest injection_guard**: 34/34 passed (0.08s)
- **pytest notify-completion**: 17/17 passed (0.08s)
- **pyright**: 0 errors, 0 warnings, 0 informations
- **black + isort**: 포매팅 완료

---

## QC 자동 검증

(아래 qc_verify.py 실행 결과 삽입)
