SettleLab
전체 코스
LESSON 04Security Testing

Slither와 Echidna 보안 워크플로

핵심40분근거 5

학습 결과

  • 정적분석과 property fuzzing의 역할을 구분한다.
  • 도구 결과를 triage하고 false positive를 문서화한다.
  • Slither/Echidna 결과를 release gate와 CI 실패 조건으로 연결한다.

선행 조건

  • Foundry fuzz와 invariant 설계

완료 기준

  • 두 도구의 역할을 설명했다.
  • triage 템플릿을 만들었다.
  • CI 실패 조건을 정의했다.

Slither와 Echidna 보안 워크플로

도입

보안 도구는 정답 생성기가 아니라 triage 도구다. Slither는 정적 분석으로 빠르게 의심 지점을 찾고, Echidna와 Foundry는 property 기반 테스트로 상태 공간을 흔든다. 도구를 실행했다는 사실보다 중요한 것은 결과를 어떤 기준으로 분류하고, 어떤 항목을 release blocker로 삼는지다.

스테이블코인 checkout에서는 자동 도구가 access control 냄새, reentrancy pattern, unused code, property violation을 빠르게 찾아줄 수 있다. 하지만 "merchant settlement가 중복 실행되면 안 된다" 같은 비즈니스 불변식은 사람이 문장으로 정의해야 한다. 이 강의는 도구 결과를 리뷰 표, CI 실패 조건, waiver 정책으로 바꾸는 방법을 다룬다.

학습 목표

  • 정적분석과 property fuzzing의 역할을 구분한다.
  • 도구 결과를 triage하고 false positive를 문서화한다.
  • Slither/Echidna 결과를 release gate와 CI 실패 조건으로 연결한다.

개념 설명

타임라인가로 스크롤 · 크게 보기 지원
Slither와 Echidna 보안 워크플로 학습 타임라인이 시각화는 보안 리뷰와 테스트 캠페인에서 시간 지연, finality, 운영 확인이 어떤 순서로 제품 상태가 되는지를 보여주며, 'Slither와 Echidna 보안 워크플로'에서 남겨야 할 설계 증거를 좁힌다.
1Model

개념 읽기

정적분석과 property fuzzing의 역할을 구분한다.

2Check

실패 상태 확인

권한 경계가 테스트되는가

3Practice

실습 산출물 작성

도구별 역할 분리표 만들기

4Close

완료 기준 대조

두 도구의 역할을 설명했다.

크게 보기
1Model

개념 읽기

정적분석과 property fuzzing의 역할을 구분한다.

2Check

실패 상태 확인

권한 경계가 테스트되는가

3Practice

실습 산출물 작성

도구별 역할 분리표 만들기

4Close

완료 기준 대조

두 도구의 역할을 설명했다.

1. 도구별 역할을 먼저 나눈다

표 자료가로 스크롤 · 크게 보기 지원
도구역할잘 잡는 것한계
Slitherstatic analyzeraccess control 냄새, reentrancy pattern, unused code, dangerous low-level callbusiness logic과 운영 정책을 모른다.
Echidnaproperty-based fuzzeruser-defined property violation, unexpected state sequenceharness와 property 품질에 의존한다.
Foundryunit/fuzz/invariant개발 루프에 가까운 regression, handler 기반 invarianttarget/handler 설계가 약하면 얕게 돈다.
Manual review설계와 threat model 검토trust assumption, economics, role ownership, release risk사람 숙련도와 리뷰 시간에 의존한다.
크게 보기
도구역할잘 잡는 것한계
Slitherstatic analyzeraccess control 냄새, reentrancy pattern, unused code, dangerous low-level callbusiness logic과 운영 정책을 모른다.
Echidnaproperty-based fuzzeruser-defined property violation, unexpected state sequenceharness와 property 품질에 의존한다.
Foundryunit/fuzz/invariant개발 루프에 가까운 regression, handler 기반 invarianttarget/handler 설계가 약하면 얕게 돈다.
Manual review설계와 threat model 검토trust assumption, economics, role ownership, release risk사람 숙련도와 리뷰 시간에 의존한다.

이 표는 도구 선택표가 아니라 리뷰 분업표다. Slither 경고가 없다고 business logic이 안전한 것은 아니고, Echidna property가 통과해도 property 자체가 약하면 의미가 없다.

2. Slither 결과는 detector가 아니라 impact로 분류한다

Slither detector 문서는 각 detector에 severity와 confidence를 붙인다. 리뷰팀은 이를 그대로 복사하지 않고 product impact로 번역해야 한다.

표 자료가로 스크롤 · 크게 보기 지원
FindingStablecoin에서 볼 impact분류 예시
reentrancy patternrefund/withdraw 중 중복 출금 가능성Real issue 또는 defense-in-depth
arbitrary ERC20 transferFrom사용자가 아닌 주소에서 자금 이동 가능성Real issue
unchecked low-level callexternal settlement failure가 무시될 수 있음Real issue
delegatecall/proxy 관련 경고implementation/storage riskManual review required
unused return valuetoken transfer 실패 무시 가능성Real issue 또는 informational
unused code공격면/유지보수 비용 증가Informational
owner/admin 단일 EOAkey compromise riskRelease gate issue
크게 보기
FindingStablecoin에서 볼 impact분류 예시
reentrancy patternrefund/withdraw 중 중복 출금 가능성Real issue 또는 defense-in-depth
arbitrary ERC20 transferFrom사용자가 아닌 주소에서 자금 이동 가능성Real issue
unchecked low-level callexternal settlement failure가 무시될 수 있음Real issue
delegatecall/proxy 관련 경고implementation/storage riskManual review required
unused return valuetoken transfer 실패 무시 가능성Real issue 또는 informational
unused code공격면/유지보수 비용 증가Informational
owner/admin 단일 EOAkey compromise riskRelease gate issue

Slither는 "의심 지점"을 준다. Triage는 "이 지점이 돈의 상태를 바꾸는가, 권한을 우회하는가, release를 막아야 하는가"로 답해야 한다.

3. Echidna property는 불변식을 실행 가능한 질문으로 만든다

Echidna는 user-defined predicate나 assertion을 깨뜨리는 입력/호출 순서를 찾는 property-based fuzzer다. Stablecoin에서 Echidna에 맡길 수 있는 질문은 다음과 같다.

표 자료가로 스크롤 · 크게 보기 지원
Property의미
echidna_total_supply_consistent()추적 supply와 balances 관계가 깨지지 않는다.
echidna_frozen_cannot_move()frozen actor가 어떤 경로로도 balance를 줄이지 못한다.
echidna_pause_blocks_transfer()paused 상태에서 movement 함수가 성공하지 않는다.
echidna_nonce_unique()signed authorization nonce가 재사용되지 않는다.
echidna_payment_idempotent()payment/refund/settlement가 중복 처리되지 않는다.
크게 보기
Property의미
echidna_total_supply_consistent()추적 supply와 balances 관계가 깨지지 않는다.
echidna_frozen_cannot_move()frozen actor가 어떤 경로로도 balance를 줄이지 못한다.
echidna_pause_blocks_transfer()paused 상태에서 movement 함수가 성공하지 않는다.
echidna_nonce_unique()signed authorization nonce가 재사용되지 않는다.
echidna_payment_idempotent()payment/refund/settlement가 중복 처리되지 않는다.

Property 이름은 결과 리포트에서 바로 읽히는 문장이어야 한다. echidna_test1처럼 이름이 애매하면 실패 triage가 느려진다.

4. Triage 템플릿

표 자료가로 스크롤 · 크게 보기 지원
Field작성 기준
ToolSlither, Echidna, Foundry, manual
Detector/propertydetector 이름 또는 property 함수명
Severity/confidence도구의 값과 리뷰팀 조정값을 모두 기록
Affected contract/function출시 영향 범위
Asset at riskuser balance, escrow, supply, admin key, merchant settlement
ClassificationReal issue, defense-in-depth, false positive, informational
Evidencefinding output, failing sequence, code link, screenshot
Actionfix, add test, waive, document, monitor
Owner담당자
Due date / waiver expiry방치 방지
크게 보기
Field작성 기준
ToolSlither, Echidna, Foundry, manual
Detector/propertydetector 이름 또는 property 함수명
Severity/confidence도구의 값과 리뷰팀 조정값을 모두 기록
Affected contract/function출시 영향 범위
Asset at riskuser balance, escrow, supply, admin key, merchant settlement
ClassificationReal issue, defense-in-depth, false positive, informational
Evidencefinding output, failing sequence, code link, screenshot
Actionfix, add test, waive, document, monitor
Owner담당자
Due date / waiver expiry방치 방지

False positive도 근거 없이 닫지 않는다. "코드 문맥상 안전"하다는 증거, 관련 테스트, 만료일이 있어야 한다. 코드가 바뀌면 false positive 판단도 다시 열릴 수 있다.

5. Stablecoin에서 우선순위 높은 경고

표 자료가로 스크롤 · 크게 보기 지원
우선순위경고왜 중요한가
P0권한 없는 mint/burn 가능성supply 직접 손상
P0paused/frozen 상태 우회compliance와 incident response 실패
P0signature nonce 재사용중복 결제 또는 unauthorized transfer
P1reentrancy 가능한 refund/withdrawescrow 자금 중복 출금
P1proxy storage/upgrade 위험token accounting 또는 role 손상
P1unchecked token transfer return정산 실패를 성공으로 기록
P2단일 EOA adminkey compromise risk
P2unused/dead codeattack surface와 리뷰 비용 증가
크게 보기
우선순위경고왜 중요한가
P0권한 없는 mint/burn 가능성supply 직접 손상
P0paused/frozen 상태 우회compliance와 incident response 실패
P0signature nonce 재사용중복 결제 또는 unauthorized transfer
P1reentrancy 가능한 refund/withdrawescrow 자금 중복 출금
P1proxy storage/upgrade 위험token accounting 또는 role 손상
P1unchecked token transfer return정산 실패를 성공으로 기록
P2단일 EOA adminkey compromise risk
P2unused/dead codeattack surface와 리뷰 비용 증가

Priority는 도구 severity와 다를 수 있다. 예를 들어 어떤 detector가 medium이라도 merchant settlement 손실로 이어지면 release blocker다.

6. CI 실패 조건

표 자료가로 스크롤 · 크게 보기 지원
조건CI 결과사람의 다음 행동
새 high severity Slither findingfailtriage owner 지정
새 P0/P1 분류 findingfailfix 또는 release exception 승인
Echidna property 실패failsequence 저장, 최소 재현 test 작성
waiver 만료fail재검토 또는 owner 갱신
unreviewed medium finding 증가fail 또는 warningrelease meeting에서 triage
informational finding만 증가pass with reportbacklog 등록
크게 보기
조건CI 결과사람의 다음 행동
새 high severity Slither findingfailtriage owner 지정
새 P0/P1 분류 findingfailfix 또는 release exception 승인
Echidna property 실패failsequence 저장, 최소 재현 test 작성
waiver 만료fail재검토 또는 owner 갱신
unreviewed medium finding 증가fail 또는 warningrelease meeting에서 triage
informational finding만 증가pass with reportbacklog 등록

CI는 모든 보안 판단을 자동화하지 않는다. 대신 미검토 위험이 조용히 배포되는 것을 막는다.

7. 도구 결과를 release gate로 연결한다

흐름도가로 스크롤 · 크게 보기 지원
강의 흐름도상태, 책임, 검증 지점을 순서대로 읽기 위한 다이어그램이다.
크게 보기

이 흐름은 "도구를 한 번 돌렸다"는 체크박스를 release gate로 바꾼다. 보안 리뷰는 반복 루프다.

코드로 확인하기

앞의 보안 기준을 코드와 테스트로 확인한다. 함수가 어떤 전제를 세우고, 테스트가 어떤 실패 조건을 고정하는지 함께 읽는다.

운영Slither 기본 실행과 SARIF 출력

SARIF 형식으로 출력하면 GitHub Code Scanning이나 다른 SAST 대시보드에 그대로 올릴 수 있다. waive는 in-source NatSpec 또는 별도 yaml.

CODE SURFACEshell
# 단발 실행slither . --filter-paths "node_modules|lib"# CI용 SARIF 출력 + machine-readableslither . --sarif slither.sarif --filter-paths "node_modules|lib"# detector를 production 기준에 맞게 좁힌다slither . \  --detect reentrancy-eth,reentrancy-no-eth,arbitrary-send,uninitialized-state,unchecked-lowlevel \  --exclude-informational \  --fail-high \  --fail-medium

운영Slither .slither-config.json — waiver 관리

검토를 마친 finding은 reason과 owner를 붙여 waive한다. waiver는 임의로 두지 말고 만료일 코멘트와 함께 PR 리뷰 대상.

CODE SURFACEjson
{  "filter_paths": "node_modules|lib|test",  "exclude_dependencies": true,  "exclude_informational": true,  "fail_high": true,  "fail_medium": true}
CODE SURFACEsolidity
// slither-disable-next-line reentrancy-events// Reason: emit is intentional after CEI; reviewed 2026-05-15 by sec-team// Expires: 2026-08-15 — reassess on next auditemit PaymentRefunded(paymentId);

컨트랙트Echidna property — refund 멱등성

property는 contract 안에 echidna_ 접두사 함수로 작성한다. invariant 후보를 그대로 옮긴다.

CODE SURFACEsolidity
contract EchidnaPaymentProperties {    Checkout internal target;    bytes32 internal probeId = keccak256("probe");    constructor() {        target = new Checkout();        target.createInvoice(probeId, address(0xA11CE), address(0xB0B), token, 100);    }    // 같은 invoice를 두 번 refund 할 수 없다    function echidna_payment_refunded_only_once() public view returns (bool) {        (, , , , Checkout.Status status) = target.invoices(probeId);        // Refunded 까지 도달했다면 그 이후 어떤 호출에서도 동일 status 가 유지되어야 한다        return status != Checkout.Status.Refunded || target.refundCount(probeId) <= 1;    }}

운영Echidna 실행 + GitHub Actions에서 release gate

property 실패는 PR을 자동 차단한다. nightly에서는 더 긴 캠페인을 돌린다.

CODE SURFACEyaml
# .github/workflows/security.ymlname: securityon: [pull_request]jobs:  static-and-property:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4      - uses: foundry-rs/foundry-toolchain@v1      - name: Slither        run: |          pip install slither-analyzer          slither . --sarif slither.sarif      - name: Echidna        uses: crytic/echidna-action@v2        with:          files: src/Checkout.sol          contract: EchidnaPaymentProperties          test-limit: 20000          corpus-dir: corpus      - uses: actions/upload-artifact@v4        if: failure()        with:          name: echidna-corpus          path: corpus

강의 포인트

표 자료가로 스크롤 · 크게 보기 지원
관점강의 중 확인할 질문학습 후 남길 증거
도구 역할Slither/Echidna/Foundry/manual review가 각각 무엇을 맡는가?도구별 역할 분리표
Triagefinding을 impact와 release risk로 분류했는가?triage 템플릿
PropertyEchidna property가 business invariant를 담고 있는가?property 목록
CI새 finding과 failing property가 release gate를 막는가?CI 실패 조건
크게 보기
관점강의 중 확인할 질문학습 후 남길 증거
도구 역할Slither/Echidna/Foundry/manual review가 각각 무엇을 맡는가?도구별 역할 분리표
Triagefinding을 impact와 release risk로 분류했는가?triage 템플릿
PropertyEchidna property가 business invariant를 담고 있는가?property 목록
CI새 finding과 failing property가 release gate를 막는가?CI 실패 조건

실무 예시

운영[CONTRACT] 상황: Slither가 checkout contract의 refund 함수에서 reentrancy pattern을 경고했고, Echidna는 echidna_payment_idempotent()를 실패시켰다. 둘을 따로 보면 다른 경고처럼 보이지만, 실제로는 같은 위험을 가리킬 수 있다.

표 자료가로 스크롤 · 크게 보기 지원
신호해석조치
Slither reentrancy finding외부 token transfer 전후 상태 전이 위험refund CEI 검토
Echidna idempotency failure같은 payment가 두 번 refund될 수 있음failing sequence를 unit test로 승격
Settlement mismatch dashboard riskmerchant ledger 손상 가능release blocker로 분류
크게 보기
신호해석조치
Slither reentrancy finding외부 token transfer 전후 상태 전이 위험refund CEI 검토
Echidna idempotency failure같은 payment가 두 번 refund될 수 있음failing sequence를 unit test로 승격
Settlement mismatch dashboard riskmerchant ledger 손상 가능release blocker로 분류

이 예시는 도구를 함께 봐야 하는 이유다. Static finding은 코드 위치를 알려주고, property failure는 실제 상태 손상을 보여준다.

흔한 오해와 실패 시나리오

표 자료가로 스크롤 · 크게 보기 지원
오해실제로 확인할 것
Slither clean이면 안전하다고 본다.business logic invariant와 manual review가 필요하다.
Echidna property가 통과하면 충분하다고 본다.property가 약하면 아무것도 증명하지 못한다.
false positive는 삭제하면 된다고 본다.waiver owner, evidence, expiry가 필요하다.
CI는 security review를 대체한다고 본다.CI는 미검토 위험을 막는 gate이고 최종 판단은 triage다.
크게 보기
오해실제로 확인할 것
Slither clean이면 안전하다고 본다.business logic invariant와 manual review가 필요하다.
Echidna property가 통과하면 충분하다고 본다.property가 약하면 아무것도 증명하지 못한다.
false positive는 삭제하면 된다고 본다.waiver owner, evidence, expiry가 필요하다.
CI는 security review를 대체한다고 본다.CI는 미검토 위험을 막는 gate이고 최종 판단은 triage다.

실습 과제

  1. 운영도구별 역할 분리표 만들기: Slither, Echidna, Foundry, manual review가 각각 잘 잡는 것과 못 잡는 것을 stablecoin checkout 예시로 정리한다.
  2. 운영Slither/Echidna triage 템플릿 작성하기: detector/property, severity, confidence, impact, affected function, classification, owner, action, waiver expiry를 포함한 결과표를 만든다.
  3. 운영CI 실패 조건 정의하기: 새 high severity Slither finding, failing Echidna property, expired waiver, unreviewed medium finding이 각각 release gate에서 어떻게 처리되는지 정의한다.

완료 기준

  1. 두 도구의 역할을 설명했다.
  2. triage 템플릿을 만들었다.
  3. CI 실패 조건을 정의했다.
  4. false positive waiver에 owner와 만료일을 붙였다.

근거 자료

Final checkpoint

읽기를 마쳤다면 여기서 기록한다

아래 버튼은 읽기 진도를 저장한다. 체크리스트, 과제, 랩 산출물은 위 Workbook에서 따로 관리한다.

  • 두 도구의 역할을 설명했다.
  • triage 템플릿을 만들었다.
  • CI 실패 조건을 정의했다.

학습 자료 근거

보안도구 Slither Echidna
이 LMS 레슨의 개념, 예시, 과제 구성을 잡는 데 사용한 근거 문서.
내부 참고 문서
Slither Static Analyzer
https://github.com/crytic/slither
Slither Detector Documentation
https://github.com/crytic/slither/wiki/Detector-Documentation
Echidna Fuzzer
https://github.com/crytic/echidna
Foundry Book: Invariant Testing
https://book.getfoundry.sh/forge/invariant-testing