레퍼런스

gori 쿼리 언어

gori에는 플로우를 걸러내는 작은 쿼리 언어(QL)가 있습니다. 같은 문법이 TUI 필터 바, gori run(-q/--query 또는 위치 인자), 그리고 MCP 도구에서 동일하게 동작합니다. 내장 레퍼런스는 TUI Help의 Query 페이지와 ql_reference MCP 도구로도 볼 수 있습니다.

필드

field:value로 필드를 매칭합니다(필드에 따라 부분 문자열 또는 완전 일치):

필드 매칭 대상
host 요청 호스트
path 요청 경로와 쿼리 문자열. 그래서 -path:x는 ?q=x도 걸러 냅니다
url 전체 URL
method HTTP 메서드
scheme http / https
proto 프로토콜: http, ws, grpc, sse. TLS 쪽은 s를 붙입니다(https, wss, grpcs, sses). websocket은 ws의 별칭입니다
src 이 플로우가 어디서 왔는지(아래)
via tui / cli / mcp. 어느 gori 진입점이 보냈는지(아래)
status 응답 상태 코드
size 요청 + 응답 전체 바이트
reqsize / respsize 각 방향의 바이트 수
dur 응답 시간(밀리초)
header 헤드(요청 + 응답 헤더) 부분 문자열
body 본문 전문 검색(trigram FTS 인덱스)
ws 소켓이 값을 담은 TEXT 또는 BINARY 메시지를 주고받은 WebSocket 플로우, 방향 무관(아래)
rpc 요청 본문이 값으로 시작하는 메서드를 부르는 JSON-RPC 호출(MCP 포함)인 플로우(아래)
stub true / false. 원본 서버를 거치지 않고 gori가 short-circuit 규칙으로 직접 답한 플로우
rewritten true / false, 또는 규칙 하나를 project/4 / global/3로. Match & Replace 규칙이 바꾼 플로우. 매칭됐지만 아무것도 바꾸지 않은 규칙은 기록되지 않고, gori가 규칙을 기록하기 전에 캡처한 플로우는 true에도 규칙에도 걸리지 않습니다
static true / false. 이미지, 폰트, 오디오·비디오. 응답 Content-Type으로 판단하고, 없으면 경로 확장자를 봅니다. SVG·CSS·JS와 이미지 프록시(?url=)는 제외하고, 성공한 응답(2xx 또는 304)만 해당합니다. -static:true가 정적 에셋 숨기기 렌즈입니다
scope in / out. 프로젝트 스코프 규칙(아래)
cache hit / miss / dynamic / none: 응답의 캐시 헤더(Age, X-Cache, CF-Cache-Status, Cache-Status 등)에서 읽은 캐시 판정. none도 실제 값입니다(판정 없음, 대기 중인 플로우 포함). cache: 쿼리를 쓰면 History에 CACHE 열이 붙습니다
host:example.com
method:POST
status:404

한쪽 방향만 보기: req. / resp.

header:와 body:는 요청과 응답을 모두 뒤집니다. 한쪽만 보려면 req. 또는 resp.를 앞에 붙입니다.

필드 뜻
req.body / resp.body 그 방향의 본문만
req.header / resp.header 그 방향의 헤드만
resp.body:secrettoken                 응답 본문에만 들어있는 토큰
resp.header:set-cookie                쿠키를 내려주는 응답
-resp.body:abcd                       응답 본문에 abcd가 없는 것
req.body~(?i)password                 요청 본문 정규식(한쪽만)
NOT (req.body:token OR resp.body:token)

res.는 resp.의 동의어이고, req.size / resp.size는 reqsize / respsize와 같습니다. 방향이 하나뿐인 필드(host, method, status 등)에는 접두사를 붙이지 않습니다.

출처: src:

src:는 요청을 실제로 보낸 주체로 플로우를 고릅니다. src:proxy는 클라이언트가 gori를 거쳐 보낸 트래픽이고, 나머지 값은 gori 자신이 만든 요청입니다. src:import는 다른 도구가 남긴 캡처를 읽어 들인 것입니다.

값 매칭 대상
proxy 캡처 프록시가 중계한 클라이언트의 요청. 평범한 캡처 트래픽
repeater Repeater 전송(TUI, gori run repeater send --record-history, MCP send_request)
fuzzer --record-history / record_history로 기록된 퍼즈 결과
discover 크롤러가 가져온 것(Discover는 기본으로 저장합니다)
retest Issue 리테스트의 한 단계(gori run retest run, MCP run_retest, TUI의 RETEST 카드). repeater와 별도 값입니다. 사람이 직접 보낸 요청과 gori가 실행한 검사의 한 단계는 같은 바이트에 대한 다른 사실이기 때문입니다
refresh 세션 슬롯 갱신의 한 단계. 수동이든 전송 직전 자동이든 같습니다(source_ref에 slot NAME step N). RFRSH로 표시됩니다
macro Fuzzer나 Miner 실행의 요청 시점 매크로가 후보 앞에서 실행한 한 단계(source_ref에 macro step N). MACRO로 표시됩니다
miner, sequencer, authorize, probe 예약됨. 아직 플로우를 기록하지 않는 도구들
import HAR, Burp export, --urls, OpenAPI 문서에서 읽어 들인 것
gori gori가 보낸 모든 출처. 가운데 행들의 합집합이며 import는 포함하지 않습니다
src:proxy                             실제로 일어난 트래픽만 History로 읽기
-src:proxy                            gori가 넣은 것 전부
src:gori                              …같은 집합을 긍정형으로
src:repeater status:200               내가 다시 보낸 것 중 200으로 돌아온 것
src:fuzzer resp.body:root:            퍼즈 히트. 내 페이로드를 발견으로 착각하지 않도록

History의 SRC 열은 이 값들을 짧은 태그로 찍습니다(PROXY, RPTR, FUZZ, CRAWL, IMPRT …). src:는 그 태그도 받으므로 src:rptr과 src:repeater는 같은 쿼리입니다. source:는 src:의 긴 철자로 함께 받습니다.

두 가지는 의도된 동작입니다:

  • 가져온(import) 플로우는 src:gori가 아닙니다. gori가 그것을 전송한 적이 없고, 다른 사람이 캡처한 실제 엔드포인트를 설명할 뿐입니다. -src:proxy에는 걸리고 src:gori에는 걸리지 않습니다.
  • 출처를 기록하기 전에 캡처된 플로우는 양쪽 어디에도 걸리지 않습니다. 그 행들은 출처를 전혀 갖고 있지 않습니다. 컬럼이 생기기 전에도 gori는 이미 Repeater 전송·크롤·import를 History에 쓰고 있었으므로, 그것들을 proxy로 채우는 것은 어떤 캡처도 만들지 않은 사실을 지어내는 일이 됩니다. SRC 열에는 —가 뜨고 src:proxy와 -src:proxy 양쪽 모두 이 행을 건너뜁니다. Pending 플로우가 status:와 -status: 양쪽에서 빠지는 것과 같습니다. 업그레이드 이후에 캡처된 플로우만 이 값을 가집니다.

src:로 흔히 하는 두 가지 좁히기는 뷰로도 준비돼 있습니다. History에서 v를 눌러 History(src:proxy)나 History + Repeater를 고르면, 다른 필터를 입력하는 동안에도 목록이 계속 좁혀진 채로 있습니다. 프로젝트는 History + Repeater로 열립니다. 뷰를 보세요.

진입점: via:

src:는 어떤 도구가 보냈는지를, via:는 어느 gori 진입점이 움직였는지를 말합니다: tui, cli (gori run), mcp(에이전트). MCP send_request는 Repeater 탭에서 보낸 것과 똑같이 src:repeater로 기록되므로, 둘을 가르는 것이 via:입니다.

via:mcp                               에이전트가 보내거나 가져온 것 전부
src:repeater via:tui                  내가 손으로 다시 보낸 것만
-via:mcp                              에이전트가 보내거나 가져오지 않은 것 전부(캡처 포함)

프록시 캡처에는 진입점이 없으므로 어떤 via: 값에도 걸리지 않고, 부정형에는 늘 남습니다. gori가 진입점을 기록하기 전에 보낸 플로우도 마찬가지입니다.

스코프: scope:in / scope:out

scope:in은 프로젝트 스코프 안쪽의 플로우를 고릅니다. TUI의 s 렌즈와 gori run history --in-scope가 적용하는 그 include/exclude 경계와 완전히 같은 것입니다. scope:out은 그 바깥을 고릅니다. 보통 항목이므로 부정할 수도, 괄호로 묶을 수도 있습니다:

scope:in status:5xx                   타깃에서 난 서버 에러
scope:out -host:cdn                   스코프 밖으로 새어 나간 트래픽, CDN 제외
(scope:in OR host:staging.example.com) method:POST

의도된 성질이 세 가지 있습니다.

  • s 렌즈가 켜졌는지와 무관합니다. 필터 항목은 모드가 아니라 질문이므로 scope:in은 어느 쪽이든 같은 뜻입니다. (렌즈가 켜져 있으면 렌즈가 이미 같은 조건을 AND로 걸기 때문에 scope:in은 중복이 되고, scope:out은 아무것도 매치하지 않습니다. 렌즈가 스코프 밖의 행을 이미 모두 걸러냈기 때문입니다.)
  • 스코프 규칙이 하나도 없으면 두 표기 모두 아무것도 매치하지 않습니다. 스코프 안에 든 것이 없으니 질문에 답이 없고, 그래서 묻지 않습니다. 특히 그 상태에서 scope:out은 "전체"를 뜻하지 않습니다. 같은 이유로, never-match를 부정한 -scope:in은 그 상태에서 scope:out과 같지 않습니다. ql_explain은 scope_rules_configured: false와 경고를 함께 돌려주고, gori run history delete는 답할 스코프가 없는 항목 하나로 프로젝트 히스토리를 지우지 않도록 스코프 쿼리를 아예 거부합니다.
  • scope:는 플로우 단위입니다. 그래서 Sitemap에서는 gori run sitemap --in-scope와 다릅니다. 그쪽은 호스트 단위(트래픽 중 하나라도 스코프 안이면 그 호스트를 남김)이므로, scope:in 쿼리는 호스트는 남기면서 그 호스트의 일부 엔드포인트만 떨어뜨릴 수 있습니다.

캡처는 어느 쪽으로도 영향을 받지 않습니다. gori는 언제나 전부 기록하고, 이것은 쿼리가 돌려주는 범위만 좁힙니다.

상태 클래스

status:는 클래스 약어를 받습니다:

status:2xx      status:4xx      status:5xx

비교

숫자 필드(status, size, reqsize, respsize, dur)는 비교 연산자 <, <=, >, >=, =를 지원합니다:

status:>=500        서버 오류
size:>100000        큰 교환
dur:>500            500ms보다 느림
dur:<2s             2s보다 빠름 (s / ms 접미사 허용)
size:>100k          바이트 필드는 k/kb, m/mb, g/gb 접미사 허용
status:>=4xx        클래스 약어에도 비교 연산자를 붙일 수 있음

정규 표현식

host, path, url, method, scheme, header, body, ws(그리고 header와 body는 req./resp. 한쪽)에 정규식 매칭을 하려면 ~를 씁니다. ~는 자체적으로 필드/값 구분자 역할을 하므로 앞에 콜론을 붙이지 마세요. 매칭은 대소문자를 구분하며, 대소문자를 무시하려면 (?i)를 앞에 붙입니다.

path~/admin/
host~^api\.
header~set-cookie
method~^P(OST|UT|ATCH)$                쓰기 메서드 전부를 한 항목으로

그 외 필드(status, size, dur, proto 등)에는 정규식 형태가 없습니다. 그런 ~ 항목은 텍스트로 검색되는 대신, 잘못된 숫자 값과 같은 방식으로 버려지고 보고됩니다.

WebSocket 메시지

ws:needle은 소켓이 needle을 담은 메시지를 주고받은 플로우와 매칭합니다(대소문자 무시). ws~regex는 정규식으로 매칭합니다. 양방향 모두, TEXT와 BINARY 페이로드를 가리지 않고 저장된 바이트 그대로 검색하므로 페이로드 앞쪽의 NUL이 뒤의 히트를 가리지 않습니다. ping·pong·close 프레임은 메시지가 아니라 매칭되지 않고, gori가 소켓에 대해 남기는 [gori] 알림 행도 마찬가지입니다. 알림은 이 접두어로 구분하므로, [gori] 로 시작하는 상대방 메시지도 건너뜁니다. -ws:x는 그런 메시지가 없는 플로우를 모두 남기며, 소켓이 아닌 플로우도 포함됩니다.

ws:admin                               admin을 언급한 소켓은?
proto:ws ws~(?i)token=[a-f0-9]{32}     아무 프레임에나 실린 토큰

ws: 뒤에는 인덱스가 없어서 프로젝트의 모든 소켓 트랜스크립트를 훑습니다. 캡처 속도는 그대로이고, 비용은 이 필드를 쓰는 쿼리가 치릅니다.

플로우 하나의 트랜스크립트만 좁히려면, History의 MESSAGES 패널에서 ^F로 검색한 뒤 스페이스 메뉴의 Narrow messages to ^F query를 고르거나(다시 고르면 전체 표시), gori run show <id> --ws-match=QUERY, 또는 MCP get_flow의 ws_query를 씁니다. 모두 ws:needle, ws~regex 또는 접두어 없는 needle을 받고, QL 필드와 똑같이 매칭하며, 각 표면이 평소 불러오는 범위보다 오래된 메시지까지 닿습니다.

JSON-RPC 메서드

rpc:method는 요청 본문이 그 메서드를 부르는 JSON-RPC 호출인 플로우와 매칭합니다. 값은 대소문자를 구분하는 접두사라서 rpc:tools/는 MCP 도구 메서드 전부, rpc:tools/call은 호출만 고릅니다. body~처럼 저장된 요청 바이트를 인덱스 없이 훑으므로, 압축된 요청 본문은 읽지 않고 params 안에 중첩된 "method" 키도 걸립니다. 본문에 "jsonrpc":"2.0"이 있어야 하며, 값의 /는 JSON이 이스케이프한 \/와도 매칭합니다.

rpc:tools/call                         MCP 도구 호출 전부
rpc:initialize host:mcp.example        한 서버에 대한 MCP 핸드셰이크

응답과 짝지어 디코드한 호출은 History 상세의 RPC 패널(MCP 서버라면 이름이 MCP), gori run show --format json과 MCP get_flow의 json_rpc 키에서 봅니다.

항목 결합

  • 공백으로 구분된 항목들은 AND로 결합됩니다. AND를 직접 써도 됩니다.
  • OR는 둘 중 하나를 매칭합니다. NOT과 - 접두사는 모두 부정입니다.
  • 괄호로 묶을 수 있습니다. 우선순위는 NOT, AND, OR 순입니다.
  • field:가 없는 단순 단어는 method, host, target을 대상으로 하는 자유 텍스트 검색입니다.
  • 콜론을 빼먹은 비교 모양의 단어(status>=400, host=api)도 자유 텍스트로 남기 때문에 대개 아무것도 매치하지 않습니다. 이때 History·Sitemap의 빈 화면, gori run history, MCP ql_explain이 콜론 형태(status:>=400)를 알려 줍니다. 따옴표로 묶거나 부정한 단어는 의도한 것으로 봅니다.
  • 존재하지 않는 field: 이름은 자유 텍스트가 아니라 오타로 봅니다. gori run history, gori run sitemap(과 그 params, js, export 동사), gori run probe는 이를 거절하고 가장 가까운 실제 필드를 알려준 뒤 0이 아닌 코드로 종료합니다. --lenient를 주면 그 토큰을 텍스트로 검색합니다(예전에 모든 표면이 조용히 하던 동작으로, methd:GET은 아무것도 매칭하지 않아 프로젝트가 비어 보였습니다). TUI 필터 바는 타이핑 중인 이름을 그대로 받습니다.
host:example.com status:5xx           둘 다 매칭되어야 함
host:api AND status:5xx               같은 의미를 풀어 쓴 것
method:POST -status:200               POST이지만 200은 아님
host:a.com OR host:b.com              둘 중 하나의 호스트
(host:a.com OR host:b.com) -path:/js  둘 중 하나의 호스트, /js 제외
NOT (host:cdn OR host:static)         둘 다 아닌 것
-(host:cdn OR host:static)            같은 뜻. `-(`와 `NOT(`도 그룹을 부정
login                                 자유 텍스트 검색

AND, OR, NOT은 대문자로 쓸 때만 연산자로 인식합니다. 따라서 "and", "or", "not"이라는 단어를 검색하는 것도 그대로 됩니다. 대문자라도 따옴표로 감싸면 리터럴이 됩니다.

큰따옴표는 공백이 포함된 값을 하나의 항목으로 유지합니다:

host:"my host"                        공백까지 포함한 하나의 host 값
"two words"                           구 전체를 자유 텍스트로
"OR"                                  연산자가 아닌 단어 그대로

따옴표 안의 \"는 따옴표 문자 그대로입니다. body:"\"role\":\"admin\""는 "role":"admin"을 찾습니다. 제어 문자(따옴표 안의 탭, NUL)가 든 body:·header: 값은 검색하지 않고 버린 뒤 그 사실을 알립니다.

값 안의 괄호는 리터럴로 남으므로 path:/a(b)는 이스케이프가 필요 없습니다. (는 항목의 맨 앞에서만 그룹을 열고, )는 맨 뒤에서만 그룹을 닫습니다.

적용 범위

모든 필터 바가 위 불리언 문법(AND/OR/NOT, -, 괄호, 따옴표)을 공유합니다. 플로우 바(History, Sitemap, 컬러 규칙, Intercept)는 비교와 ~ 정규식도 공유합니다. 나머지 바는 severity와 cvss(아래)만 비교하고 ~는 아예 없습니다(거기서 ~ 항목은 자유 텍스트입니다). 그 밖에 다른 것은 필드 집합뿐이고, 그것도 각 화면이 서로 다른 종류의 행을 거르기 때문입니다.

화면 필드
History, gori run history, MCP 위 표 전체
Sitemap, gori run sitemap, MCP list_sitemap 위와 동일, 여기에 노드별 경로 메모용 tag: 추가: 대소문자 구분 없이 메모의 일부와 비교하고, 태그가 붙은 경로와 그 아래 전부, 그리고 거기로 이어지는 경로가 매칭됩니다. -tag:는 그 하위 트리를 빼고, 모든 tag: 항목은 쿼리의 나머지와 AND로 묶입니다
컬러 규칙(Colormarker) 위와 동일. History 필터 바에 쓰는 그 쿼리를 그대로 받습니다
Intercept 캐치 조건, Extract 규칙 조건 host, path, url, method, scheme, status, proto, header, body. 나머지 필드는 모두 거부(아래 참고). 여기서 proto는 ws나 http만 답합니다. gRPC와 SSE는 캡처된 응답의 Content-Type으로 판단하므로 proto:grpc, proto:sse와 TLS 표기는 절대 매칭되지 않습니다
Probe severity(sev), status(st), category(cat), host, code
Issues severity(sev), status(st), host, title, cvss
하위 탭 스트립 / 필터(Repeater와 다른 도구 탭), MCP get_repeater_context filter tag, name, host(target), method(verb), status: 마지막 전송 결과로, 앞부분 일치로 비교하는 코드(status:4는 모든 4xx), error, unsent 중 하나
Evidence 탭 issue, host, method, status, confirmation(confirm), source(src), date

홀드 게이트와 Extract 규칙 조건은 캡처되기 전의 흐르는 메시지 하나를 평가하므로, 그 메시지가 답할 수 없는 History 필드는 추측하지 않고 거부합니다. scope:(프로젝트의 스코프 규칙은 메시지의 일부가 아님), size:·reqsize:·respsize:·dur:(교환이 아직 끝나지 않음), stub:·rewritten:·static:· src:·via:·cache:·rpc:·ws:(게이트가 쥔 것은 트랜스크립트가 아니라 메시지 하나이고, 그 body:가 이미 그 메시지를 뜻함), 그리고 한쪽 방향만 보는 req./resp. 표기가 그렇습니다. 거부된 필드를 대신 자유 텍스트로 검색하는 일도 없습니다. 입력하는 자리에서 그렇게 알려주고, 그런 필드를 담은 Extract 규칙은 저장되지 않으며, MCP intercept_set_filter와 gori run intercept filter는 그 조건을 거부합니다.

Probe와 Issues는 심각도 이름(info, low, medium/med, high, critical/crit)과 트리아지 상태(open, confirmed/conf, false-positive/fp, resolved/done, 그리고 open이 아닌 모든 상태를 뜻하는 closed)를 받습니다. 심각도는 비교를 지원하므로 sev:>=high도 동작합니다. Issues는 수치 비교 연산자(cvss:>=7.0, cvss:<4.0), 일치 점수(cvss:7.5), 벡터 부분일치(cvss:3.1)를 지원하는 cvss:도 받습니다.

sev:>=high -status:fp                 Issues: high와 critical, 오탐 제외
cvss:>=7.0 status:open                Issues: open 상태인 high 이상 CVSS 발견
cat:cors sev:medium                   Probe: medium 등급 CORS 발견
host:api.example.com method:POST      Intercept: 한 호스트의 POST만 홀드
body:secret AND -host:cdn             컬러 규칙: 유출은 칠하고 CDN은 제외

Intercept 바와 컬러 규칙 바 모두 입력하는 동안 필드 이름과 알려진 값을 Tab으로 자동 완성합니다.

요청·응답 본문 문자열 매칭

header:와 body:는 메시지의 바이트를 뒤집니다. 따라서 어디서 동작하는지는 필터를 물어보는 그 시점에 어떤 바이트가 존재하는가로 정해집니다.

  • History, Sitemap, 컬러 규칙은 이미 캡처된 플로우를 봅니다. 그래서 두 필드 모두 요청·응답 양쪽에서 항상 동작합니다.
  • Intercept와 Extract 규칙 조건은 흐르는 중인 메시지를 봅니다. header:는 HTTP 요청·응답 게이트와 Extract 규칙 조건에서 동작하고, 홀드된 WebSocket 메시지에서는 동작하지 않습니다. WebSocket 메시지에는 자기 헤드가 없기 때문입니다. body:는 페이로드가 손에 있는 경우(홀드된 WebSocket 메시지와 Extract 규칙 조건)에서 동작하고, HTTP 홀드 게이트에서는 동작하지 않습니다. 그 게이트가 바로 본문을 버퍼링할지 말지를 결정하는 지점이기 때문입니다.

규칙을 쓰기 전에 알아둘, 의도된 차이가 하나 있습니다.

  • 쿼리에서 body:는 트라이그램 인덱스를 읽습니다. 빠르지만 각 방향 첫 8 KiB로 제한되고 바이너리·압축 본문은 건너뜁니다. body~정규식은 대신 저장된 바이트를 그대로 훑고 제한이 없습니다.
  • 컬러 규칙에서 body:는 항상 훑고, 각 방향 첫 64 KiB를 읽습니다. 인덱싱은 캡처 이후에 일어나는데 규칙은 방금 도착한 행을 칠해야 하니 훑는 것 말고는 정답이 없고, 64 KiB 한계는 큰 본문 한 화면이 목록을 멈춰 세우지 않게 하는 장치입니다. 그래서 컬러 규칙은 똑같은 쿼리가 목록에 못 띄우는 행도 칠하지만, 64 KiB를 넘어가는 매치는 칠하지 않습니다.

모든 화면의 body:는 와이어에 흐른 그대로의 바이트를 읽습니다. 그래서 어느 것도 gzip 본문 안의 문자열은 찾지 못합니다. Extract 규칙 조건도 마찬가지입니다. 조건은 응답을 디코드하기 전에 평가되고, 압축 해제된 텍스트를 보는 것은 그 뒤에 이어지는 추출뿐입니다. 압축된 내용을 걸러야 한다면 그 바깥을 거세요: 헤더, 경로, 또는 응답 크기.

주의할 점

쿼리 결과가 멀쩡해 보여도 실제로는 일부 행을 확인하지 않은 경우가 몇 가지 있습니다.

  • 대기 중인 플로우에는 상태, 지속 시간, 응답 크기가 없어 status:와 -status: 양쪽에서 모두 빠집니다(dur, respsize도 같습니다).
  • 버려진 항목은 쿼리를 넓힙니다. gori가 읽을 수 없는 값(status:>=foo)은 거부되지 않고 무시되지만, 무시된 사실은 알려 줍니다. gori run은 경고를 출력하고, MCP 쿼리 도구는 응답의 ignored_terms에 그 항목을 적습니다(strict:true를 주면 쿼리를 거절합니다). 무엇이 남았는지는 ql_explain으로 확인하세요.
  • 잘못된 정규식은 오류입니다. 조용히 버려지지 않고 body~[는 쿼리 전체를 실패시킵니다.
  • **큰 본문에 -body:**를 쓰면 8 KiB 인덱스 한도 너머의 일치를 인덱스가 보지 못해 그대로 남깁니다.

예제

# 한 호스트의 오류
gori run history -q 'host:api.example.com status:5xx'

# 토큰을 언급하는 느린 POST
gori run history -q 'method:POST dur:>1s body:token'

# 정적 자산을 제외한 admin 경로
gori run history -q 'path~/admin/ -path~\.(css|js|png)$'

# 패시브 스캔의 범위 지정
gori run probe -q 'host:example.com'