Hostveil / 문서 / CLI 레퍼런스

CLI 레퍼런스

모든 하위 명령, 플래그, 기본값입니다. root 소유 파일(SSH, 방화벽)을 읽거나 보호된 경로에 쓰는 명령은 root 권한이 필요하므로, hostveil은 (version/help를 제외하고) sudo 아래에서 자동으로 자신을 다시 실행합니다. 이를 원하지 않으면 HOSTVEIL_NO_SUDO=1을 설정하세요.

개요

hostveil <command> [flags]

대화형 터미널에서 명령 없이 실행하면 Hostveil은 TUI를 엽니다. stdin/stdout이 터미널이 아니면 대신 scan을 실행합니다. hostveil version(또는 --version)은 버전을 출력하고, hostveil help(또는 --help)는 사용법을 출력합니다.

scan

호스트를 스캔하고 보안 발견 항목을 보고합니다.

hostveil scan [flags]
플래그기본값설명
--jsonfalse보고서를 JSON으로 출력합니다.
--sariffalse보고서를 CI 시스템과 GitHub code scanning이 읽는 SARIF 2.1.0 형식으로 출력합니다. --json과 함께 쓸 수 없습니다. 도메인별 커버리지가 run 속성에 함께 실리므로, 일부만 점검된 스캔은 내보내기에서도 그대로 보입니다.
--output FILE선택한 형식 그대로 보고서를 stdout 대신 파일에 씁니다. 종료 코드는 그대로이므로 CI 게이트는 계속 동작합니다.
--only LIST지정한 도메인만 스캔합니다. 쉼표로 구분합니다 (예: --only ssh,firewall). 스캔하지 않은 도메인은 100이 아니라 N/A로 표시됩니다. 부분 스캔은 마지막 스캔 기준선으로 저장되지 않고 변화 요약도 만들지 않습니다 — 저장하면 다음 전체 스캔이 건너뛴 도메인의 모든 발견 항목을 새로 생긴 것으로 보고하게 됩니다.
--skip LIST지정한 도메인을 제외한 모든 도메인을 스캔합니다. --only와 함께 쓸 수 없으며, 같은 부분 스캔 규칙이 적용됩니다.
--glyphs NAME기억된 값, 없으면 plain상태 표시에 쓸 기호 세트입니다: plain 또는 nerd. nerd는 패치된 Nerd Font의 글리프를 씁니다 — 폰트를 설치하고 HOSTVEIL_GLYPHS=nerd를 한 번 설정하세요. 터미널에 어떤 폰트를 쓰는지 물어볼 방법이 없어서 자동 감지가 아니라 명시적 선택이며, 기본값은 아무것도 바꾸지 않습니다.
--verbose, -vfalse설명과 수정 안내를 표시합니다.
--no-colorfalse색상 출력을 비활성화합니다.

종료 코드: 수정되지 않은 발견 항목 중 HIGH가 있으면 1, 탐지 영역이 아예 실패했으면 3, 그렇지 않으면 0입니다 — 종료 코드를 참고하세요. 색상은 터미널에만 출력되며 NO_COLOR가 설정되면 억제됩니다.

--json의 모양

열거형 필드는 모두 숫자가 아니라 소문자 이름입니다:

{
  "findings": [
    {
      "id": "ssh.rootlogin",
      "title": "SSH permits root login with a password",
      "severity": "high",
      "source": "ssh",
      "remediation": "review"
    }
  ],
  "domains": [
    {"source": "ssh", "state": "done", "finding_count": 5},
    {"source": "cve", "state": "skipped", "reason": "trivy is not installed"}
  ]
}

severityhigh, medium, low 중 하나입니다. remediationauto, review, manual, unavailable 중 하나입니다. source는 도메인 이름이며 발견 항목 ID의 접두사와 같습니다. statedone, degraded, skipped, error 중 하나입니다 — done이 아닌 도메인은 "아무것도 없다"와 "볼 수 없었다"를 가르는 지점이므로, 결과가 비었다고 깨끗한 호스트로 취급하기 전에 반드시 확인하세요.

발견 항목에는 fixed도 실리고, 같은 실행에서 무언가를 적용했다면 pending도 실립니다. fixed는 Hostveil이 이 항목에 수정을 적용했다는 뜻이고, pending은 호스트가 그 수정을 아직 읽지 않았다는 뜻입니다. 그래서 이 항목은 점수에서 계속 감점되고 종료 코드에도 그대로 반영됩니다. 위험이 아직 서 있는지 판단하려는 소비자는 fixed만 볼 것이 아니라 fixed && !pending을 읽어야 합니다. 둘 다 거짓이면 생략되며, 새로 스캔하면 남지 않습니다 — 스캔은 모든 것을 점검기 결과로 다시 만들기 때문입니다.

3.11에서 변경

이 필드들은 예전에는 정수였고, 그래서 소비하는 쪽마다 순서표를 따로 들고 있어야 했습니다. Hostveil은 정수 형식을 읽기는 계속 하므로 이전 버전이 남긴 스캔 스냅샷은 그대로 살아 있지만, 쓸 때는 이름만 씁니다.

SARIF로 내보낼 때 심각도는 어떻게 되나

SARIF의 등급도 셋이고 Hostveil의 심각도도 셋이라 일대일로 대응합니다.

HostveilSARIF levelGitHub security-severity
higherror9.5
mediumwarning5.5
lownote3.0

두 번째 숫자는 GitHub code scanning이 정렬과 필터에 쓰는 0에서 10 사이의 척도입니다. 구간이 critical 9.0, high 7.0, medium 4.0에서 시작하므로 Hostveil의 High는 GitHub의 high가 아니라 critical 구간에 뜹니다.

이름이 어긋나는 것은 의도한 것입니다. Hostveil의 최상위 등급은 아무것도 갖지 않은 사람이 호스트 밖에서 지금 당장 닿을 수 있다는 뜻이고, code scanning에서 오늘 처리하라는 뜻의 구간은 critical입니다. 이름을 이름에 맞췄다면 그 항목들이 다음 스프린트에 볼 구간으로 내려갔을 겁니다.

fix

발견 항목에 대한 수정을 미리 보고 적용합니다.

hostveil fix <finding-id> [flags]
hostveil fix --all [flags]
플래그기본값설명
--allfalse안전한(Auto-fix) 발견 항목을 모두 한 번에 적용합니다.
--reviewfalse--all과 함께 쓰면 Review 수정도 각 항목의 첫 번째 대안으로 함께 적용합니다. 목록과 개수는 따로 표시됩니다: Review 수정은 Hostveil이 할 수는 있지만 무인으로는 하지 않는 것들로, 이 호스트에 대한 접근을 끊을 수 있거나 되돌릴 체크포인트가 없는 명령을 실행합니다.
--action N-1Review 수정에서 적용할, 0부터 시작하는 대안의 번호입니다.
--service NAME""서비스 이름으로 발견 항목을 구분합니다.
--yesfalse대화형 확인 없이 적용합니다.

적용 시에는 항상 diff/명령을 먼저 보여 주고, 원본을 체크포인트로 백업한 뒤 적용합니다. 수정 및 롤백을 참고하세요.

rollback

이전에 적용한 수정을 되돌립니다.

hostveil rollback <checkpoint-id> [--force]
플래그기본값설명
--forcefalse수정 적용 이후 파일이 바뀌었더라도 복원합니다.

(hostveil history에서 얻은) 체크포인트 ID 하나를 받아 백업된 파일을 바이트 단위 그대로 복원합니다. 파일이 수정이 써 넣은 내용과 더 이상 일치하지 않으면, 롤백은 그 뒤의 편집을 버리는 대신 거부하고 종료 코드 1을 반환합니다 — 롤백이 거부할 때를 참고하세요.

history

적용된 수정과 그 롤백 ID를 나열합니다.

hostveil history
hostveil history --scans

체크포인트를 최신순으로 나열하며, 타임스탬프, 발견 항목 ID, 레이블, 그리고 정확한 hostveil rollback <id> 명령 또는 되돌릴 수 없음 표시가 함께 나옵니다.

플래그동작
--scans적용된 수정 이력 대신, 보관된 모든 스캔의 점수를 오래된 순으로 보여 주고 직전 스캔 대비 변화를 함께 표시합니다. Hostveil은 최근 30개 스캔을 보관합니다. 어떤 영역도 확인하지 못한 스캔은 숫자가 아니라 N/A로 표시되고 변화도 계산하지 않습니다 — 아무도 채점할 수 없었던 실행은 0점으로 떨어진 것이 아니기 때문입니다.

SSH로 접속했을 때

대시보드는 루프백에서만 듣기 때문에 출력되는 주소는 서버 쪽 주소입니다. 노트북 브라우저에 그대로 치면 노트북에 닿습니다. hostveil serve는 SSH 세션임을 알아채면, 클라이언트가 실제로 닿은 주소를 써서 본인 기기에서 실행할 포워딩 명령을 함께 출력합니다.

ssh -N -L 8787:127.0.0.1:8787 you@10.0.0.2

그것을 띄워 둔 채로 본인 기기에서 출력된 URL을 엽니다. 대신 대시보드를 외부에 노출되는 주소로 바인딩하도록 권하지는 않습니다. 이 대시보드의 모든 경로는 root 권한으로 조치를 적용하거나 /etc/shadow를 읽은 스캔 결과를 다루고, 포워딩된 포트는 인증이 이미 끝난 같은 접근이기 때문입니다.

diagnostics

버그 리포트에 필요한 정보를 파일 하나로 모아 줍니다. 네트워크에는 전혀 닿지 않습니다. 전송 기능 자체가 없고, 결과를 이슈에 붙여넣는 것은 운영자의 몫입니다.

hostveil diagnostics [flags]

리포트에는 hostveil 버전, 호스트의 배포판과 플랫폼, 기록된 크래시 트레이스, 그리고 마지막으로 저장된 스캔의 점수·영역 상태·발견 항목 ID와 심각도가 담깁니다. 발견 항목의 설명, 조치 방법, 근거는 담기지 않습니다. 운영자가 도움을 요청하려는 바로 그 설정을 인용할 수 있는 정보이기 때문입니다.

플래그기본값설명
--trace FILE""HOSTVEIL_DEBUG=1로 만든 명령 트레이스를 첨부합니다.
--unredactedfalseIP 주소와 홈 디렉터리 사용자 이름을 가리지 않습니다. 로컬에서만 쓰는 용도입니다.
--output FILE""리포트를 출력하는 대신 파일로 씁니다.

리포트를 출력할 때 어디에 붙여넣으면 되는지도 함께 알려 줍니다: https://github.com/seolcu/hostveil/issues/new. 이 명령 자체는 네트워크에 닿지 않으며, 실제로 닿는 경로는 환경 변수 문서에 정리되어 있습니다.

explain

발견 항목을 쉬운 말로 설명합니다.

hostveil explain <finding-id> [flags]
플래그기본값설명
--aifalse조언성 AI 설명을 덧붙입니다. 기본은 로컬 Ollama이며, 외부 API를 쓰려면 HOSTVEIL_AI_PROVIDER를 설정하세요.
--service NAME""서비스 이름으로 발견 항목을 구분합니다.

내장된 쉬운 말 설명은 항상 출력되며, --ai는 조언 섹션을 추가합니다. AI 설명을 참고하세요.

export

호스트를 스캔하고 결과를 다섯 가지 형식 중 하나로 내보냅니다. json과 sarif는 scan --json/--sarif와 완전히 같은 결과물로, 다른 프로그램이 읽기 위한 형식입니다. markdown, docx, pdf는 각 발견 항목과 그 수정 방법을 쉬운 말로 설명합니다. 결과를 직접 읽거나 동료에게 전달할 때 쓰는 형식입니다.

hostveil export --format FMT [flags]
플래그기본값설명
--format FMT필수입니다. json, sarif, markdown, docx, pdf 중 하나입니다.
--output FILE표준 출력 대신 FILE에 씁니다. docxpdf는 필수입니다. 터미널에서는 이진 형식을 보여줄 방법이 없기 때문입니다.
--only LIST이 도메인만 스캔합니다(쉼표로 구분). 스캔하지 않은 도메인은 100이 아니라 N/A로 표시됩니다.
--skip LIST나열한 도메인만 제외하고 스캔합니다(쉼표로 구분). --only와 함께 쓸 수 없습니다.

종료 코드는 scan과 같은 게이트를 따릅니다. 종료 코드를 참고하세요.

advise

호스트를 스캔하고 등록된 Fix가 있는 모든 발견 항목을, 그 Fix를 적용하면 얻는 것과 치르는 대가와 함께 나열합니다. --ai를 주면 ai-context로 저장해 둔 호스트 설명(있다면)에 비추어 적용/보류/상황에 따라 다름 중 하나의 판단도 덧붙입니다. AI 설명을 참고하세요.

hostveil advise [--ai] [flags]
플래그기본값설명
--aifalse발견 항목마다 AI 판단을 덧붙입니다. 기본은 로컬 Ollama이며, 외부 API를 쓰려면 HOSTVEIL_AI_PROVIDER를 설정하세요.
--only LIST이 도메인만 스캔합니다(쉼표로 구분).
--skip LIST나열한 도메인만 제외하고 스캔합니다(쉼표로 구분). --only와 함께 쓸 수 없습니다.

결정론적 목록은 AI 없이도 항상 출력됩니다. --ai는 그 아래에 상황별 판단을 덧붙이거나, 덧붙이지 못한 이유를 말합니다.

ai-context

이 호스트를 한 줄로 설명한 문구를 보여주거나, 저장하거나, 지웁니다. "개인 미디어 서버, 안정성보다 최신 보안 패치가 중요함" 같은 문구입니다. explain --aiadvise --ai는 이 설명을 읽어 Fix를 추상적으로가 아니라 이 호스트에 맞춰 판단합니다. hostveil이 상태를 저장하는 것과 같은 디렉터리에 남아 있으며, 바꾸거나 지우기 전까지 계속 쓰입니다.

hostveil ai-context               # 현재 설명을 보여줌
hostveil ai-context "TEXT"        # 설명을 저장함
hostveil ai-context --clear       # 설명을 지움
플래그기본값설명
--clearfalse저장된 설명을 보여주는 대신 지웁니다.

serve

localhost 웹 대시보드를 실행합니다. hostveil web은 별칭입니다.

hostveil serve [--addr ADDR] [--theme NAME] [--layout NAME]
플래그기본값설명
--addr ADDR127.0.0.1:8787대시보드를 바인딩할 주소입니다.
--theme NAME기억된 값, 없으면 onedark대시보드가 처음 표시될 색상 테마입니다.
--layout NAME기억된 값, 없으면 console대시보드가 처음 표시될 화면 배치입니다. 브라우저의 선택기로 고른 값은 그 브라우저에 저장되어 이 값을 이깁니다. 따라서 이 옵션은 아직 아무것도 고르지 않은 브라우저가 보게 될 배치를 정합니다.

이 명령은 일회용 접근 토큰이 포함된 URL을 출력합니다 — 주소만 입력하지 말고 그 URL을 그대로 여세요. loopback은 운영자와 다른 로컬 계정을 구분해 주지 않고 대시보드는 root로 실행되므로, 모든 경로가 토큰을 요구합니다.

대시보드는 localhost로 향한 요청에만 응답하므로 --addr로는 네트워크에 공개할 수 없습니다 — 루프백이 아닌 주소로 바인딩하면 이 머신을 IP나 호스트 이름으로 찾아온 요청은 거부하며, Hostveil이 이를 알려 줍니다. 포트 포워딩으로 접근하면 그대로 동작합니다 — 브라우저는 어느 쪽이든 localhost로 요청하기 때문입니다. 원격 접근에는 ssh -L 8787:127.0.0.1:8787 you@server를 쓰세요.

tui

대화형 터미널 UI를 엽니다(터미널에서 명령 없이 실행할 때의 기본값이기도 합니다).

hostveil tui [--theme NAME] [--layout NAME] [--glyphs NAME]
플래그기본값설명
--theme NAME기억된 값, 없으면 onedark색상 테마: onedark, gruvbox, nord, catppuccin, tokyonight.
--layout NAME기억된 값, 없으면 console화면 배치입니다: console, split, triage, railverdict, lanes, inline. TUI 안에서 l을 누르면 바꿀 수 있고 그 선택을 기억합니다. 우선순위는 이 플래그 > HOSTVEIL_LAYOUT > 기억된 값 > console입니다.
--glyphs NAME기억된 값, 없으면 plain상태 표시에 쓸 기호 세트입니다: plain 또는 nerd. nerd는 패치된 Nerd Font의 글리프를 씁니다 — 폰트를 설치하고 HOSTVEIL_GLYPHS=nerd를 한 번 설정하세요. 터미널에 어떤 폰트를 쓰는지 물어볼 방법이 없어서 자동 감지가 아니라 명시적 선택이며, 기본값은 아무것도 바꾸지 않습니다.

대화형 터미널이 필요하며, 그렇지 않으면 hostveil scan을 사용하라고 안내합니다. TUI 안에서 t를 누르면 테마를 고르고 기억시킬 수 있습니다 — 인터페이스를 참고하세요.

종료 코드

코드의미
0성공(scan의 경우, 수정되지 않은 HIGH 발견 항목이 없음).
1scan이 수정되지 않은 HIGH 발견 항목을 찾았거나, 명령이 실패했습니다.
2사용법 오류 — 알 수 없는 명령이거나 필수 인자가 누락되었습니다.
3scan 중 탐지 도메인이 완전히 실패해, 호스트를 검사해야 할 범위보다 좁게 검사했습니다. 의존성이 없어 건너뛴 도메인이나 부분 커버리지로 강등된 도메인은 여기에 해당하지 않으며, 둘 다 출력에 표시됩니다.

update

Hostveil을 최신 릴리스로 업데이트합니다.

hostveil update
hostveil update --check

이 바이너리가 어떻게 설치됐는지 확인해 같은 방식으로 업데이트합니다. 호스트에 무엇이 있는지를 두고 서로 다른 말을 하는 도구가 생기지 않도록 하기 위해서입니다.

설치 방식update가 하는 일
설치 스크립트릴리스 아카이브를 받아 바이너리를 제자리에서 교체합니다.
.deb릴리스의 .deb을 받아 apt-get으로 설치합니다. dpkg가 파일시스템을 계속 정확히 기술하도록.
.rpm같은 방식으로 dnf를 씁니다.
go installGo 툴체인으로 소스에서 다시 빌드합니다. 직접 빌드한 바이너리를 배포본으로 바꿔치우면 그 빌드를 말없이 버리는 셈입니다.

검증은 선택이 아닙니다. 받은 파일을 릴리스의 체크섬 파일과 대조해 맞지 않으면 버리고, GitHub CLI가 있으면 서명된 빌드 프로버넌스도 검증합니다. 프로버넌스 검증이 실패하면 업데이트를 중단하고, gh가 없어서 검증을 못 한 경우는 안내로 끝냅니다. 체크섬은 바이트가 온전히 도착했다는 것만 증명하고 누가 만들었는지는 말해 주지 않기 때문입니다.

설치 방식을 알아낼 수 없으면 아무것도 하지 않고 그 사실을 알립니다. 거기서 추측하는 것은 다른 도구가 자기 것이라고 믿는 파일을 덮어쓰는 일입니다.

플래그하는 일
--check새 버전이 있는지만 알리고 설치하지 않습니다. 종료 코드 10이면 업데이트가 있고 0이면 최신이라, cron 작업이 문장을 읽지 않고 분기할 수 있습니다.
--yes설치 전에 묻지 않습니다.

하루 한 번 확인

스캔, 대시보드, TUI는 각각 하루에 한 번 GitHub에 새 릴리스가 있는지 묻고, 있으면 한 줄로 알립니다. 요청은 백그라운드에서 돌기 때문에 아무것도 그것을 기다리지 않으며, 실패해도 아무 말을 하지 않습니다. 프록시 뒤에 있는 호스트는 Hostveil이 보고할 문제를 가진 호스트가 아닙니다.

이 줄은 --json, SARIF, --output으로 파일에 쓴 보고서에는 절대 실리지 않습니다. 그것들은 기계가, 나중에 읽습니다.

Hostveil은 스스로 무언가를 설치하지 않습니다. HOSTVEIL_NO_UPDATE_CHECK=1을 설정하면 hostveil update를 직접 실행할 때를 빼고는 GitHub에 연결하지 않습니다.

uninstall

설치할 때 쓴 도구로 Hostveil을 제거합니다.

hostveil uninstall

패키지로 설치했다면 apt-get removednf remove로 제거하고, 그 외에는 바이너리를 지웁니다.

저장된 스캔 기록과 롤백 체크포인트는 건드리지 않으며, 묻기 전에 그 위치를 먼저 알려 줍니다. 그 체크포인트는 이 호스트에서 Hostveil이 고친 모든 파일의 백업이라, 프로그램을 지운다는 것이 그 작업을 되돌릴 능력까지 버릴 이유는 되지 않습니다. 확신이 서면 직접 지우세요.

플래그하는 일
--yes제거 전에 묻지 않습니다.