GitHub Action
GitHub Actions에서 OWASP Noir로 엔드포인트를 찾고 패시브 보안 스캔을 돌립니다.
CI에서 GitHub Actions로 OWASP Noir를 돌려 엔드포인트를 찾고, 원하면 패시브 보안 스캔도 함께 돌릴 수 있습니다.
빠른 시작
최소 워크플로:
name: Noir Security Analysis
on: [push, pull_request]
jobs:
noir-analysis:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run OWASP Noir
id: noir
uses: owasp-noir/noir@main
with:
base_path: '.'
- name: Display results
run: echo '${{ steps.noir.outputs.endpoints }}' | jq .
base_path: 분석 대상 디렉터리 (-b/--base-path)endpoints: 뒤 스텝에서 처리할 JSON 결과
입력값(Inputs)
| 이름 | 설명 | 필수 | 기본값 |
|---|---|---|---|
base_path |
분석할 기준 경로 (-b/--base-path) |
예 | . |
url |
엔드포인트의 기준 URL (-u/--url) |
아니오 | `` |
format |
출력 형식 (plain, yaml, json, jsonl, markdown-table, curl, httpie, oas2, oas3 등) |
아니오 | json |
output_file |
결과를 파일로 저장 (-o/--output) |
아니오 | `` |
techs |
추가할 기술 지정 (-t/--techs) |
아니오 | `` |
exclude_techs |
제외할 기술 지정 (--exclude-techs) |
아니오 | `` |
passive_scan |
패시브 보안 스캔 켜기 (-P/--passive-scan) |
아니오 | false |
passive_scan_severity |
패시브 스캔 최소 심각도 (critical, high, medium, low) |
아니오 | high |
use_all_taggers |
모든 태거 활성화 (-T/--use-all-taggers) |
아니오 | false |
use_taggers |
특정 태거만 활성화 (--use-taggers) |
아니오 | `` |
include_path |
plain 출력에 소스 파일 경로 추가. JSON에는 항상 들어 있음 (--include-path) |
아니오 | false |
verbose |
상세 출력 (--verbose) |
아니오 | false |
debug |
디버그 출력 (-d/--debug) |
아니오 | false |
concurrency |
동시성 수준 (--concurrency) |
아니오 | `` |
exclude_codes |
제외할 HTTP 상태 코드, 쉼표로 구분 (--exclude-codes) |
아니오 | `` |
status_codes |
발견한 엔드포인트의 HTTP 상태 코드 표시 (--status-codes) |
아니오 | false |
ai_provider |
AI 제공업체 접두사 또는 전체 커스텀 URL (--ai-provider) |
아니오 | `` |
ai_model |
AI 모델명 (--ai-model) |
아니오 | `` |
ai_key |
AI API 키 (--ai-key) |
아니오 | `` |
ai_agent |
에이전트형 AI 워크플로 켜기 (--ai-agent) |
아니오 | false |
probe |
발견한 엔드포인트로 HTTP 요청 보내기 (--probe) |
아니오 | false |
probe_via |
프로브 요청을 이 프록시 URL로 보내기 (--probe-via) |
아니오 | `` |
export_es |
Elasticsearch 또는 OpenSearch에 엔드포인트 색인 (--export-es) |
아니오 | `` |
export_webhook |
엔드포인트 목록을 JSON으로 웹훅 URL에 POST (--export-webhook) |
아니오 | `` |
diff_path |
diff 분석에 쓸 이전 버전 코드 경로 (--diff-path) |
아니오 | `` |
diff_ref |
체크아웃과 비교할 git 리비전(예: pull request의 base). 체크아웃에 없으면 가져옴 (--diff-ref) |
아니오 | `` |
fail_on |
diff에 added, removed, changed, auth-removed 중 하나라도 있으면 스텝 실패(종료 코드 3) (--fail-on) |
아니오 | `` |
no_log |
실행 로그를 숨기고 결과만 표시 (--no-log) |
아니오 | true |
참고:
- 불리언 옵션은 문자열(
'true'/'false')로 넘기세요. output_file은 워크스페이스 기준 경로입니다. 뒤 스텝에서 리포트 파일이 필요하면 지정하세요. 스텝 출력값은 지정 여부와 관계없이 채워집니다.status_codes,exclude_codes,probe,probe_via는url이 있어야 합니다. 없으면 스캔이 에러로 멈춥니다.jsonl이면 아래 출력값은 각 줄을 모아json과 같은 문서 하나로 만듭니다.
출력값(Outputs)
| 이름 | 설명 |
|---|---|
endpoints |
format이 json이나 jsonl일 때 Noir 결과 문서 전체({"endpoints":[...],"passive_results":[...],"errors":[...]}). 다른 출력 형식이면 빈 값 |
passive_results |
format이 json이나 jsonl일 때 패시브 스캔 결과 JSON 배열. 패시브 스캔을 껐거나, 결과가 없거나, 다른 출력 형식이면 [] |
출력값 활용:
- name: Count endpoints
run: echo '${{ steps.noir.outputs.endpoints }}' | jq '.endpoints | length'
- name: Show passive issues (if enabled)
run: echo '${{ steps.noir.outputs.passive_results }}' | jq '. | length'
예시
고급 스캔
name: Noir Passive Scan
on: [push, pull_request]
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Run OWASP Noir with Passive Scanning
id: noir
uses: owasp-noir/noir@main
with:
base_path: 'src'
format: 'json'
passive_scan: 'true'
passive_scan_severity: 'medium'
use_all_taggers: 'true'
verbose: 'true'
output_file: 'noir-results.json'
- name: Process Results
run: |
echo "Endpoints discovered:"
echo '${{ steps.noir.outputs.endpoints }}' | jq '.endpoints | length'
echo "Passive scan findings:"
echo '${{ steps.noir.outputs.passive_results }}' | jq '. | length'
- name: Save detailed results
uses: actions/upload-artifact@v4
with:
name: noir-security-results
path: noir-results.json
모노레포 매트릭스
name: Monorepo Noir
on: [push, pull_request]
jobs:
noir:
runs-on: ubuntu-latest
strategy:
matrix:
service: [service-a, service-b, service-c]
steps:
- uses: actions/checkout@v6
- name: Run Noir for ${{ matrix.service }}
id: noir
uses: owasp-noir/noir@main
with:
base_path: '${{ matrix.service }}'
format: 'json'
Pull Request 공격 표면 리뷰
풀 리퀘스트를 기준 브랜치와 비교해 결과를 코멘트로 남기고, 인증이 빠진 라우트가 생기면 체크를 실패시킵니다.
name: Attack Surface Review
on: pull_request
permissions:
contents: read
pull-requests: write
jobs:
noir-diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Diff the attack surface
uses: owasp-noir/noir@main
with:
base_path: '.'
diff_ref: ${{ github.event.pull_request.base.sha }}
format: 'markdown-table'
output_file: 'noir-diff.md'
fail_on: 'auth-removed'
- name: Comment on the pull request
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: gh pr comment "${{ github.event.pull_request.number }}" --body-file noir-diff.md
actions/checkout은 기본으로 커밋 하나만 가져옵니다. diff_ref가 체크아웃에 없으면 Action이 스캔 전에 그 리비전을 가져옵니다. diff가 fail_on에 걸리면 스텝은 종료 코드 3으로 실패하지만 리포트 파일은 그대로 쓰이므로, 위 코멘트 스텝은 if: always()로 실행됩니다. 코멘트 대신 코드 줄에 바로 표시하려면 format: 'sarif'로 출력하고 github/codeql-action/upload-sarif로 업로드하세요.
프레임워크별 스캔
- uses: owasp-noir/noir@main
with:
base_path: '.'
techs: 'rails' # ruby on rails
passive_scan: 'true'
- uses: owasp-noir/noir@main
with:
base_path: 'src'
techs: 'express' # node.js express
format: 'json'
- uses: owasp-noir/noir@main
with:
base_path: '.'
techs: 'django' # python django
passive_scan: 'true'
passive_scan_severity: 'medium'
상태 코드 설정
상태 코드는 실제 요청으로 얻으므로 url이 실행 중인 앱을 가리켜야 합니다.
- uses: owasp-noir/noir@main
with:
base_path: '.'
url: 'http://localhost:3000'
status_codes: 'true' # HTTP 상태 코드 포함
exclude_codes: '404,429' # 노이즈가 많은 코드 제외
다른 출력 형식
- uses: owasp-noir/noir@main
with:
base_path: '.'
format: 'markdown-table' # 또는: 'curl', 'httpie', 'yaml', 'jsonl', 'oas3'
output_file: 'noir.md'
모범 사례
passive_scan: 'true'로 보안 문제를 일찍 잡으세요.passive_scan_severity와exclude_codes로 노이즈를 줄이세요.- JSON 출력에는 엔드포인트마다 소스 파일 위치가 이미 들어 있습니다.
plain출력에서 보려면include_path: 'true'를 켜세요. - 자동 탐지가 놓친 프레임워크는
techs로 추가하고, 필요 없는 분석기는exclude_techs로 빼세요. actions/upload-artifact로 결과를 보관하세요.
트러블슈팅
엔드포인트가 나오지 않을 때:
base_path가 소스 디렉터리를 가리키는지 확인- 저장소가 지원하는 프레임워크를 쓰는지 확인
techs를 직접 지정
출력이 크거나 느린 경우:
format: 'jsonl'로output_file에 저장 (한 줄에 엔드포인트 하나)base_path범위를 줄이거나techs/exclude_techs로 거르기
진단이 어려운 경우:
debug: 'true'나verbose: 'true'를 켜고no_log: 'false'도 함께 지정.no_log는 기본값이true라 로그를 숨깁니다
HTTP 상태 코드 노이즈:
status_codes: 'false'로 비활성화 또는exclude_codes로 제외
구현 참고 사항
- Action은
ghcr.io/owasp-noir/noirDocker 이미지로 실행됩니다. 이미지 태그는 고정한 ref를 따릅니다.@v1.4.0은1.4.0,@main은main, 커밋 SHA는latest를 씁니다. 태그를 받을 수 없으면(예: 이미지가 없는 브랜치) 경고를 남기고latest로 대신 실행합니다. - 입력값 하나가 CLI 플래그 하나에 대응합니다.
- 지원 기술 목록:
noir list techs