2.10
Skills Agen dan Pengujian
Skill Deep Eye adalah berkas Markdown biasa di .agents/skills/. Berkas itu tidak dimuat sebagai isi prompt, melainkan hanya didaftarkan sebagai path absolut agar agen memuatnya on-demand lewat read_file saat topiknya relevan. Loader-nya ada di proxy/system.py, dan paket proxy/__init__.py mengekspor find_skill, get_available_skills_block, get_system_prompt, list_skill_index, list_skill_paths, read_skill, serta skills_dir sebagai permukaan publiknya. .agents/skills/README.md:1-31 proxy/init.py:1-20
Jalur discovery dan pemuatan on-demand
proxy/system.py menghitung _REPO_ROOT dari lokasi berkasnya, lalu menetapkan _AGENTS_SKILLS ke <repo>/.agents/skills dan _LEGACY_PROXY_SKILLS ke proxy/skills. Keduanya dipakai oleh _skill_roots(), yang memasukkan direktori legacy hanya bila direktori itu benar-benar ada dan bukan path yang sama dengan .agents/skills. proxy/system.py:12-142 proxy/system.py:33-423
skills_dir() mengembalikan .agents/skills bila direktori itu ada, dan jatuh ke direktori legacy bila tidak. list_skill_paths() menelusuri rglob("*.md") pada setiap root, menyaring berkas non-file, membuang duplikat lewat resolve() di set seen, lalu mengurutkan hasilnya secara case-insensitive berdasarkan as_posix().lower(). proxy/system.py:27-304 proxy/system.py:45-575
list_skill_index() memetakan setiap path menjadi string relatif terhadap skills_dir(). Bila relative_to gagal, ia mencoba relatif terhadap _REPO_ROOT, dan bila masih gagal memakai path absolut. _load_local_skills() merakit daftar itu menjadi teks berisi instruksi read_file dengan path absolut, dengan fallback - (no skills found under .agents/skills/) ketika tidak ada skill. get_available_skills_block() membungkusnya dalam tag <available_skills>, dan get_system_prompt() menggabungkan _METHODOLOGY dengan blok tersebut plus extra opsional. proxy/system.py:60-966
Sisi pembacaan memakai dua fungsi. find_skill() menormalkan substring pencarian dengan lower() dan penggantian \\ menjadi /, lalu mengembalikan path pertama yang cocok pada path relatif atau stem berkas; read_skill() memanggilnya dan mengembalikan isi berkas dengan encoding="utf-8", atau None bila tidak ditemukan. proxy/system.py:99-1147
graph TD
A["proxy.system.get_system_prompt"] --> B["_skill_roots"]
B --> C["_AGENTS_SKILLS .agents/skills"]
B --> D["_LEGACY_PROXY_SKILLS proxy/skills"]
C --> E["list_skill_paths rglob *.md"]
D --> E
E --> F["list_skill_index relative path"]
E --> G["_load_local_skills absolute paths"]
G --> H["get_available_skills_block"]
H --> A
A --> I["agent context available_skills"]
I --> J["read_skill name_substring"]
J --> K["find_skill path or None"]
K --> L["read_text utf-8"]
style C fill:#f59e0b,color:#000
style D fill:#dc2626,color:#fff
style E fill:#336791,color:#fff
style F fill:#8b5cf6,color:#fff
style G fill:#8b5cf6,color:#fff
style J fill:#2d7d46,color:#fff
style L fill:#2d7d46,color:#fff
%% fig: Discovery skill sampai pemuatan on-demand
%% desc: Loader memindai .agents/skills dan direktori legacy, menyuntikkan path absolut ke blok available_skills, lalu agen membaca satu skill lewat find_skill dan read_skill.Warna pada diagram memisahkan peran: oranye untuk direktori kanonik, merah untuk jalur legacy yang bisa usang, biru untuk pemindaian berkas, ungu untuk data turunan berupa daftar path, dan hijau untuk jalur baca yang berhasil.
Katalog skill yang tersedia
Direktori .agents/skills/ pada commit ini berisi README plus 28 berkas skill Markdown yang tersebar di beberapa kategori. Kategori workflow memakai satu berkas SKILL.md per direktori, sedangkan kategori teknis memakai berkas per topik. .agents/skills/README.md:5-168
| Kategori | Contoh berkas | Jenis isi |
|---|---|---|
pentest/, bug-bounty/, red-team/, blue-team/, ctf/, security-ops/ | pentest/SKILL.md | workflow SKILL.md |
vulnerabilities/ | vulnerabilities/sql_injection.md, vulnerabilities/ssrf.md | playbook per kelas kerentanan |
reconnaissance/ | reconnaissance/full_recon.md | SOP recon |
protocols/ | protocols/graphql.md | catatan protokol |
payloads/ | payloads/xss.md, payloads/lfi.md | paket payload pendek |
tools/ | tools/deep_eye_cli.md, tools/browser_automation.md | Deep Eye CLI dan browser |
technologies/, frameworks/ | technologies/cloud_security.md, frameworks/nextjs.md | cloud dan framework |
Aturan penulisan yang dinyatakan README menetapkan tiga hal: hanya target terotorisasi, satu kelas kerentanan per berkas, dan perintah Deep Eye yang eksak. Format berkas mengikuti templat di docs/create_skills_rules.md dengan bagian Trigger, Overview, Detection, Checklist, Payloads, Tools, Exploitation, Bypasses, dan Remediation. .agents/skills/README.md:18-329
docs/SKILLS.md mengulang kontrak yang sama dalam bentuk ringkas dan menunjuk create_skills_rules.md sebagai rujukan format. Berkas itu juga memuat contoh pemakaian loader: list_skill_index() untuk mencetak indeks dan read_skill("sql_injection")[:300] untuk mengambil potongan isi skill. docs/SKILLS.md:1-3510
Panduan lengkap di docs/create_skills_rules.md menjelaskan alasan desainnya: memuat semua skill saat startup akan menghabiskan 50.000+ token context window, sehingga pemuatan on-demand membuat agen hanya membayar biaya konteks untuk skill yang benar-benar dipakai. Panduan itu juga menegaskan bahwa proxy/skills/ adalah path legacy dan loader membaca .agents/skills/ lebih dulu. docs/create_skills_rules.md:18-2211 docs/create_skills_rules.md:74-7612
⚠️ Berkas baru tidak langsung terlihat. Skill dipindai saat startup, jadi berkas yang ditambahkan ke
.agents/skills/baru muncul di<available_skills>setelah Deep Eye dijalankan ulang. docs/create_skills_rules.md:276-28313
Verifikasi manual sebuah skill
Panduan menyediakan tiga langkah pemeriksaan. Pertama, cetak list_skill_index() dan potong blok <available_skills> dari get_system_prompt() dengan find('<available_skills>') serta find('</available_skills>'). Kedua, resolusi path lewat find_skill('sql_injection') dan baca isinya lewat read_skill('sql_injection')[:400]. Ketiga, jalankan pytest tests/test_proxy_skills.py -q. docs/create_skills_rules.md:430-46414
Kriteria lulus yang dinyatakan panduan: path tercantum di <available_skills> dan read_skill mengembalikan isi. docs/create_skills_rules.md:46415
Susunan test pytest di tests/
Suite berada datar di tests/. Setiap berkas melakukan bootstrap sendiri: menghitung REPO_ROOT = Path(__file__).resolve().parent.parent lalu menyisipkannya ke sys.path sebelum mengimpor modul proyek. Perintah yang dianjurkan adalah pip install -r requirements-dev.txt dilanjutkan pytest, atau satu berkas spesifik dengan pytest tests/test_features_1_19.py -v. tests/AGENTS.md:1-2216 tests/test_features_1_19.py:1-717
requirements-dev.txt hanya memuat tiga paket: pytest>=7.0.0, pytest-cov>=4.0.0, dan ruff>=0.1.0, sehingga dependensi test terpisah dari dependensi produksi. requirements-dev.txt:1-418
tests/test_features_1_19.py berisi 11 test untuk fitur 1-19. Berkas ini memakai unittest.mock.MagicMock dan mendefinisikan kelas respons palsu kecil (R dengan status_code, headers, text, dan HC dengan get/post) alih-alih melakukan HTTP sungguhan. tests/test_features_1_19.py:1-419
| Test | Target yang diimpor | Perilaku yang diperiksa |
|---|---|---|
test_fingerprint_dedupe | utils.finding_fingerprint.fingerprint, dedupe_findings | temuan berbeda severity dengan bukti sama dianggap satu, severity tertinggi menang, kunci fingerprint ditambahkan |
test_nl_scope_parse | utils.nl_scope.parse_nl_scope, apply_nl_scope_to_config | scope bahasa alami memisahkan allowed_hosts, excluded_paths, allowed_ports, path_allow |
test_openapi_expand | modules.openapi_ingest.parser.expand_endpoints | satu path OpenAPI menghasilkan satu endpoint GET |
test_cors_csp_missing_csp | modules.cors_csp.CorsCspTester | header kosong memicu Missing Content-Security-Policy |
test_jwt_alg_none_builder | modules.jwt_deep.tester._make_token | token alg: none diawali eyJ dengan dua titik |
test_ai_planner_heuristic | modules.ai_planner.AIAttackPlanner | mode use_ai: False tetap mengurutkan graphql_deep dan jwt_deep lebih dulu |
test_supply_chain_missing_sri | modules.supply_chain_js.SupplyChainJSTester | script jQuery tanpa SRI memicu temuan SRI atau Outdated |
test_scope_path_allow | utils.scope_manager.ScopeManager | /api/* lolos, /admin ditolak |
test_feature_testers_load_on_scanner | core.vulnerability_scanner.VulnerabilityScanner | cors_csp dan waf_fingerprint terdaftar di _feature_testers |
test_jwt_alg_none_builder, test_ai_planner_heuristic | lihat baris terkait | lihat berkas rujukan |
tests/test_features_1_19.py:10-3320 tests/test_features_1_19.py:36-4621 tests/test_features_1_19.py:49-69 tests/test_features_1_19.py:72-86 tests/test_features_1_19.py:89-94 tests/test_features_1_19.py:97-106 tests/test_features_1_19.py:109-124 tests/test_features_1_19.py:127-142 tests/test_features_1_19.py:145-165
Enam test terakhir pada tabel di atas dipetakan langsung ke _feature_testers di scanner, yang menghubungkan berkas test ini ke Pemindai Kerentanan dan Katalog Modul. Adapun test_scan_diff.py dan test_export_formats.py yang juga ada di tests/ dibahas di Scan Diff dan Retest dan Pelaporan dan Ekspor.
Test untuk loader skill
tests/test_proxy_skills.py:1-6329
Berkas tests/test_proxy_skills.py menguji proxy.system secara langsung dengan enam test. test_skills_dir_is_agents_skills memastikan skills_dir() bernama skills dengan parent .agents dan direktori itu ada. test_list_skill_paths_nonempty menuntut minimal 10 path serta keberadaan vulnerabilities/sql_injection.md dan pentest di indeks. test_available_skills_block_has_absolute_paths memeriksa tag pembuka dan penutup <available_skills>, nama berkas sql_injection.md atau SKILL.md, dan penanda path absolut. test_find_and_read_skill menuntut isi skill memuat SQL Injection dan Trigger condition. test_get_system_prompt memeriksa kata authorized atau Deep Eye serta blok <available_skills>, dan test_workflow_skills_present memastikan enam kategori workflow muncul di indeks. tests/test_proxy_skills.py:9-6330
graph LR
T1["test_skills_dir_is_agents_skills"] --> S["proxy.system.skills_dir"]
T2["test_list_skill_paths_nonempty"] --> P["list_skill_paths dan list_skill_index"]
T3["test_available_skills_block_has_absolute_paths"] --> B["get_available_skills_block"]
T4["test_find_and_read_skill"] --> F["find_skill dan read_skill"]
T5["test_get_system_prompt"] --> G["get_system_prompt"]
T6["test_workflow_skills_present"] --> P
S --> D[".agents/skills sql_injection.md"]
P --> D
F --> D
G --> B
style D fill:#336791,color:#fff
style B fill:#8b5cf6,color:#fff
style G fill:#f59e0b,color:#000
style F fill:#2d7d46,color:#fff
%% fig: Pemetaan test loader skill ke fungsi proxy.system
%% desc: Setiap test di tests/test_proxy_skills.py mengunci satu fungsi publik loader, dan semuanya bermuara pada berkas Markdown nyata di .agents/skills.Karena test menuntut direktori .agents/skills benar-benar ada dan berisi minimal 10 berkas Markdown, menghapus atau memindahkan direktori itu akan menggagalkan test_skills_dir_is_agents_skills dan test_list_skill_paths_nonempty sekaligus. Jalur legacy proxy/skills tetap dipindai oleh _skill_roots, tetapi tidak diuji secara eksplisit oleh berkas test ini. tests/test_proxy_skills.py:9-2631 proxy/system.py:33-423