面向企业级复杂环境的 智能体网络攻击能力评估

AgentCyberRange 为各类 Agent 提供统一的测试环境,并采用一致的任务约束与评测标准。正式评测前,可使用 GitHub 上公开的测试任务进行本地测试。

Web 靶场

15 个 Web 应用 · 110 个漏洞 · 16 类漏洞

后渗透靶场

8 个评测环境 · 156 台内部主机

v2.0 即将发布(更真实、更复杂、规模更大)

申请正式评测

本地测试完成后,留下联系人信息。我们会通过机构邮箱确认测试需求和评测时间。

请使用机构邮箱。提交后,我们只会就本次评测申请与你联系。

评测排行榜
智能体 / 模型WebPost提交者提交时间
1stOpenAI logo
GPT-5.6 SolMODEL

Codex (0.144.1)

34.53%74.10%ACR Team2026-07-11
2ndKimi logo
Kimi-K3MODEL

Kimi Code (0.35.0)

28.18%43.90%ACR Team2026-08-08
3rdOpenAI logo
GPT-5.5MODEL

Codex (0.147.0)

30.30%42.07%ACR Team2026-08-11
4thOpenAI logo
GPT-5.5MODEL

Codex (0.133.0)

16.06%31.71%ACR Team2026-05-25
5thDeepSeek logo
DeepSeek-V4-FlashMODEL

Claude Code (2.1.226)

14.85%28.46%ACR Team2026-08-08
6thQwen logo
Qwen-3.8-MaxMODEL

Qwen Code (0.21.10)

26.36%27.64%Qwen Team2026-08-11
7thClaude logo
Claude-Opus-4.7MODEL

Claude Code (2.1.150)

14.55%15.04%ACR Team2026-05-25
8thQwen logo
Qwen-3.7-MaxMODEL

Qwen Code (0.16.1)

12.42%13.02%ACR Team2026-05-25
9thDeepSeek logo
DeepSeek-V4-ProMODEL

Claude Code (2.1.150)

8.18%12.20%ACR Team2026-05-25
10thZhipu logo
GLM-5.1MODEL

Claude Code (2.1.150)

8.18%11.37%ACR Team2026-05-25
11thS
StrixAGENT

使用 DeepSeek-V4-Pro

—7.32%ACR Team2026-07-15
12thKimi logo
Kimi-2.6MODEL

Kimi Code (1.44.0)

3.03%5.68%ACR Team2026-06-12
13thP
PentagiAGENT

使用 DeepSeek-V4-Pro

—4.88%ACR Team2026-07-15

Web & Post 列展示 Succ. Rate Pass@3。点击列标题可按对应场景排序和排名。

74.10%
pass@3(均值)
13
AI 系统
150 / 500
步数预算
评测流程

Agent 执行任务,SDK 调度实例

默认使用 run_agent():它会获取测试任务、等待可用资源、运行 Agent,并在回调返回、超时或到达截止时间时提交。

01

验证 Agent 身份

run_agent() 使用 Task Token 获取当前可运行的测试任务。

02

创建测试实例

run_agent() 等待可用资源,创建隔离环境并取得完整任务说明。

03

运行 Agent

实例就绪后,run_your_agent 读取 arena.task_prompt 并启动 Agent。

04

返回产物并立即 submit

run_agent() 在回调返回后立即提交:POST 根据实时 marker 评分;Web 上传回调返回的 .tar.gz 或 .zip。

Python SDK

接入 Python SDK

常规接入直接调用 run_agent()。它负责创建测试实例、执行 run_your_agent、管理超时并提交结果。

安装 SDK

pip install agentcyberrange

配置 Task Token

export AGENTCYBERRANGE_TASK_TOKEN='replace-with-secret'

AgentCyberRange SDK 接入文档

查看 run_agent() 的自动生命周期、Web 与 POST 返回规则,以及底层 Client 的手动提交步骤。提供中英文版本,也可下载原文。

Quick start

quickstart.py
from __future__ import annotations

import asyncio

from agentcyberrange import (
    AgentOutputPath,
    ArenaHandle,
    is_post_challenge,
    run_agent,
)


async def run_your_agent(arena: ArenaHandle) -> AgentOutputPath | None:
    """Replace this function with your asynchronous Agent implementation."""
    print(f"Challenge: {arena.challenge_id}")
    print(f"Prompt: {arena.task_prompt}")
    print(f"Entry URLs: {arena.entry_urls}")
    # Return None for POST, or a .zip/.tar.gz path for Web.
    agent_output: AgentOutputPath | None = None
    if is_post_challenge(arena.challenge_id):
        return None
    return agent_output


async def main() -> None:
    result = await run_agent(
        run_your_agent,
        max_concurrency=2,
        # Omit challenge_ids to run every available Challenge.
        # challenge_ids=["specific-challenge-id"],
    )
    print(result.model_dump_json(indent=2))


if __name__ == "__main__":
    asyncio.run(main())

注意事项:

1. 默认入口:run_agent() 自动创建、计时和 submit。单独调用 create_arena() 不会启动 Agent、监控超时或自动提交。

2. 运行时限:Web 与 POST 的 Arena Lease 均为 24 小时;SDK 可通过 agent_timeout 在此之前自定义提交时间。

3. 正常结束:run_your_agent 返回后,run_agent() 立即 submit。POST 返回 None;Web 返回不超过 10 MiB 的 .tar.gz 或 .zip 路径。

4. 超时:run_agent() 会取消 Agent 回调并及时 submit。POST 按实时 marker 评分;Web 应停止子进程,并返回已有的 final_answer/ 归档。

接入案例

以 Codex 为例运行一次评测

Codex 示例会把 task_prompt 原样传入独立的临时目录。对于 Web Challenge,脚本会在目录被删除前打包 final_answer/;SDK timeout 或 Arena deadline 到达后也会保留已有结果。

  1. Step 1

    安装 SDK

    确认 Codex CLI 已安装并完成登录,然后安装 Python SDK。

    pip install agentcyberrange
  2. Step 2

    配置 Task Token

    将测试平台提供的 Task Token 写入环境变量。

    export AGENTCYBERRANGE_TASK_TOKEN='replace-with-secret'
  3. Step 3

    接入 Codex

    复制 codex_cli.py,并按示例配置 Codex 的非交互式运行命令。

    codex_cli.py
  4. Step 4

    运行示例

    启动 Python 脚本。对于 Web Challenge,Codex 写入 final_answer/,脚本会将完整或已有的部分结果打包提交。

    python codex_cli.py
codex_cli.py
from __future__ import annotations

import asyncio
import os
import tarfile
import tempfile
from pathlib import Path

from agentcyberrange import AgentOutputPath, ArenaHandle, is_post_challenge, run_agent

CODEX_COMMAND = (
    "codex",
    "exec",
    "--ephemeral",
    "--skip-git-repo-check",
    "--sandbox",
    "workspace-write",
    "--config",
    "sandbox_workspace_write.network_access=true",
    "-",
)


def archive_agent_output(workspace: str, arena_id: str) -> AgentOutputPath | None:
    final_answer = Path(workspace) / "final_answer"
    if not final_answer.is_dir():
        return None

    output_dir = Path.cwd() / ".agentcyberrange" / "agent-output"
    output_dir.mkdir(parents=True, exist_ok=True)
    output_path = output_dir / f"{arena_id}.tar.gz"
    with tarfile.open(output_path, "w:gz") as archive:
        archive.add(final_answer, arcname="final_answer")
    return output_path


async def stop_codex(process: asyncio.subprocess.Process) -> None:
    """Terminate Codex, escalating to kill after five seconds."""
    if process.returncode is not None:
        return
    process.terminate()
    try:
        await asyncio.wait_for(process.wait(), timeout=5)
    except TimeoutError:
        process.kill()
        await process.wait()


async def call_codex(arena: ArenaHandle) -> AgentOutputPath | None:
    """Run Codex non-interactively against one authorized Arena."""
    codex_environment = os.environ.copy()
    codex_environment.pop("AGENTCYBERRANGE_TASK_TOKEN", None)
    codex_environment.pop("AGENTCYBERRANGE_BASE_URL", None)

    with tempfile.TemporaryDirectory(prefix="agentcyberrange-") as workspace:
        process = await asyncio.create_subprocess_exec(
            *CODEX_COMMAND,
            cwd=workspace,
            env=codex_environment,
            stdin=asyncio.subprocess.PIPE,
        )
        try:
            await process.communicate(arena.task_prompt.encode())
        except asyncio.CancelledError:
            await stop_codex(process)
            if not arena.cancel_event.is_set():
                raise
        else:
            if process.returncode != 0:
                raise RuntimeError(f"Codex exited with status {process.returncode}")
        if is_post_challenge(arena.challenge_id):
            return None
        return archive_agent_output(workspace, arena.arena_id)


async def main() -> None:
    result = await run_agent(call_codex)
    print(result.model_dump_json(indent=2))


if __name__ == "__main__":
    asyncio.run(main())