pwn 0.5.784 → 0.5.785
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile +6 -6
- data/README.md +37 -0
- data/bin/pwn +2 -1
- data/bin/pwn_web_cache_deception +35 -7
- data/documentation/AI-Integration.md +7 -5
- data/documentation/Agent-Tool-Registry.md +2 -2
- data/documentation/Backup-Retention.md +70 -15
- data/documentation/Configuration.md +10 -6
- data/documentation/Contributing.md +1 -1
- data/documentation/Cron.md +2 -2
- data/documentation/Diagrams.md +2 -2
- data/documentation/General-PWN-Usage.md +4 -3
- data/documentation/Home.md +6 -5
- data/documentation/How-PWN-Works.md +6 -5
- data/documentation/Installation.md +12 -9
- data/documentation/Mission-Cancellation.md +134 -0
- data/documentation/Operability.md +17 -0
- data/documentation/Persistence.md +7 -5
- data/documentation/Plugin-Degradation.md +12 -0
- data/documentation/Plugins.md +3 -2
- data/documentation/Runtime-Source-Protection.md +162 -0
- data/documentation/Transparent-Browser.md +11 -0
- data/documentation/Troubleshooting.md +3 -2
- data/documentation/What-is-PWN.md +2 -2
- data/documentation/YubiKey-Vaults.md +183 -0
- data/documentation/YubiKey.md +339 -0
- data/documentation/diagrams/cron-scheduling.svg +130 -130
- data/documentation/diagrams/dot/cron-scheduling.dot +3 -3
- data/documentation/diagrams/dot/persistence-filesystem.dot +5 -3
- data/documentation/diagrams/dot/plugin-ecosystem.dot +2 -2
- data/documentation/diagrams/persistence-filesystem.svg +172 -142
- data/documentation/diagrams/plugin-ecosystem.svg +64 -64
- data/documentation/pwn-ai-Agent.md +10 -4
- data/etc/default_cron/session_cleanup.rb +43 -27
- data/etc/default_skills/pwn/ai/agent/mission_namespace/SKILL.md +21 -0
- data/etc/default_skills/pwn/ai/agent/tools/browser_act/SKILL.md +45 -0
- data/etc/default_skills/pwn/ai/agent/tools/loot_query/SKILL.md +27 -26
- data/etc/default_skills/pwn/ai/agent/tools/recon_run/SKILL.md +25 -15
- data/etc/default_skills/pwn/ai/agent/tools/workspace_tool/SKILL.md +24 -0
- data/etc/default_skills/pwn/ai/server_tools/SKILL.md +25 -0
- data/etc/default_skills/pwn/backups/SKILL.md +54 -0
- data/etc/default_skills/pwn/plugins/recon/SKILL.md +12 -1
- data/etc/default_skills/pwn/plugins/yubikey/SKILL.md +157 -0
- data/etc/default_skills/pwn/plugins/yubikey/fido/SKILL.md +189 -0
- data/etc/default_skills/pwn/plugins/yubikey/hsmauth/SKILL.md +83 -0
- data/etc/default_skills/pwn/plugins/yubikey/management/SKILL.md +80 -0
- data/etc/default_skills/pwn/plugins/yubikey/oath/SKILL.md +115 -0
- data/etc/default_skills/pwn/plugins/yubikey/openpgp/SKILL.md +144 -0
- data/etc/default_skills/pwn/plugins/yubikey/otp/SKILL.md +97 -0
- data/etc/default_skills/pwn/plugins/yubikey/piv/SKILL.md +110 -0
- data/etc/default_skills/pwn/plugins/yubikey/protocol/SKILL.md +21 -0
- data/etc/default_skills/pwn/plugins/yubikey/security_domain/SKILL.md +75 -0
- data/etc/default_skills/pwn/plugins/yubikey/security_domain/scp/SKILL.md +46 -0
- data/etc/default_skills/pwn/plugins/yubikey/transport/SKILL.md +98 -0
- data/etc/default_skills/pwn/redaction/SKILL.md +13 -1
- data/lib/pwn/ai/agent/dispatch.rb +26 -15
- data/lib/pwn/ai/agent/learning.rb +14 -18
- data/lib/pwn/ai/agent/loop.rb +17 -1
- data/lib/pwn/ai/agent/mission_namespace.rb +331 -0
- data/lib/pwn/ai/agent/policy_evaluation.rb +8 -8
- data/lib/pwn/ai/agent/prompt_builder.rb +13 -2
- data/lib/pwn/ai/agent/request_runtime.rb +122 -18
- data/lib/pwn/ai/agent/reward.rb +5 -3
- data/lib/pwn/ai/agent/skill_consolidation.rb +3 -2
- data/lib/pwn/ai/agent/skill_review.rb +9 -5
- data/lib/pwn/ai/agent/swarm.rb +4 -0
- data/lib/pwn/ai/agent/tools/browser_act.rb +32 -0
- data/lib/pwn/ai/agent/tools/loot_query.rb +11 -1
- data/lib/pwn/ai/agent/tools/recon_run.rb +11 -1
- data/lib/pwn/ai/agent/tools/workspace_tool.rb +29 -0
- data/lib/pwn/ai/agent/turn_finalizer.rb +6 -2
- data/lib/pwn/ai/agent.rb +1 -0
- data/lib/pwn/ai/anthropic.rb +8 -33
- data/lib/pwn/ai/cli.rb +34 -5
- data/lib/pwn/ai/gemini.rb +1 -0
- data/lib/pwn/ai/grok.rb +39 -28
- data/lib/pwn/ai/ollama.rb +4 -2
- data/lib/pwn/ai/open_ai.rb +11 -32
- data/lib/pwn/ai/open_web_ui.rb +62 -4
- data/lib/pwn/ai/router.rb +8 -1
- data/lib/pwn/ai/server_tools.rb +231 -0
- data/lib/pwn/ai.rb +1 -0
- data/lib/pwn/backups.rb +347 -0
- data/lib/pwn/config.rb +70 -39
- data/lib/pwn/migrate.rb +85 -280
- data/lib/pwn/module_skills.rb +7 -0
- data/lib/pwn/plugins/ai_sandbox.rb +538 -1
- data/lib/pwn/plugins/authentication_helper.rb +74 -4
- data/lib/pwn/plugins/basic_auth.rb +2 -1
- data/lib/pwn/plugins/google_workspace.rb +4 -21
- data/lib/pwn/plugins/jobs.rb +1 -1
- data/lib/pwn/plugins/log.rb +3 -1
- data/lib/pwn/plugins/preflight_checker.rb +34 -9
- data/lib/pwn/plugins/recon.rb +4 -1
- data/lib/pwn/plugins/repl/ai.rb +293 -26
- data/lib/pwn/plugins/repl/ai_console.rb +268 -88
- data/lib/pwn/plugins/repl/ai_swarm.rb +177 -58
- data/lib/pwn/plugins/repl/mesh.rb +3 -16
- data/lib/pwn/plugins/repl/vault.rb +4 -15
- data/lib/pwn/plugins/repl.rb +1 -216
- data/lib/pwn/plugins/sandbox/driver.rb +4 -0
- data/lib/pwn/plugins/transparent_browser.rb +215 -0
- data/lib/pwn/plugins/vault.rb +412 -135
- data/lib/pwn/plugins/yubikey/fido.rb +1288 -0
- data/lib/pwn/plugins/yubikey/hsmauth.rb +439 -0
- data/lib/pwn/plugins/yubikey/management.rb +686 -0
- data/lib/pwn/plugins/yubikey/oath.rb +766 -0
- data/lib/pwn/plugins/yubikey/openpgp.rb +1063 -0
- data/lib/pwn/plugins/yubikey/otp.rb +897 -0
- data/lib/pwn/plugins/yubikey/piv.rb +1315 -0
- data/lib/pwn/plugins/yubikey/protocol.rb +341 -0
- data/lib/pwn/plugins/yubikey/security_domain/scp.rb +482 -0
- data/lib/pwn/plugins/yubikey/security_domain.rb +464 -0
- data/lib/pwn/plugins/yubikey/transport.rb +1017 -0
- data/lib/pwn/plugins/yubikey.rb +844 -0
- data/lib/pwn/plugins.rb +1 -0
- data/lib/pwn/redaction.rb +69 -12
- data/lib/pwn/session_trace.rb +4 -0
- data/lib/pwn/setup.rb +114 -24
- data/lib/pwn/version.rb +1 -1
- data/lib/pwn/www/app_cobalt_io.rb +16 -5
- data/lib/pwn/www/bug_crowd.rb +16 -5
- data/lib/pwn/www/coinbase_pro.rb +16 -5
- data/lib/pwn/www/github.rb +30 -14
- data/lib/pwn/www/paypal.rb +15 -4
- data/lib/pwn/www/synack.rb +16 -5
- data/lib/pwn/www/twitter.rb +17 -6
- data/lib/pwn.rb +1 -0
- data/spec/documentation/installation_md_spec.rb +1 -1
- data/spec/fixtures/yubikey/apdu_frames.json +162 -0
- data/spec/integration/authentication_helper_oath_spec.rb +117 -0
- data/spec/integration/controller_spill_spec.rb +48 -0
- data/spec/integration/harness_process_spec.rb +97 -0
- data/spec/integration/mission_cancel_spec.rb +79 -0
- data/spec/integration/mission_curses_pty_spec.rb +44 -0
- data/spec/integration/readme_security_spec.rb +47 -0
- data/spec/integration/web_cache_deception_yubikey_spec.rb +159 -0
- data/spec/lib/pwn/ai/agent/dispatch_spec.rb +6 -3
- data/spec/lib/pwn/ai/agent/dispatch_vault_safety_spec.rb +86 -0
- data/spec/lib/pwn/ai/agent/injection_guard_spec.rb +2 -0
- data/spec/lib/pwn/ai/agent/learning_spec.rb +4 -4
- data/spec/lib/pwn/ai/agent/loop_artifacts_spec.rb +5 -0
- data/spec/lib/pwn/ai/agent/loop_spec.rb +104 -29
- data/spec/lib/pwn/ai/agent/mission_namespace_spec.rb +138 -0
- data/spec/lib/pwn/ai/agent/request_runtime_spec.rb +48 -0
- data/spec/lib/pwn/ai/agent/shell_search_effect_spec.rb +44 -0
- data/spec/lib/pwn/ai/agent/solve_spec.rb +6 -4
- data/spec/lib/pwn/ai/agent/tools/browser_act_spec.rb +44 -0
- data/spec/lib/pwn/ai/agent/tools/loot_query_yubikey_spec.rb +55 -0
- data/spec/lib/pwn/ai/agent/tools/recon_run_yubikey_spec.rb +43 -0
- data/spec/lib/pwn/ai/agent/tools/workspace_tool_spec.rb +20 -0
- data/spec/lib/pwn/ai/agent/turn_finalizer_spec.rb +7 -0
- data/spec/lib/pwn/ai/anthropic_vault_enrollment_spec.rb +37 -0
- data/spec/lib/pwn/ai/cli_spec.rb +6 -9
- data/spec/lib/pwn/ai/oauth_vault_persistence_spec.rb +195 -0
- data/spec/lib/pwn/ai/open_ai_spec.rb +2 -2
- data/spec/lib/pwn/ai/open_web_ui_workspace_spec.rb +36 -0
- data/spec/lib/pwn/ai/router_spec.rb +1 -1
- data/spec/lib/pwn/ai/server_tools_spec.rb +39 -0
- data/spec/lib/pwn/backups_spec.rb +114 -0
- data/spec/lib/pwn/config_redaction_yubikey_spec.rb +28 -0
- data/spec/lib/pwn/config_yubikey_spec.rb +92 -0
- data/spec/lib/pwn/migrate_spec.rb +29 -81
- data/spec/lib/pwn/migrate_yubikey_spec.rb +128 -0
- data/spec/lib/pwn/module_skills_spec.rb +8 -0
- data/spec/lib/pwn/plugins/ai_sandbox_spec.rb +230 -0
- data/spec/lib/pwn/plugins/authentication_helper_native_yubikey_spec.rb +40 -0
- data/spec/lib/pwn/plugins/authentication_helper_yubikey_spec.rb +90 -0
- data/spec/lib/pwn/plugins/capability_broker/daemon_spec.rb +1 -1
- data/spec/lib/pwn/plugins/google_workspace_spec.rb +17 -35
- data/spec/lib/pwn/plugins/log_yubikey_spec.rb +47 -0
- data/spec/lib/pwn/plugins/preflight_checker_native_yubikey_spec.rb +19 -0
- data/spec/lib/pwn/plugins/preflight_checker_yubikey_spec.rb +55 -0
- data/spec/lib/pwn/plugins/recon_yubikey_spec.rb +43 -0
- data/spec/lib/pwn/plugins/repl/ai_console_spec.rb +110 -75
- data/spec/lib/pwn/plugins/repl/ai_legacy_containment_spec.rb +200 -0
- data/spec/lib/pwn/plugins/repl/ai_swarm_spec.rb +19 -16
- data/spec/lib/pwn/plugins/repl/ai_vault_edit_yubikey_spec.rb +103 -0
- data/spec/lib/pwn/plugins/repl/ai_yubikey_spec.rb +48 -0
- data/spec/lib/pwn/plugins/repl/mesh_vault_persistence_spec.rb +149 -0
- data/spec/lib/pwn/plugins/repl/vault_yaml_serialization_spec.rb +11 -0
- data/spec/lib/pwn/plugins/repl/vault_yubikey_spec.rb +39 -0
- data/spec/lib/pwn/plugins/repl_spec.rb +56 -5
- data/spec/lib/pwn/plugins/transparent_browser_jev_spec.rb +46 -0
- data/spec/lib/pwn/plugins/vault_native_yubikey_spec.rb +29 -0
- data/spec/lib/pwn/plugins/vault_publication_safety_spec.rb +258 -0
- data/spec/lib/pwn/plugins/vault_store_safety_spec.rb +241 -0
- data/spec/lib/pwn/plugins/vault_yubikey_safety_spec.rb +168 -0
- data/spec/lib/pwn/plugins/vault_yubikey_spec.rb +128 -0
- data/spec/lib/pwn/plugins/vault_yubikey_vector_spec.rb +45 -0
- data/spec/lib/pwn/plugins/yubikey/fido_spec.rb +854 -0
- data/spec/lib/pwn/plugins/yubikey/hsmauth_spec.rb +235 -0
- data/spec/lib/pwn/plugins/yubikey/management_spec.rb +277 -0
- data/spec/lib/pwn/plugins/yubikey/oath_spec.rb +349 -0
- data/spec/lib/pwn/plugins/yubikey/openpgp_spec.rb +810 -0
- data/spec/lib/pwn/plugins/yubikey/otp_spec.rb +337 -0
- data/spec/lib/pwn/plugins/yubikey/piv_spec.rb +646 -0
- data/spec/lib/pwn/plugins/yubikey/protocol_secure_spec.rb +28 -0
- data/spec/lib/pwn/plugins/yubikey/protocol_spec.rb +149 -0
- data/spec/lib/pwn/plugins/yubikey/protocol_vectors_spec.rb +18 -0
- data/spec/lib/pwn/plugins/yubikey/security_domain/scp_spec.rb +256 -0
- data/spec/lib/pwn/plugins/yubikey/security_domain/support.rb +153 -0
- data/spec/lib/pwn/plugins/yubikey/security_domain_spec.rb +296 -0
- data/spec/lib/pwn/plugins/yubikey/transport_spec.rb +760 -0
- data/spec/lib/pwn/plugins/yubikey_security_spec.rb +260 -0
- data/spec/lib/pwn/plugins/yubikey_spec.rb +209 -0
- data/spec/lib/pwn/plugins/yubikey_terminal_spec.rb +147 -0
- data/spec/lib/pwn/redaction_yubikey_spec.rb +61 -0
- data/spec/lib/pwn/session_cleanup_default_spec.rb +7 -5
- data/spec/lib/pwn/session_cleanup_payload_spec.rb +11 -11
- data/spec/lib/pwn/session_cleanup_recovery_spec.rb +34 -20
- data/spec/lib/pwn/setup_native_yubikey_spec.rb +66 -0
- data/spec/lib/pwn/setup_vault_yubikey_spec.rb +61 -0
- data/spec/lib/pwn/setup_yubikey_spec.rb +40 -0
- data/spec/lib/pwn/www/login_yubikey_spec.rb +273 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/harness/cli_faults.rb +13 -9
- data/spec/support/harness/controller_spill.rb +26 -0
- data/spec/support/harness/controller_state.rb +54 -0
- data/spec/support/harness/evaluate.rb +12 -1
- data/spec/support/harness/experiments.rb +1 -1
- data/spec/support/harness/fake_provider.rb +22 -6
- data/spec/support/harness/fault_preload.rb +3 -1
- data/spec/support/harness/mission_console.rb +54 -0
- data/spec/support/harness/mission_curses_pty.rb +41 -0
- data/spec/support/harness/mission_dispatch.rb +30 -0
- data/spec/support/harness/mission_fixture_preload.rb +24 -0
- data/spec/support/harness/mission_job_lifetime.rb +25 -0
- data/spec/support/harness/mission_legacy.rb +25 -0
- data/spec/support/harness/mission_normal_exit.rb +34 -0
- data/spec/support/harness/mission_swarm.rb +23 -0
- data/spec/support/harness/mission_unsupported.rb +29 -0
- data/spec/support/harness/package_acceptance.rb +33 -5
- data/spec/support/harness/session_acceptance.rb +4 -4
- data/spec/support/harness/swarm_acceptance.rb +1 -1
- data/spec/support/harness/swarm_control.rb +44 -0
- data/spec/support/mission_namespace.rb +14 -0
- data/spec/support/mission_pipe_queue.rb +33 -0
- data/third_party/pwn_rdoc.jsonl +589 -19
- metadata +129 -13
|
@@ -9,135 +9,135 @@
|
|
|
9
9
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(43.2 636.7)">
|
|
10
10
|
<title>PWN_Plugins</title>
|
|
11
11
|
<polygon fill="#0f172a" stroke="none" points="-43.2,43.2 -43.2,-636.7 634.45,-636.7 634.45,43.2 -43.2,43.2"/>
|
|
12
|
-
<text xml:space="preserve" text-anchor="start" x="8" y="-571.5" font-family="sans-Serif" font-weight="bold" font-size="20.00" fill="#e2e8f0">PWN::Plugins - Selected categories from
|
|
12
|
+
<text xml:space="preserve" text-anchor="start" x="8" y="-571.5" font-family="sans-Serif" font-weight="bold" font-size="20.00" fill="#e2e8f0">PWN::Plugins - Selected categories from 108 plugin modules</text>
|
|
13
13
|
<g id="clust1" class="cluster">
|
|
14
14
|
<title>cluster_cat</title>
|
|
15
15
|
</g>
|
|
16
16
|
<!-- Root -->
|
|
17
17
|
<g id="node1" class="node">
|
|
18
18
|
<title>Root</title>
|
|
19
|
-
<path fill="#7dd3fc" stroke="#334155" stroke-width="2" d="
|
|
20
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
19
|
+
<path fill="#7dd3fc" stroke="#334155" stroke-width="2" d="M108.38,-303.25C108.38,-303.25 32.38,-303.25 32.38,-303.25 26.38,-303.25 20.38,-297.25 20.38,-291.25 20.38,-291.25 20.38,-279.25 20.38,-279.25 20.38,-273.25 26.38,-267.25 32.38,-267.25 32.38,-267.25 108.38,-267.25 108.38,-267.25 114.38,-267.25 120.38,-273.25 120.38,-279.25 120.38,-279.25 120.38,-291.25 120.38,-291.25 120.38,-297.25 114.38,-303.25 108.38,-303.25"/>
|
|
20
|
+
<text xml:space="preserve" text-anchor="middle" x="70.38" y="-279.82" font-family="sans-Serif" font-size="14.00" fill="#0f172a">PWN::Plugins</text>
|
|
21
21
|
</g>
|
|
22
22
|
<!-- Web -->
|
|
23
23
|
<g id="node2" class="node">
|
|
24
24
|
<title>Web</title>
|
|
25
|
-
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="
|
|
26
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
25
|
+
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="M281.12,-546.25C281.12,-546.25 240.38,-546.25 240.38,-546.25 234.38,-546.25 228.38,-540.25 228.38,-534.25 228.38,-534.25 228.38,-522.25 228.38,-522.25 228.38,-516.25 234.38,-510.25 240.38,-510.25 240.38,-510.25 281.12,-510.25 281.12,-510.25 287.12,-510.25 293.12,-516.25 293.12,-522.25 293.12,-522.25 293.12,-534.25 293.12,-534.25 293.12,-540.25 287.12,-546.25 281.12,-546.25"/>
|
|
26
|
+
<text xml:space="preserve" text-anchor="middle" x="260.75" y="-524.95" font-family="sans-Serif" font-size="9.00" fill="#0f172a">Web / Proxy</text>
|
|
27
27
|
</g>
|
|
28
28
|
<!-- Root->Web -->
|
|
29
29
|
<g id="edge1" class="edge">
|
|
30
30
|
<title>Root->Web</title>
|
|
31
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
32
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
31
|
+
<path fill="none" stroke="#94a3b8" d="M81.18,-303.98C102.57,-343.65 156.67,-437.72 220.38,-501.25 221.81,-502.68 223.32,-504.08 224.89,-505.44"/>
|
|
32
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="223.25,-506.82 229.23,-508.98 225.91,-503.56 223.25,-506.82"/>
|
|
33
33
|
</g>
|
|
34
34
|
<!-- Net -->
|
|
35
35
|
<g id="node3" class="node">
|
|
36
36
|
<title>Net</title>
|
|
37
|
-
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="
|
|
38
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
37
|
+
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="M275.75,-492.25C275.75,-492.25 245.75,-492.25 245.75,-492.25 239.75,-492.25 233.75,-486.25 233.75,-480.25 233.75,-480.25 233.75,-468.25 233.75,-468.25 233.75,-462.25 239.75,-456.25 245.75,-456.25 245.75,-456.25 275.75,-456.25 275.75,-456.25 281.75,-456.25 287.75,-462.25 287.75,-468.25 287.75,-468.25 287.75,-480.25 287.75,-480.25 287.75,-486.25 281.75,-492.25 275.75,-492.25"/>
|
|
38
|
+
<text xml:space="preserve" text-anchor="middle" x="260.75" y="-470.95" font-family="sans-Serif" font-size="9.00" fill="#0f172a">Network</text>
|
|
39
39
|
</g>
|
|
40
40
|
<!-- Root->Net -->
|
|
41
41
|
<g id="edge2" class="edge">
|
|
42
42
|
<title>Root->Net</title>
|
|
43
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
44
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
43
|
+
<path fill="none" stroke="#94a3b8" d="M86.24,-304.01C111.76,-335.58 166.38,-400.45 220.38,-447.25 222.63,-449.2 225.03,-451.14 227.49,-453.03"/>
|
|
44
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="226,-454.55 232.08,-456.43 228.5,-451.17 226,-454.55"/>
|
|
45
45
|
</g>
|
|
46
46
|
<!-- Xpl -->
|
|
47
47
|
<g id="node4" class="node">
|
|
48
48
|
<title>Xpl</title>
|
|
49
|
-
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="
|
|
50
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
49
|
+
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="M280.75,-438.25C280.75,-438.25 240.75,-438.25 240.75,-438.25 234.75,-438.25 228.75,-432.25 228.75,-426.25 228.75,-426.25 228.75,-414.25 228.75,-414.25 228.75,-408.25 234.75,-402.25 240.75,-402.25 240.75,-402.25 280.75,-402.25 280.75,-402.25 286.75,-402.25 292.75,-408.25 292.75,-414.25 292.75,-414.25 292.75,-426.25 292.75,-426.25 292.75,-432.25 286.75,-438.25 280.75,-438.25"/>
|
|
50
|
+
<text xml:space="preserve" text-anchor="middle" x="260.75" y="-416.95" font-family="sans-Serif" font-size="9.00" fill="#0f172a">Exploitation</text>
|
|
51
51
|
</g>
|
|
52
52
|
<!-- Root->Xpl -->
|
|
53
53
|
<g id="edge3" class="edge">
|
|
54
54
|
<title>Root->Xpl</title>
|
|
55
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
56
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
55
|
+
<path fill="none" stroke="#94a3b8" d="M97.07,-304.19C126.65,-325.91 176.77,-362.5 220.38,-393.25 222.34,-394.64 224.36,-396.05 226.41,-397.48"/>
|
|
56
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="225.2,-399.2 231.33,-400.89 227.6,-395.74 225.2,-399.2"/>
|
|
57
57
|
</g>
|
|
58
58
|
<!-- Osint -->
|
|
59
59
|
<g id="node5" class="node">
|
|
60
60
|
<title>Osint</title>
|
|
61
|
-
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="
|
|
62
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
61
|
+
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="M275.75,-384.25C275.75,-384.25 245.75,-384.25 245.75,-384.25 239.75,-384.25 233.75,-378.25 233.75,-372.25 233.75,-372.25 233.75,-360.25 233.75,-360.25 233.75,-354.25 239.75,-348.25 245.75,-348.25 245.75,-348.25 275.75,-348.25 275.75,-348.25 281.75,-348.25 287.75,-354.25 287.75,-360.25 287.75,-360.25 287.75,-372.25 287.75,-372.25 287.75,-378.25 281.75,-384.25 275.75,-384.25"/>
|
|
62
|
+
<text xml:space="preserve" text-anchor="middle" x="260.75" y="-362.95" font-family="sans-Serif" font-size="9.00" fill="#0f172a">OSINT</text>
|
|
63
63
|
</g>
|
|
64
64
|
<!-- Root->Osint -->
|
|
65
65
|
<g id="edge4" class="edge">
|
|
66
66
|
<title>Root->Osint</title>
|
|
67
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
68
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
67
|
+
<path fill="none" stroke="#94a3b8" d="M115.54,-304.24C149.51,-318.85 195.71,-338.71 226.57,-351.98"/>
|
|
68
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="225.56,-353.84 231.91,-354.28 227.22,-349.98 225.56,-353.84"/>
|
|
69
69
|
</g>
|
|
70
70
|
<!-- Data -->
|
|
71
71
|
<g id="node6" class="node">
|
|
72
72
|
<title>Data</title>
|
|
73
|
-
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="
|
|
74
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
73
|
+
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="M279.62,-330.25C279.62,-330.25 241.88,-330.25 241.88,-330.25 235.88,-330.25 229.88,-324.25 229.88,-318.25 229.88,-318.25 229.88,-306.25 229.88,-306.25 229.88,-300.25 235.88,-294.25 241.88,-294.25 241.88,-294.25 279.62,-294.25 279.62,-294.25 285.62,-294.25 291.62,-300.25 291.62,-306.25 291.62,-306.25 291.62,-318.25 291.62,-318.25 291.62,-324.25 285.62,-330.25 279.62,-330.25"/>
|
|
74
|
+
<text xml:space="preserve" text-anchor="middle" x="260.75" y="-308.95" font-family="sans-Serif" font-size="9.00" fill="#0f172a">Data / DAO</text>
|
|
75
75
|
</g>
|
|
76
76
|
<!-- Root->Data -->
|
|
77
77
|
<g id="edge5" class="edge">
|
|
78
78
|
<title>Root->Data</title>
|
|
79
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
80
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
79
|
+
<path fill="none" stroke="#94a3b8" d="M121.36,-292.41C153.01,-296.95 193.28,-302.72 222.2,-306.87"/>
|
|
80
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="221.57,-308.9 227.8,-307.67 222.16,-304.74 221.57,-308.9"/>
|
|
81
81
|
</g>
|
|
82
82
|
<!-- Auth -->
|
|
83
83
|
<g id="node7" class="node">
|
|
84
84
|
<title>Auth</title>
|
|
85
|
-
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="
|
|
86
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
85
|
+
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="M275.75,-276.25C275.75,-276.25 245.75,-276.25 245.75,-276.25 239.75,-276.25 233.75,-270.25 233.75,-264.25 233.75,-264.25 233.75,-252.25 233.75,-252.25 233.75,-246.25 239.75,-240.25 245.75,-240.25 245.75,-240.25 275.75,-240.25 275.75,-240.25 281.75,-240.25 287.75,-246.25 287.75,-252.25 287.75,-252.25 287.75,-264.25 287.75,-264.25 287.75,-270.25 281.75,-276.25 275.75,-276.25"/>
|
|
86
|
+
<text xml:space="preserve" text-anchor="middle" x="260.75" y="-254.95" font-family="sans-Serif" font-size="9.00" fill="#0f172a">Auth</text>
|
|
87
87
|
</g>
|
|
88
88
|
<!-- Root->Auth -->
|
|
89
89
|
<g id="edge6" class="edge">
|
|
90
90
|
<title>Root->Auth</title>
|
|
91
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
92
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
91
|
+
<path fill="none" stroke="#94a3b8" d="M121.36,-278.09C154.52,-273.33 197.13,-267.23 226.26,-263.05"/>
|
|
92
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="226.22,-265.18 231.86,-262.25 225.62,-261.02 226.22,-265.18"/>
|
|
93
93
|
</g>
|
|
94
94
|
<!-- HW -->
|
|
95
95
|
<g id="node8" class="node">
|
|
96
96
|
<title>HW</title>
|
|
97
|
-
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="
|
|
98
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
97
|
+
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="M277,-222.25C277,-222.25 244.5,-222.25 244.5,-222.25 238.5,-222.25 232.5,-216.25 232.5,-210.25 232.5,-210.25 232.5,-198.25 232.5,-198.25 232.5,-192.25 238.5,-186.25 244.5,-186.25 244.5,-186.25 277,-186.25 277,-186.25 283,-186.25 289,-192.25 289,-198.25 289,-198.25 289,-210.25 289,-210.25 289,-216.25 283,-222.25 277,-222.25"/>
|
|
98
|
+
<text xml:space="preserve" text-anchor="middle" x="260.75" y="-200.95" font-family="sans-Serif" font-size="9.00" fill="#0f172a">Hardware</text>
|
|
99
99
|
</g>
|
|
100
100
|
<!-- Root->HW -->
|
|
101
101
|
<g id="edge7" class="edge">
|
|
102
102
|
<title>Root->HW</title>
|
|
103
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
104
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
103
|
+
<path fill="none" stroke="#94a3b8" d="M115.54,-266.26C149,-251.87 194.34,-232.38 225.18,-219.11"/>
|
|
104
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="225.85,-221.11 230.53,-216.81 224.19,-217.26 225.85,-221.11"/>
|
|
105
105
|
</g>
|
|
106
106
|
<!-- CI -->
|
|
107
107
|
<g id="node9" class="node">
|
|
108
108
|
<title>CI</title>
|
|
109
|
-
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="
|
|
110
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
109
|
+
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="M281.12,-168.25C281.12,-168.25 240.38,-168.25 240.38,-168.25 234.38,-168.25 228.38,-162.25 228.38,-156.25 228.38,-156.25 228.38,-144.25 228.38,-144.25 228.38,-138.25 234.38,-132.25 240.38,-132.25 240.38,-132.25 281.12,-132.25 281.12,-132.25 287.12,-132.25 293.12,-138.25 293.12,-144.25 293.12,-144.25 293.12,-156.25 293.12,-156.25 293.12,-162.25 287.12,-168.25 281.12,-168.25"/>
|
|
110
|
+
<text xml:space="preserve" text-anchor="middle" x="260.75" y="-146.95" font-family="sans-Serif" font-size="9.00" fill="#0f172a">CI / DevOps</text>
|
|
111
111
|
</g>
|
|
112
112
|
<!-- Root->CI -->
|
|
113
113
|
<g id="edge8" class="edge">
|
|
114
114
|
<title>Root->CI</title>
|
|
115
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
116
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
115
|
+
<path fill="none" stroke="#94a3b8" d="M97.07,-266.31C126.65,-244.59 176.77,-208 220.38,-177.25 222.34,-175.86 224.36,-174.45 226.41,-173.02"/>
|
|
116
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="227.6,-174.76 231.33,-169.61 225.2,-171.3 227.6,-174.76"/>
|
|
117
117
|
</g>
|
|
118
118
|
<!-- Comm -->
|
|
119
119
|
<g id="node10" class="node">
|
|
120
120
|
<title>Comm</title>
|
|
121
|
-
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="
|
|
122
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
121
|
+
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="M275.75,-114.25C275.75,-114.25 245.75,-114.25 245.75,-114.25 239.75,-114.25 233.75,-108.25 233.75,-102.25 233.75,-102.25 233.75,-90.25 233.75,-90.25 233.75,-84.25 239.75,-78.25 245.75,-78.25 245.75,-78.25 275.75,-78.25 275.75,-78.25 281.75,-78.25 287.75,-84.25 287.75,-90.25 287.75,-90.25 287.75,-102.25 287.75,-102.25 287.75,-108.25 281.75,-114.25 275.75,-114.25"/>
|
|
122
|
+
<text xml:space="preserve" text-anchor="middle" x="260.75" y="-92.95" font-family="sans-Serif" font-size="9.00" fill="#0f172a">Comms</text>
|
|
123
123
|
</g>
|
|
124
124
|
<!-- Root->Comm -->
|
|
125
125
|
<g id="edge9" class="edge">
|
|
126
126
|
<title>Root->Comm</title>
|
|
127
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
128
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
127
|
+
<path fill="none" stroke="#94a3b8" d="M86.24,-266.49C111.76,-234.92 166.38,-170.05 220.38,-123.25 222.63,-121.3 225.03,-119.36 227.49,-117.47"/>
|
|
128
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="228.5,-119.33 232.08,-114.07 226,-115.95 228.5,-119.33"/>
|
|
129
129
|
</g>
|
|
130
130
|
<!-- Util -->
|
|
131
131
|
<g id="node11" class="node">
|
|
132
132
|
<title>Util</title>
|
|
133
|
-
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="
|
|
134
|
-
<text xml:space="preserve" text-anchor="middle" x="
|
|
133
|
+
<path fill="#6ee7b7" stroke="#334155" stroke-width="1.2" d="M275.75,-60.25C275.75,-60.25 245.75,-60.25 245.75,-60.25 239.75,-60.25 233.75,-54.25 233.75,-48.25 233.75,-48.25 233.75,-36.25 233.75,-36.25 233.75,-30.25 239.75,-24.25 245.75,-24.25 245.75,-24.25 275.75,-24.25 275.75,-24.25 281.75,-24.25 287.75,-30.25 287.75,-36.25 287.75,-36.25 287.75,-48.25 287.75,-48.25 287.75,-54.25 281.75,-60.25 275.75,-60.25"/>
|
|
134
|
+
<text xml:space="preserve" text-anchor="middle" x="260.75" y="-38.95" font-family="sans-Serif" font-size="9.00" fill="#0f172a">Utility</text>
|
|
135
135
|
</g>
|
|
136
136
|
<!-- Root->Util -->
|
|
137
137
|
<g id="edge10" class="edge">
|
|
138
138
|
<title>Root->Util</title>
|
|
139
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
140
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
139
|
+
<path fill="none" stroke="#94a3b8" d="M81.18,-266.52C102.57,-226.85 156.67,-132.78 220.38,-69.25 222.55,-67.08 224.93,-64.97 227.4,-62.95"/>
|
|
140
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="228.61,-64.66 232.08,-59.33 226.05,-61.34 228.61,-64.66"/>
|
|
141
141
|
</g>
|
|
142
142
|
<!-- w -->
|
|
143
143
|
<g id="node12" class="node">
|
|
@@ -150,8 +150,8 @@
|
|
|
150
150
|
<!-- Web->w -->
|
|
151
151
|
<g id="edge11" class="edge">
|
|
152
152
|
<title>Web->w</title>
|
|
153
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
154
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="411.
|
|
153
|
+
<path fill="none" stroke="#94a3b8" d="M293.26,-528.53C323.93,-528.81 371.64,-529.23 411.79,-529.59"/>
|
|
154
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="411.67,-531.69 417.68,-529.65 411.7,-527.49 411.67,-531.69"/>
|
|
155
155
|
</g>
|
|
156
156
|
<!-- n -->
|
|
157
157
|
<g id="node13" class="node">
|
|
@@ -163,8 +163,8 @@
|
|
|
163
163
|
<!-- Net->n -->
|
|
164
164
|
<g id="edge12" class="edge">
|
|
165
165
|
<title>Net->n</title>
|
|
166
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
167
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="424.
|
|
166
|
+
<path fill="none" stroke="#94a3b8" d="M288.24,-474.25C321.72,-474.25 380.35,-474.25 424.93,-474.25"/>
|
|
167
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="424.73,-476.35 430.73,-474.25 424.73,-472.15 424.73,-476.35"/>
|
|
168
168
|
</g>
|
|
169
169
|
<!-- x -->
|
|
170
170
|
<g id="node14" class="node">
|
|
@@ -176,8 +176,8 @@
|
|
|
176
176
|
<!-- Xpl->x -->
|
|
177
177
|
<g id="edge13" class="edge">
|
|
178
178
|
<title>Xpl->x</title>
|
|
179
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
180
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="435.
|
|
179
|
+
<path fill="none" stroke="#94a3b8" d="M293.26,-420.25C330.3,-420.25 392.22,-420.25 435.64,-420.25"/>
|
|
180
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="435.47,-422.35 441.47,-420.25 435.47,-418.15 435.47,-422.35"/>
|
|
181
181
|
</g>
|
|
182
182
|
<!-- o -->
|
|
183
183
|
<g id="node15" class="node">
|
|
@@ -189,8 +189,8 @@
|
|
|
189
189
|
<!-- Osint->o -->
|
|
190
190
|
<g id="edge14" class="edge">
|
|
191
191
|
<title>Osint->o</title>
|
|
192
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
193
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
192
|
+
<path fill="none" stroke="#94a3b8" d="M288.24,-366.25C323.03,-366.25 384.99,-366.25 430.11,-366.25"/>
|
|
193
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="429.97,-368.35 435.97,-366.25 429.97,-364.15 429.97,-368.35"/>
|
|
194
194
|
</g>
|
|
195
195
|
<!-- d -->
|
|
196
196
|
<g id="node16" class="node">
|
|
@@ -202,21 +202,21 @@
|
|
|
202
202
|
<!-- Data->d -->
|
|
203
203
|
<g id="edge15" class="edge">
|
|
204
204
|
<title>Data->d</title>
|
|
205
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
205
|
+
<path fill="none" stroke="#94a3b8" d="M291.86,-312.25C321.1,-312.25 366.76,-312.25 406.34,-312.25"/>
|
|
206
206
|
<polygon fill="#94a3b8" stroke="#94a3b8" points="406.14,-314.35 412.14,-312.25 406.14,-310.15 406.14,-314.35"/>
|
|
207
207
|
</g>
|
|
208
208
|
<!-- a -->
|
|
209
209
|
<g id="node17" class="node">
|
|
210
210
|
<title>a</title>
|
|
211
|
-
<path fill="#fcd34d" stroke="#334155" stroke-width="1.2" d="
|
|
211
|
+
<path fill="#fcd34d" stroke="#334155" stroke-width="1.2" d="M558.88,-276.25C558.88,-276.25 413.12,-276.25 413.12,-276.25 407.12,-276.25 401.12,-270.25 401.12,-264.25 401.12,-264.25 401.12,-252.25 401.12,-252.25 401.12,-246.25 407.12,-240.25 413.12,-240.25 413.12,-240.25 558.88,-240.25 558.88,-240.25 564.88,-240.25 570.88,-246.25 570.88,-252.25 570.88,-252.25 570.88,-264.25 570.88,-264.25 570.88,-270.25 564.88,-276.25 558.88,-276.25"/>
|
|
212
212
|
<text xml:space="preserve" text-anchor="middle" x="486" y="-260.2" font-family="sans-Serif" font-size="9.00" fill="#0f172a">OAuth2 · BasicAuth</text>
|
|
213
|
-
<text xml:space="preserve" text-anchor="middle" x="486" y="-249.7" font-family="sans-Serif" font-size="9.00" fill="#0f172a">AuthenticationHelper · Vault</text>
|
|
213
|
+
<text xml:space="preserve" text-anchor="middle" x="486" y="-249.7" font-family="sans-Serif" font-size="9.00" fill="#0f172a">AuthenticationHelper · Vault · YubiKey</text>
|
|
214
214
|
</g>
|
|
215
215
|
<!-- Auth->a -->
|
|
216
216
|
<g id="edge16" class="edge">
|
|
217
217
|
<title>Auth->a</title>
|
|
218
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
219
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="
|
|
218
|
+
<path fill="none" stroke="#94a3b8" d="M288.24,-258.25C314.28,-258.25 355.54,-258.25 393.57,-258.25"/>
|
|
219
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="393.11,-260.35 399.11,-258.25 393.11,-256.15 393.11,-260.35"/>
|
|
220
220
|
</g>
|
|
221
221
|
<!-- h -->
|
|
222
222
|
<g id="node18" class="node">
|
|
@@ -228,8 +228,8 @@
|
|
|
228
228
|
<!-- HW->h -->
|
|
229
229
|
<g id="edge17" class="edge">
|
|
230
230
|
<title>HW->h</title>
|
|
231
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
232
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="412.
|
|
231
|
+
<path fill="none" stroke="#94a3b8" d="M289.57,-204.25C320.12,-204.25 370.39,-204.25 412.29,-204.25"/>
|
|
232
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="412.23,-206.35 418.23,-204.25 412.23,-202.15 412.23,-206.35"/>
|
|
233
233
|
</g>
|
|
234
234
|
<!-- c -->
|
|
235
235
|
<g id="node19" class="node">
|
|
@@ -241,8 +241,8 @@
|
|
|
241
241
|
<!-- CI->c -->
|
|
242
242
|
<g id="edge18" class="edge">
|
|
243
243
|
<title>CI->c</title>
|
|
244
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
245
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="422.
|
|
244
|
+
<path fill="none" stroke="#94a3b8" d="M293.26,-150.25C326.6,-150.25 380.08,-150.25 422.1,-150.25"/>
|
|
245
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="422.03,-152.35 428.03,-150.25 422.03,-148.15 422.03,-152.35"/>
|
|
246
246
|
</g>
|
|
247
247
|
<!-- m -->
|
|
248
248
|
<g id="node20" class="node">
|
|
@@ -254,8 +254,8 @@
|
|
|
254
254
|
<!-- Comm->m -->
|
|
255
255
|
<g id="edge19" class="edge">
|
|
256
256
|
<title>Comm->m</title>
|
|
257
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
258
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="399.
|
|
257
|
+
<path fill="none" stroke="#94a3b8" d="M288.24,-96.25C315.75,-96.25 360.24,-96.25 399.97,-96.25"/>
|
|
258
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="399.81,-98.35 405.81,-96.25 399.81,-94.15 399.81,-98.35"/>
|
|
259
259
|
</g>
|
|
260
260
|
<!-- u -->
|
|
261
261
|
<g id="node21" class="node">
|
|
@@ -270,8 +270,8 @@
|
|
|
270
270
|
<!-- Util->u -->
|
|
271
271
|
<g id="edge20" class="edge">
|
|
272
272
|
<title>Util->u</title>
|
|
273
|
-
<path fill="none" stroke="#94a3b8" d="
|
|
274
|
-
<polygon fill="#94a3b8" stroke="#94a3b8" points="408.
|
|
273
|
+
<path fill="none" stroke="#94a3b8" d="M288.24,-40.83C317.76,-39.24 366.86,-36.6 408.62,-34.36"/>
|
|
274
|
+
<polygon fill="#94a3b8" stroke="#94a3b8" points="408.67,-36.46 414.55,-34.04 408.44,-32.26 408.67,-36.46"/>
|
|
275
275
|
</g>
|
|
276
276
|
</g>
|
|
277
277
|
</svg>
|
|
@@ -5,6 +5,9 @@ the goal; the agent plans a sequence of tool calls (`pwn_eval`, `shell`,
|
|
|
5
5
|
`memory_*`, `skill_*`, `mistakes_*`, `reward_*`, `curriculum_*`, `extro_*`,
|
|
6
6
|
`agent_*`, ...), executes them against the live process, observes the results,
|
|
7
7
|
and checks completion against the original request and available host evidence.
|
|
8
|
+
Unspecified tool writes go to `~/.pwn/workspaces/runtime`. A path outside that
|
|
9
|
+
directory is allowed only when the original request names it. See
|
|
10
|
+
[Operability](Operability.md).
|
|
8
11
|
Learning records failures and corrections; it cannot guarantee nonrecurrence.
|
|
9
12
|
|
|
10
13
|
## Two ways to run it
|
|
@@ -336,7 +339,9 @@ anthropic` opens that nested mapping, and `/vault edit ai anthropic model`
|
|
|
336
339
|
opens a scalar. Tokens identify one nested key path, never filenames or multiple
|
|
337
340
|
disjoint scopes. The target and decryptor are the same `driver_opts.pwn_env_path`
|
|
338
341
|
and `driver_opts.pwn_dec_path` used by `pwn-vault`, defaulting to
|
|
339
|
-
`~/.pwn/pwn.yaml` and its existing `.decryptor` sidecar.
|
|
342
|
+
`~/.pwn/pwn.yaml` and its existing legacy `.decryptor` sidecar. Hardware-backed
|
|
343
|
+
[YubiKey vaults](YubiKey-Vaults.md) are detected without requiring a sidecar.
|
|
344
|
+
Unknown paths are rejected; edit the parent mapping
|
|
340
345
|
to add a new key. Arrays are edited as a whole, not by numeric path indices.
|
|
341
346
|
Existing non-null types must be retained; an existing null may remain null or
|
|
342
347
|
be replaced by a YAML value. The root must retain an `ai` mapping, a supported
|
|
@@ -355,8 +360,9 @@ only shipped schema key names, never reads/decrypts the vault, and never offers
|
|
|
355
360
|
configuration values; existing custom keys can be typed explicitly.
|
|
356
361
|
|
|
357
362
|
Plaintext is decrypted/edited in memory. Only encrypted bytes enter the private
|
|
358
|
-
temporary file, which is atomically renamed over the vault using
|
|
359
|
-
AES-256-CBC
|
|
363
|
+
temporary file, which is atomically renamed over the vault using its existing
|
|
364
|
+
backend: legacy AES-256-CBC key/IV or a fresh authenticated YubiKey envelope.
|
|
365
|
+
The device is never provisioned and the legacy decryptor is not regenerated.
|
|
360
366
|
Save re-reads the current document, preserves changes outside the selected scope,
|
|
361
367
|
and refuses a changed selected scope (the whole document for unscoped edits).
|
|
362
368
|
Editor instances serialize saves with a directory lock; a final ciphertext check
|
|
@@ -642,7 +648,7 @@ After the reply, `Learning.auto_introspect` calls `rsi_tick`. That tick reads ES
|
|
|
642
648
|
|
|
643
649
|
## What the agent can call
|
|
644
650
|
|
|
645
|
-
16 toolsets · **
|
|
651
|
+
16 toolsets · **152 tools** - full table at
|
|
646
652
|
[Agent Tool Registry](Agent-Tool-Registry.md).
|
|
647
653
|
|
|
648
654
|
The two that matter most:
|
|
@@ -20,7 +20,7 @@ module PWN
|
|
|
20
20
|
'learning' => %w[learning.jsonl learning lessons.json memory.json memory.archive.json memory.idx mistakes.json policy policy.json policy_traj.jsonl curriculum curriculum_kpi.jsonl extrospection.json finetune preferences.jsonl reward_sentinel.json skill_review.jsonl operator-learning-review.jsonl],
|
|
21
21
|
'artifacts' => %w[artifacts exports findings.jsonl engagements corpora binws redb ghidra sandbox_snapshots],
|
|
22
22
|
'state' => %w[swarm cron agents.yml open_goal.json jobs missions runs metrics metrics.json capabilities.json],
|
|
23
|
-
'logs' => %w[logs], 'cache' => %w[cache], 'tmp' => %w[
|
|
23
|
+
'logs' => %w[logs], 'cache' => %w[cache], 'tmp' => %w[workspaces/runtime],
|
|
24
24
|
'maintenance' => %w[maintenance session_cleanup_archive],
|
|
25
25
|
'backups' => %w[backup]
|
|
26
26
|
}.freeze
|
|
@@ -38,16 +38,17 @@ module PWN
|
|
|
38
38
|
raise IOError, 'Symlinked maintenance policy' if File.symlink?(path)
|
|
39
39
|
|
|
40
40
|
publish(path, JSON.pretty_generate(POLICY)) unless File.exist?(path)
|
|
41
|
-
|
|
41
|
+
private_directory(File.join(root, 'cache')) unless File.exist?(File.join(root, 'cache'))
|
|
42
|
+
private_directory(File.join(root, 'workspaces', 'runtime')) unless File.exist?(File.join(root, 'workspaces', 'runtime'))
|
|
42
43
|
layout = File.join(directory, 'layout.json')
|
|
43
44
|
raise IOError, 'Unsafe maintenance inventory' if File.symlink?(layout)
|
|
44
45
|
|
|
45
46
|
previous = File.file?(layout) ? JSON.parse(File.binread(layout)) : nil
|
|
46
|
-
raise IOError, 'Unknown maintenance inventory version' if previous && ![1, 2].include?(previous['version'])
|
|
47
|
+
raise IOError, 'Unknown maintenance inventory version' if previous && ![1, 2, 3].include?(previous['version'])
|
|
47
48
|
|
|
48
|
-
publish(layout, JSON.generate(version:
|
|
49
|
+
publish(layout, JSON.generate(version: 3, categories: STORAGE)) unless previous && previous['version'] == 3
|
|
49
50
|
end
|
|
50
|
-
{ version:
|
|
51
|
+
{ version: 3, root: directory }
|
|
51
52
|
end
|
|
52
53
|
|
|
53
54
|
# Startup performs only fixed-path checks and one coalesced request write.
|
|
@@ -368,7 +369,7 @@ module PWN
|
|
|
368
369
|
def self.register_disposable(path:, category:, expires_at: nil)
|
|
369
370
|
raise ArgumentError, 'Not a disposable category' unless %w[cache tmp logs].include?(category)
|
|
370
371
|
|
|
371
|
-
root =
|
|
372
|
+
root = disposable_directory(category)
|
|
372
373
|
path = File.expand_path(path)
|
|
373
374
|
raise IOError, 'Disposable path escapes its category' unless path.start_with?("#{root}/") && File.realpath(path) == path
|
|
374
375
|
raise IOError, 'Disposable must be an owned regular file' unless File.file?(path) && File.stat(path).uid == Process.uid
|
|
@@ -421,7 +422,7 @@ module PWN
|
|
|
421
422
|
# Known disposable input producer. The permanent lease covers publication,
|
|
422
423
|
# consumption and unlink; a killed consumer leaves a registered exact file.
|
|
423
424
|
def self.temporary(bytes:)
|
|
424
|
-
directory = private_directory(
|
|
425
|
+
directory = private_directory(disposable_directory('tmp'))
|
|
425
426
|
path = File.join(directory, "input-#{SecureRandom.hex(12)}.txt")
|
|
426
427
|
File.open("#{path}.lease", File::RDWR | File::CREAT | File::NOFOLLOW, 0o600) do |lease|
|
|
427
428
|
lease.flock(File::LOCK_EX)
|
|
@@ -465,6 +466,14 @@ module PWN
|
|
|
465
466
|
path
|
|
466
467
|
end
|
|
467
468
|
|
|
469
|
+
# Disposable category tmp lives in the runtime workspace, not ~/.pwn/tmp.
|
|
470
|
+
def self.disposable_directory(category)
|
|
471
|
+
raise ArgumentError, 'Not a disposable category' unless %w[cache tmp logs].include?(category)
|
|
472
|
+
|
|
473
|
+
base = File.join(Dir.home, '.pwn')
|
|
474
|
+
category == 'tmp' ? File.join(base, 'workspaces', 'runtime') : File.join(base, category)
|
|
475
|
+
end
|
|
476
|
+
|
|
468
477
|
def self.private_directory(path)
|
|
469
478
|
ancestor = File.expand_path(path)
|
|
470
479
|
loop do
|
|
@@ -499,7 +508,7 @@ module PWN
|
|
|
499
508
|
return 'unknown_schema' unless row.is_a?(Hash) && row['version'] == 1 && %w[cache tmp logs].include?(row['category']) && row['expires_at'].is_a?(Integer)
|
|
500
509
|
|
|
501
510
|
path = row['path']
|
|
502
|
-
root =
|
|
511
|
+
root = disposable_directory(row['category'])
|
|
503
512
|
return 'unsafe_path' unless path.is_a?(String) && path.start_with?("#{root}/") && File.expand_path(path) == path
|
|
504
513
|
return 'missing' unless File.exist?(path)
|
|
505
514
|
return 'unsafe_path' unless File.realpath(path) == path && File.file?(path) && File.stat(path).uid == Process.uid
|
|
@@ -574,7 +583,7 @@ module PWN
|
|
|
574
583
|
next if dry_run
|
|
575
584
|
|
|
576
585
|
unless result[:ledger]
|
|
577
|
-
directory =
|
|
586
|
+
directory = PWN::Backups.directory(label: 'disposable')
|
|
578
587
|
result[:ledger] = File.join(directory, 'ledger.json')
|
|
579
588
|
end
|
|
580
589
|
backup_path = File.join(File.dirname(result[:ledger]), "#{Digest::SHA256.hexdigest(path)}.bin")
|
|
@@ -788,11 +797,14 @@ module PWN
|
|
|
788
797
|
# children. Restoring a ledger alone never undoes deletion or migration.
|
|
789
798
|
def self.recovery_status(ledger:)
|
|
790
799
|
root = File.join(Dir.home, '.pwn')
|
|
791
|
-
prefixes = %w[maintenance session_cleanup_archive learning/migrations].map { |name| "#{File.join(root, name)}/" }
|
|
800
|
+
prefixes = %w[backup maintenance session_cleanup_archive learning/migrations].map { |name| "#{File.join(root, name)}/" }
|
|
792
801
|
raise IOError, 'Unsafe recovery ledger' unless prefixes.any? { |prefix| ledger.start_with?(prefix) } && File.realpath(ledger) == ledger
|
|
793
802
|
|
|
794
803
|
data = JSON.parse(File.binread(ledger))
|
|
795
804
|
operation = data['operation']
|
|
805
|
+
operation = 'session_cleanup' if ledger.include?('/backup/') && data['records'].is_a?(Array) && data['deleted_ids'].is_a?(Array)
|
|
806
|
+
operation = 'continuation_retirement' if ledger.include?('/backup/') && data['backup'] == File.join(File.dirname(ledger), 'personas.json')
|
|
807
|
+
operation = 'session_layout' if ledger.include?('/backup/') && File.basename(ledger) == 'layout.json'
|
|
796
808
|
operation = 'session_layout' if File.basename(ledger) == 'layout.json' && ledger.start_with?("#{File.join(root, 'session_cleanup_archive')}/") && data['records'].is_a?(Array)
|
|
797
809
|
operation = 'learning_migration' if ledger.start_with?("#{File.join(root, 'learning', 'migrations')}/") && data['version'] == 1 && data['before_sha256'] == File.basename(ledger, '.json')
|
|
798
810
|
operation = 'session_cleanup' if ledger.start_with?("#{File.join(root, 'session_cleanup_archive')}/") && data['dry_run'] == false && data['records'].is_a?(Array) && data['deleted_ids'].is_a?(Array)
|
|
@@ -841,7 +853,7 @@ module PWN
|
|
|
841
853
|
end
|
|
842
854
|
end
|
|
843
855
|
root = File.join(Dir.home, '.pwn', 'maintenance', 'quarantine')
|
|
844
|
-
raise IOError, 'Unsafe recovery ledger' unless ledger.start_with?("#{
|
|
856
|
+
raise IOError, 'Unsafe recovery ledger' unless [root, File.join(Dir.home, '.pwn', 'backup')].any? { |base| ledger.start_with?("#{base}/") } && File.realpath(ledger) == ledger
|
|
845
857
|
|
|
846
858
|
data = JSON.parse(File.binread(ledger))
|
|
847
859
|
raise IOError, 'Unknown recovery ledger' unless data['operation'] == 'routine' && data['records'].is_a?(Array)
|
|
@@ -851,7 +863,7 @@ module PWN
|
|
|
851
863
|
data['records'].each do |row|
|
|
852
864
|
path = row.fetch('path')
|
|
853
865
|
category = row.fetch('category')
|
|
854
|
-
target_root =
|
|
866
|
+
target_root = disposable_directory(category)
|
|
855
867
|
backup_path = row.fetch('backup')
|
|
856
868
|
raise IOError, 'Unsafe recovery path' unless %w[cache tmp logs].include?(category) && path.start_with?("#{target_root}/") && File.expand_path(path) == path && File.realpath(File.dirname(path)) == File.dirname(path)
|
|
857
869
|
raise IOError, 'Unsafe recovery backup' unless File.dirname(backup_path) == File.dirname(ledger) && File.realpath(backup_path) == backup_path && Digest::SHA256.file(backup_path).hexdigest == row['sha256']
|
|
@@ -1021,7 +1033,7 @@ module PWN
|
|
|
1021
1033
|
File.open(PWN::Sessions.support_path(kind: :lease, session_id: id), File::RDWR | File::CREAT | File::NOFOLLOW, 0o600) do |lease|
|
|
1022
1034
|
raise IOError, 'Swarm continuation active' unless lease.flock(File::LOCK_EX | File::LOCK_NB)
|
|
1023
1035
|
|
|
1024
|
-
directory =
|
|
1036
|
+
directory = PWN::Backups.directory(label: 'continuation')
|
|
1025
1037
|
backup_path = File.join(directory, 'personas.json')
|
|
1026
1038
|
publish(backup_path, bytes)
|
|
1027
1039
|
raise IOError, 'Continuation backup mismatch' unless File.binread(backup_path) == bytes
|
|
@@ -1141,7 +1153,7 @@ module PWN
|
|
|
1141
1153
|
def self.publish(path, bytes)
|
|
1142
1154
|
temporary = "#{path}.#{SecureRandom.hex(8)}.tmp"
|
|
1143
1155
|
root = File.join(Dir.home, '.pwn')
|
|
1144
|
-
category = %w[cache tmp].find { |name| path.start_with?("#{
|
|
1156
|
+
category = %w[cache tmp].find { |name| path.start_with?("#{disposable_directory(name)}/") }
|
|
1145
1157
|
if category
|
|
1146
1158
|
directory = private_directory(File.join(root, 'maintenance', 'atomic'))
|
|
1147
1159
|
journal = File.join(directory, "#{SecureRandom.hex(12)}.json")
|
|
@@ -1183,7 +1195,7 @@ module PWN
|
|
|
1183
1195
|
next if days.nil? || (expired_only && row.fetch('created_at') > Time.now.to_i - (days * 86_400))
|
|
1184
1196
|
|
|
1185
1197
|
path, target = row.values_at('path', 'target')
|
|
1186
|
-
base = "#{
|
|
1198
|
+
base = "#{disposable_directory(row['category'])}/"
|
|
1187
1199
|
raise IOError, 'Unsafe atomic path' unless [path, target].all? { |name| name.is_a?(String) && name.start_with?(base) && File.expand_path(name) == name } && File.dirname(path) == File.dirname(target) && path.match?(/\A#{Regexp.escape(target)}\.[a-f0-9]{16}\.tmp\z/)
|
|
1188
1200
|
next unless File.exist?(path) || File.symlink?(path)
|
|
1189
1201
|
raise IOError, 'Changed atomic bytes' unless verified_backup?(path, row['sha256']) && File.stat(path).ino == row['inode'] && File.stat(path).dev == row['device']
|
|
@@ -1210,16 +1222,7 @@ module PWN
|
|
|
1210
1222
|
end
|
|
1211
1223
|
|
|
1212
1224
|
def self.backup(path, expected, result)
|
|
1213
|
-
|
|
1214
|
-
base = File.join(Dir.home, '.pwn', 'session_cleanup_archive')
|
|
1215
|
-
raise 'Unsafe archive directory' if File.symlink?(base)
|
|
1216
|
-
|
|
1217
|
-
FileUtils.mkdir_p(base, mode: 0o700)
|
|
1218
|
-
raise 'Unsafe archive permissions' unless File.stat(base).uid == Process.uid && (File.stat(base).mode & 0o777) == 0o700
|
|
1219
|
-
|
|
1220
|
-
result[:archive_dir] = File.join(base, "#{Time.now.utc.strftime('%Y%m%dT%H%M%S')}-#{SecureRandom.hex(8)}")
|
|
1221
|
-
Dir.mkdir(result[:archive_dir], 0o700)
|
|
1222
|
-
end
|
|
1225
|
+
result[:archive_dir] ||= PWN::Backups.directory(label: 'session-cleanup')
|
|
1223
1226
|
expected.each do |name, record|
|
|
1224
1227
|
next unless record
|
|
1225
1228
|
|
|
@@ -1273,6 +1276,9 @@ module PWN
|
|
|
1273
1276
|
locks = []
|
|
1274
1277
|
begin
|
|
1275
1278
|
paths.each do |path|
|
|
1279
|
+
owner = Thread.current[:pwn_learning_write_lock]
|
|
1280
|
+
next if File.basename(path) == '.learning-write.lock' && owner && owner[:pid] == Process.pid && owner[:thread] == Thread.current
|
|
1281
|
+
|
|
1276
1282
|
lock = File.open(path, File::RDWR | File::CREAT | File::NOFOLLOW, 0o600) # rubocop:disable Style/FileOpen -- closed together in ensure
|
|
1277
1283
|
locks << lock
|
|
1278
1284
|
raise 'Dependency writer active' unless lock.flock(File::LOCK_EX | File::LOCK_NB)
|
|
@@ -1327,7 +1333,7 @@ module PWN
|
|
|
1327
1333
|
# Legacy writers block all mutations, including evidence migration.
|
|
1328
1334
|
# One permanent inode serializes CLI, curses and cron maintenance writers.
|
|
1329
1335
|
# Read-only previews never acquire a writer lock or create lock files.
|
|
1330
|
-
def self.with_maintenance_lock(dry_run
|
|
1336
|
+
def self.with_maintenance_lock(dry_run:, &block)
|
|
1331
1337
|
return yield if dry_run
|
|
1332
1338
|
|
|
1333
1339
|
root = PWN::Sessions.sessions_dir
|
|
@@ -1342,8 +1348,16 @@ module PWN
|
|
|
1342
1348
|
|
|
1343
1349
|
begin
|
|
1344
1350
|
Thread.current[:pwn_session_maintenance_lock] = { pid: Process.pid, thread: Thread.current, path: path, file: file }
|
|
1345
|
-
|
|
1351
|
+
learning = PWN::AI::Agent::Learning.send(:learning_lock, nonblocking: true)
|
|
1352
|
+
if learning == :busy
|
|
1353
|
+
Thread.current[:pwn_backup_learning_busy] = true
|
|
1354
|
+
yield
|
|
1355
|
+
else
|
|
1356
|
+
PWN::Backups.transaction(&block)
|
|
1357
|
+
end
|
|
1346
1358
|
ensure
|
|
1359
|
+
PWN::AI::Agent::Learning.send(:learning_unlock, lock: learning) unless learning == :busy
|
|
1360
|
+
Thread.current[:pwn_backup_learning_busy] = nil
|
|
1347
1361
|
Thread.current[:pwn_session_maintenance_lock] = owner
|
|
1348
1362
|
end
|
|
1349
1363
|
end
|
|
@@ -1452,6 +1466,8 @@ module PWN
|
|
|
1452
1466
|
|
|
1453
1467
|
def self.maintenance_transaction(dry_run:, current_session_id:, proc_root:)
|
|
1454
1468
|
preflight = sweep(dry_run: true, current_session_id: current_session_id, proc_root: proc_root)
|
|
1469
|
+
return preflight.merge(apply_blocked: true, evidence_migration: { deferred: 'learning_writer_active', migrated_rows: 0 }) if Thread.current[:pwn_backup_learning_busy] && !dry_run
|
|
1470
|
+
|
|
1455
1471
|
blocked = stopping? || !preflight[:legacy_owners].empty? || Array(preflight[:unresolved_store_remediation]).any?
|
|
1456
1472
|
unless dry_run || blocked
|
|
1457
1473
|
# Private metadata-only preflight survives an interrupted migration.
|