코드 강제(Code Enforcement)
개요
가드는 누군가가 이를 우회하려 할 때 무엇을 거부하는지로 평가되며, 정상 경로(happy path) 통과 여부로 평가되지 않습니다. 리뷰를 통과하는 두 가지 실패 모드는 위험한 값 자체가 아닌 값의 표현(representation)을 검사하는 제어와, 실행할 수 없었음에도 성공을 반환하는 제어입니다. 둘 다 작성자 자신의 가정 하에 작성된 모든 테스트에서는 정상으로 보입니다.
사용법
훅, 가드, 검증기, 권한 검사, 린트 규칙 또는 CI 게이트를 작성하거나 변경할 때 아래 단계를 따르십시오. 파일을 열기 전에 시작하십시오. 1단계가 종종 코드가 속한 위치를 바꾸기 때문입니다.
일반적인 예시: "저장소 외부에서 rm -rf 차단" (1단계는 명령 문자열에서 결정을 옮깁니다), "마이그레이션에 롤백이 없으면 CI 실패" (3단계와 4단계는 마이그레이션 목록이 비어 돌아올 때 게이트가 통과하는 것을 막습니다), "서명되지 않은 커밋이 있는 푸시 거부" (5단계는 별칭, --no-verify, 두 번째 원격을 열거합니다).
단계
- 싱크(sink)를 명명하십시오. 보호하는 대상을 정확히 명시하십시오: 확장된 argv, 요청 본문, SQL 파라미터, 확인된 경로. 그 값을 검증하십시오.
- 실제로 볼 수 있는지 확인하십시오. 코드가 값의 표현(representation)만 가지고 있다면 — 셸 명령 문자열, diff, 로그 줄, 커밋 메시지 — 결정은 검사가 아닌 휴리스틱(heuristic)입니다. 주석과 전달 노트에 명시하고, 해당 계층을 권고(advisory)로 표시하십시오. 되돌릴 수 없는 결과에 대해 휴리스틱을 유일한 장벽으로 삼지 마십시오.
- 실패 시 폐쇄(fail closed)하십시오. 누락된 런타임, 읽을 수 없는 입력, 파서 예외, 확인되지 않은 변수, 빈 결과: 거부하고 무엇이 누락되었는지 명명하십시오. 실행할 수 없어서 0을 반환하는 가드는 비활성화된 가드이며, 몇 달 동안 조용히 비활성화 상태로 남습니다.
- 프로브(probe)의 실패를 보이게 만드십시오. 가드가 실행될 수 있는지 여부를 결정하는 명령에
2>/dev/null을 사용하지 말고, 빈 결과를 성공으로 바꾸는 분기를 만들지 마십시오. 프로브가 조용히 실패해도 된다면, 3단계는 시행 불가능합니다. - 수정을 작성하기 전에 우회 경로를 열거하십시오. 제어가 만족되거나 건너뛸 수 있는 방법을 나열하십시오: 복합 명령, 중복 플래그, 두 번째 호출, 별칭이나 함수, 누락된 인터프리터, 다른 호스트, 서브셸, 이름이 변경된 파일. 목록을 커밋 본문이나 테스트 파일에 유지하십시오.
- 목록의 각 항목을 프로젝트의 자동화된 검사에 연결된 테스트 케이스로 전환하십시오. 수동 자체 테스트는 인정되지 않습니다: 테스트를 실행한 세션이 사라지면 함께 사라집니다.
- 우회가 저렴하고 결과가 심각할 때, 적대적 패스를 실행하십시오. 새로운 컨텍스트의 하위 에이전트를 파견하여 가드를 검토하는 것이 아니라 깨뜨리는 것을 목표로 삼게 하십시오. 그 출력은 시도 목록과 결과입니다. 최악의 경우가 경고인 제어에 대해서는 이 단계를 건너뛰십시오.
주의사항
- 셸 명령을 구문 분석하여 결정하기. 따옴표,
$(),&&, 별칭 및env접두사는 모두 최종 실행을 변경합니다. 이러한 계층은 속도 방지턱일 뿐입니다. 실제 검사는 명령의 효과가 도달하는 곳에 있어야 합니다. command -v가드.if command -v tool > /dev/null; then check; fi는 도구가 없는 모든 시스템에서 검사를 조용히 건너뜁니다 — 바로 그 도구가 가장 필요한 시스템에서 말이죠. 반대로 하십시오: 도구가 없을 때 거부하십시오.- 아무것도 찾지 못하는 발견 단계.
git grep -E는\b를 지원하지 않으므로, 이러한 패턴은 오류 없이 0개의 파일과 일치하며 게이트는 아무것도 읽지 않고 통과합니다. 카나리(canary)로 단계를 보호하십시오: 출력에 반드시 나타나야 하는 파일을 사용하십시오. - 구현한 거부만 테스트하기. 흥미로운 테스트는 생각하지 못한 입력입니다. 이것이 5단계가 생성하는 것입니다.
- 수동으로만 테스트된 가드. 작성자의 머신에서는 통과하지만, 그 후 썩어갑니다. 프로젝트에 테스트를 연결할 장소가 없다면, 그 누락된 하네스(harnes)도 작업의 일부입니다.
- 가드를 작성한 컨텍스트는 그것을 깨뜨릴 수 없습니다. 구멍을 만든 맹점을 공유하며, 자신의 설계를 확인할 것입니다. 새로운 컨텍스트만이 적대적입니다.
제약 사항
- 보호된 값에 접근 가능할 때 그 값을 대리하는 프록시(proxy)로 결정하지 마십시오.
- 가드가 자신의 임무를 수행할 수 없는 경로에서 0을 반환하지 마십시오. 거부하고 원인을 명명하십시오.
- 가드가 실행될 수 있는지 여부를 설정하는 프로브의 오류를 절대 억제하지 마십시오.
- 열거된 모든 우회 경로는 전달 전에 자동화된 테스트로 존재해야 합니다.
- 어떤 계층이 권고(advisory)이고 어떤 계층이 시행(enforcing)인지 명확히 밝히십시오. 보장으로 제시된 휴리스틱은 가드가 없는 것보다 더 나쁩니다.