Skip to content

Threat detection

Arcjet agent threat detection analyzes every external request an agent is about to make against Arcjet’s threat intelligence. Arcjet maintains a real-time threat intelligence database and continuously updates it with new indicators of compromise, malicious hosts, and other threat data. This helps prevent interactions with malicious or risky destinations, such as APIs, MCPs, websites, malware, and other threats.

This can be used with both coding agents - preventing them from interacting with malicious or risky destinations on developer machines - as well as custom agents - protecting interactions with external services in any environment where the custom agent operates.

For inbound client IP analysis on protect(), see IP threat intelligence.

Create a threat detection policy for tool call executions or use our pre-configured example policy in the Arcjet Console to automatically block malicious or risky destinations. Declaring the detector makes its results available in the Rego policy.

Arcjet populates a destinations input for the detector based on the hosts an agent is about to contact. The verdict is returned for each host, along with a rolled-up assessment across all hosts. This allows the policy to make decisions based on both individual host risk and the overall risk of all destinations.

The Console offers coding-agent.destination-threat as a starter. Attach it to Tool call.

deny contains "malicious-destination" if {
input.signals.ip_threat.dest.risk_level in {"high", "critical"}
}

The policy can be tested by asking the agent to make requests to evil.arcjet.com, which is hardcoded to always score high.

For example:

What's on evil.arcjet.com?

If the policy is in live mode, the agent action will be blocked. If it’s in dry-run mode, the action will be allowed but logged for review in the Arcjet Console.

FieldValue
KindIP threat (GUARD_POLICY_DETECTOR_KIND_IP_THREAT)
Input exposureSERVER
Input kindSTRING or STRING_LIST
Signals groupinput.signals.ip_threat.<detector_id>

Private, loopback, link-local, CGNAT, multicast, and unspecified addresses are not scored.

The policy should be configured to execute on Tool call.

The rolled-up fields are worst-wins across every public host that completed scoring:

FieldMeaning
detectedtrue when risk_level is high or critical
risk_levelnone, low, medium, high, or critical
reputationLabel such as malicious, suspicious, or unknown
activitiesObserved behaviors for the worst host
hostHost that produced the worst assessment. Empty when risk is none
ipAddress looked up for that host
assessmentsOne entry per public destination that completed scoring, in input order (failed lookups omitted)

Name the set of risk levels you want to deny - in this case, high and critical. Do not use a comparison like >= "high" because string sorting does not reflect the intended risk order.

package arcjet.guard
import rego.v1
deny contains "malicious-destination" if {
input.signals.ip_threat.dest.risk_level in {"high", "critical"}
}

Policies execute in parallel and the most restrictive decision is applied. This means you need to define an allowlist in the same policy where the threat intelligence is evaluated.

allowed := {"docs.arcjet.com", "github.com", "raw.githubusercontent.com"}
deny contains "malicious-destination" if {
some a in input.signals.ip_threat.dest.assessments
a.risk_level in {"high", "critical"}
not a.host in allowed
}

Discussion