Skip to main content

YARA Detection API

The v2 Detection API manages the YARA rules that urlquery runs against every analysis: the same rule sets and rules you see under Detection → YARA on urlquery.net. Use it to keep rules in a repository and sync them from CI. See YARA rules for what the rules scan and how their alerts work.

All routes are on https://api.urlquery.net and require x-apikey. You see and change only your own sets and rules, and those your team shares.

MethodPathQuota classResult
GET/public/v2/detection/yara/setsyara_readYour rule sets.
POST/public/v2/detection/yara/setsyara_writeCreates a rule set.
GET/public/v2/detection/yara/sets/{set_id}yara_readOne rule set.
PUT/public/v2/detection/yara/sets/{set_id}yara_writeReplaces a set's name, description, and visibility. Owner only.
DELETE/public/v2/detection/yara/sets/{set_id}yara_writeDeletes a set and all its rules. Owner only.
GET/public/v2/detection/yara/sets/{set_id}/rulesyara_readThe set's rules, with their source.
POST/public/v2/detection/yara/sets/{set_id}/rulesyara_writeCompiles and saves a new rule in a set you own or your team shares.
GET/public/v2/detection/yara/rules/{rule_id}yara_readOne rule, with its source.
PUT/public/v2/detection/yara/rules/{rule_id}yara_writeCompiles and replaces a rule.
DELETE/public/v2/detection/yara/rules/{rule_id}yara_writeDeletes a rule.
POST/public/v2/detection/yara/validateyara_writeCompiles a source without saving it.
POST/public/v2/detection/yara/testyara_writeRuns a source against a report you can read, without saving it.

Every call also consumes the account's overall v2 quota. yara_write is lower than the other classes because each call compiles a YARA source.

Create a rule​

A detection rule is one YARA source, which can contain more than one YARA rule. The source is compiled before it is saved; includes are not allowed and the limit is 1 MiB.

curl --fail-with-body --request POST \
--header "x-apikey: ${URLQUERY_API_KEY}" \
--header 'content-type: application/json' \
--data @- \
"https://api.urlquery.net/public/v2/detection/yara/sets/${SET_ID}/rules" <<'EOF'
{
"name": "phishing-kits",
"description": "Kit fingerprints",
"content": "rule kit_a { strings: $a = \"kit-a\" condition: $a }",
"visibility": "private",
"alert_visibility": "private"
}
EOF
  • visibility is private or team. team lets your teammates see and use the rule, and with can_team_edit also change it.
  • alert_visibility decides who sees the rule's alerts on matching reports: private (you) or team.

PUT /public/v2/detection/yara/rules/{rule_id} takes the same body and replaces the rule. Only the owner's visibility, alert_visibility, and can_team_edit are applied; a teammate's update changes the name, description, and source.

To pause a rule without deleting it, replace it with "enabled": false; "enabled": true turns it back on, and leaving enabled out keeps its state. Anyone who can edit the rule can switch it. A disabled rule stops running within about five minutes. New rules are always enabled, so "enabled": false on create returns 400.

Compile errors​

A source that does not compile is rejected with 422 and nothing is saved. The message lists up to 10 compiler errors with their lines:

{
"success": false,
"error": {
"http_code": 422,
"error": "UNPROCESSABLE_ENTITY",
"message": "YARA source does not compile: line 2: syntax error, unexpected end of file"
}
}

To check a source in CI before saving it, call POST /public/v2/detection/yara/validate with {"content": "..."}. It returns 200 with valid, rule_count, and every error and warning in diagnostics.

If the compiler is busy, saving a rule, validation and tests return 503 COMPILER_BUSY; retry after a few seconds. A request body over about 6 MiB returns 413 SOURCE_TOO_LARGE, like a source over 1 MiB.

Test a rule against a report​

POST /public/v2/detection/yara/test with {"content": "...", "report_id": "<report UUID>"} runs a source against one report you can read, without saving anything. Use it to see what a new or changed rule matches before you save it. A report you can't read returns 404, once the source compiles. Testing YARA rules covers choosing reports to test against, how a test differs from analysis, and what to do when a result surprises you.

Each script and stored response body of the report is scanned on its own, as during analysis. A source that does not compile returns valid: false with its diagnostics, and nothing is scanned.

{
"success": true,
"data": {
"valid": true, "rule_count": 1, "diagnostics": [], "scanned": 12,
"skipped": {"unavailable": 3, "archived": 0, "limit": 0, "timeout": 0},
"matches": [{
"kind": "script", "url": "https://example.test/kit.js", "sha256": "<sha256>",
"rules": [{"name": "collect", "strings": [{"name": "$a", "count": 4,
"matches": [{"offset": 15, "length": 12, "data": "/api/collect"}]}]}]
}]
}
}
  • scanned counts the resources scanned.
  • Each entry in matches is a resource that matched:
    • kind is script or response, with its url and sha256;
    • rules lists the YARA rules that matched;
    • for each string, count is how often it matched, and matches holds its first three matches, each with its byte offset, length, and up to 64 bytes of matched data. Bytes outside printable ASCII are shown as ..
  • skipped counts what was not scanned:
FieldNot scanned
unavailableResponse bodies urlquery doesn't store, such as images.
archivedFiles inside archives.
limitResources past 200, or past 32 MiB in total.
timeoutResources whose scan took over 5 s, or ran past 10 s in total.

A test counts against yara_write, like validation.

Syncing from CI​

Rule and set IDs are stable, so a sync job can keep a mapping from file to rule ID:

  1. Create the set once, in the UI or with POST /public/v2/detection/yara/sets, and store its ID.
  2. List the set's rules with GET .../sets/{set_id}/rules and match them to your files by name.
  3. Optionally, test each changed file against a report it should match and one it shouldn't, with POST .../yara/test, and stop if the results are wrong.
  4. PUT changed files, POST new ones, and DELETE rules whose file was removed.

Each write is checked on its own; a file that does not compile fails with 422 without affecting the others.

A create that times out or returns 502 or 504 may still have been saved. List the set before retrying, so the rule is not created twice.