pwn 0.5.783 → 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 +8 -8
- data/README.md +37 -0
- data/Rakefile +19 -1
- data/bin/pwn +2 -1
- data/bin/pwn_setup +1 -1
- data/bin/pwn_web_cache_deception +35 -7
- data/build_gem.sh +1 -1
- data/documentation/AI-Integration.md +7 -5
- data/documentation/Agent-Tool-Registry.md +2 -2
- data/documentation/Backup-Retention.md +82 -0
- data/documentation/Configuration.md +10 -6
- data/documentation/Contributing.md +1 -1
- data/documentation/Cron.md +64 -35
- 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 +7 -6
- data/documentation/Installation.md +254 -10
- data/documentation/Mission-Cancellation.md +134 -0
- data/documentation/Operability.md +17 -0
- data/documentation/Persistence.md +8 -6
- data/documentation/Plugin-Degradation.md +12 -0
- data/documentation/Plugins.md +3 -2
- data/documentation/Reinforcement-Learning.md +5 -6
- 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 -128
- data/documentation/diagrams/dot/cron-scheduling.dot +5 -5
- 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 +1245 -22
- 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/extrospection.rb +6 -7
- data/lib/pwn/ai/agent/learning.rb +62 -25
- 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.rb +5 -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 +35 -16
- 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 +53 -3
- 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/cron.rb +120 -49
- data/lib/pwn/migrate.rb +150 -68
- 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/binary_parser.rb +5 -4
- data/lib/pwn/plugins/ghidra.rb +4 -3
- data/lib/pwn/plugins/google_workspace.rb +4 -21
- data/lib/pwn/plugins/jobs.rb +1 -1
- data/lib/pwn/plugins/log.rb +21 -3
- data/lib/pwn/plugins/preflight_checker.rb +34 -9
- data/lib/pwn/plugins/recon.rb +4 -1
- data/lib/pwn/plugins/repl/ai.rb +305 -27
- data/lib/pwn/plugins/repl/ai_console.rb +273 -89
- data/lib/pwn/plugins/repl/ai_swarm.rb +181 -62
- 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/sessions.rb +58 -16
- data/lib/pwn/setup.rb +123 -41
- 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/scripts/build_gate.rb +58 -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/build_gate_spec.rb +73 -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/persistence_roundtrip_spec.rb +1 -7
- 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/policy_spec.rb +27 -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 +31 -3
- 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/cron_spec.rb +113 -6
- data/spec/lib/pwn/migrate_spec.rb +108 -5
- 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_spec.rb +7 -0
- 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 +125 -78
- data/spec/lib/pwn/plugins/repl/ai_legacy_containment_spec.rb +200 -0
- data/spec/lib/pwn/plugins/repl/ai_swarm_spec.rb +30 -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_spec.rb +13 -10
- data/spec/lib/pwn/redaction_yubikey_spec.rb +61 -0
- data/spec/lib/pwn/session_cleanup_concurrency_spec.rb +201 -0
- data/spec/lib/pwn/session_cleanup_default_spec.rb +167 -2
- data/spec/lib/pwn/session_cleanup_legacy_spec.rb +101 -0
- data/spec/lib/pwn/session_cleanup_payload_spec.rb +335 -2
- data/spec/lib/pwn/session_cleanup_recovery_spec.rb +403 -0
- data/spec/lib/pwn/sessions_spec.rb +112 -0
- data/spec/lib/pwn/setup_native_yubikey_spec.rb +66 -0
- data/spec/lib/pwn/setup_spec.rb +3 -1
- 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/gate_failure_formatter.rb +14 -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 +599 -15
- metadata +140 -17
|
@@ -75,6 +75,18 @@ Required: `searchsploit`. Fallback: `intel_lookup`.
|
|
|
75
75
|
|
|
76
76
|
Required: `subfinder`, `httpx`. Fallback: `NmapIt.scan` + `Corpus.get`.
|
|
77
77
|
|
|
78
|
+
## pwn-plugins-yubikey
|
|
79
|
+
|
|
80
|
+
Required: `ykman` (YubiKey Manager CLI). Preflight checks executable presence
|
|
81
|
+
only; it never opens a device, requests a PIN, or performs a challenge. An `ok`
|
|
82
|
+
status does not establish device availability, provisioning, or authorization.
|
|
83
|
+
Hardware-backed vault operations require the selected YubiKey and its existing
|
|
84
|
+
HMAC-SHA1 OTP slot; missing devices, denied touch, or authentication failures
|
|
85
|
+
raise without falling back to a disk master key or software MFA. Restore device
|
|
86
|
+
access before retrying. Dispatch blocks the handler when vault expansion fails;
|
|
87
|
+
if output redaction fails after execution, it withholds the result and reports
|
|
88
|
+
that the handler executed, so verify its effects before retrying.
|
|
89
|
+
|
|
78
90
|
## pwn-plugins-credentialattack
|
|
79
91
|
|
|
80
92
|
Required: `hydra`, `john`, `hashcat`. Fallback: `pwn_eval` + `Corpus`.
|
data/documentation/Plugins.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# `PWN::Plugins` - All
|
|
1
|
+
# `PWN::Plugins` - All 108 Modules
|
|
2
2
|
|
|
3
3
|
Every plugin is a plain Ruby module of `public_class_method def self.x(opts = {})`
|
|
4
4
|
methods with self-documenting `.help`. Source: `lib/pwn/plugins/*.rb`.
|
|
@@ -64,6 +64,7 @@ show-source PWN::Plugins::Fuzz.http
|
|
|
64
64
|
|---|---|
|
|
65
65
|
| `OAuth2` · `BasicAuth` · `AuthenticationHelper` | credential flows |
|
|
66
66
|
| `Vault` | Local encrypted configuration and engagement loot helpers; not a HashiCorp Vault client |
|
|
67
|
+
| [`YubiKey`](YubiKey.md) | Guarded ykman operations, HMAC-backed authenticated vaults and OATH codes |
|
|
67
68
|
|
|
68
69
|
### Hardware / Physical
|
|
69
70
|
| Module | Purpose | Doc |
|
|
@@ -97,6 +98,6 @@ show-source PWN::Plugins::Fuzz.http
|
|
|
97
98
|
|
|
98
99
|
## Full alphabetical list
|
|
99
100
|
|
|
100
|
-
`AFLplusplus AISandbox Android ArtifactRegistry Assembly AuthenticationHelper BareSIP BasicAuth BeEF BinaryAnalysis BinaryParser BinWorkspace BlackDuckBinaryAnalysis BurpSuite BusPirate Capability CapabilityBroker Char CredentialAttack CreditCard DAOLDAP DAOMongo DAOPostgres DAOSQLite3 Debugger DefectDojo DetectOS Detonate EIN Emulator ExploitDB ExploitDev FileFu Findings Frida Fuzz GDB GDBMI GDBMi Ghidra GhidraHeadless Git Github GoogleWorkspace HackerOne Handler Httpx Hunter IPInfo IRC Jenkins JiraDataCenter Jobs JSONPathify K8s Log MailAgent Metasploit MethodCatalog MitmProxy MonkeyPatch MSR206 NessusCloud NexposeVulnScan NmapIt Nuclei OAuth2 OCR OpenAPI OpenVAS Packet PDFParse Pony PreflightChecker ProcessTube PS PWNLogger RabbitMQ Radare2 Recon REDB REPL ROP Sandbox SBOM ScannableCodes Semgrep Serial Shodan SlackClient Sock Spider Sqlmap SSN ThreadPool Tor TransparentBrowser TTYSpinner TwitterAPI URIScheme Vault VIN Voice Volatility Vsphere XXD Zaproxy`
|
|
101
|
+
`AFLplusplus AISandbox Android ArtifactRegistry Assembly AuthenticationHelper BareSIP BasicAuth BeEF BinaryAnalysis BinaryParser BinWorkspace BlackDuckBinaryAnalysis BurpSuite BusPirate Capability CapabilityBroker Char CredentialAttack CreditCard DAOLDAP DAOMongo DAOPostgres DAOSQLite3 Debugger DefectDojo DetectOS Detonate EIN Emulator ExploitDB ExploitDev FileFu Findings Frida Fuzz GDB GDBMI GDBMi Ghidra GhidraHeadless Git Github GoogleWorkspace HackerOne Handler Httpx Hunter IPInfo IRC Jenkins JiraDataCenter Jobs JSONPathify K8s Log MailAgent Metasploit MethodCatalog MitmProxy MonkeyPatch MSR206 NessusCloud NexposeVulnScan NmapIt Nuclei OAuth2 OCR OpenAPI OpenVAS Packet PDFParse Pony PreflightChecker ProcessTube PS PWNLogger RabbitMQ Radare2 Recon REDB REPL ROP Sandbox SBOM ScannableCodes Semgrep Serial Shodan SlackClient Sock Spider Sqlmap SSN ThreadPool Tor TransparentBrowser TTYSpinner TwitterAPI URIScheme Vault VIN Voice Volatility Vsphere XXD YubiKey Zaproxy`
|
|
101
102
|
|
|
102
103
|
[← Home](Home.md) · [Diagrams](Diagrams.md)
|
|
@@ -359,14 +359,13 @@ This is the live control list. Track the outcomes, not source comments.
|
|
|
359
359
|
```ruby
|
|
360
360
|
# Seeded idempotently by PWN::Cron.install_defaults (pwn setup --migrate):
|
|
361
361
|
PWN::Cron.install_defaults
|
|
362
|
-
# ->
|
|
363
|
-
# -> curriculum_offline_judge 30 3 * * * Curriculum.offline_judge(since_hours: 24, limit: 40)
|
|
364
|
-
# -> curriculum_train_weekly 0 4 * * 0 Curriculum.train_and_gate(dry_run: true) # false only with trainer+GPU
|
|
365
|
-
# -> learning_consolidate_nightly 0 5 * * * Learning.consolidate
|
|
362
|
+
# -> session_cleanup 45 3 * * * SessionCleanup.coordinate(dry_run: false)
|
|
366
363
|
```
|
|
367
364
|
|
|
368
|
-
|
|
369
|
-
`
|
|
365
|
+
Curriculum practice, judge and training are explicit opt-ins, not seeded jobs.
|
|
366
|
+
Select a template from `PWN::Cron::CURRICULUM_JOBS` and explicitly create it only
|
|
367
|
+
when wanted (see [Cron](Cron.md)). Deletion survives repeated default installation
|
|
368
|
+
and migration. Existing jobs and legacy aliases remain unchanged.
|
|
370
369
|
`pwn setup` also starts the background cron worker so these YAML jobs fire
|
|
371
370
|
without a per-job crontab line.
|
|
372
371
|
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Runtime source protection
|
|
2
|
+
|
|
3
|
+
> The mandatory worker boundary protects source and separates the finite
|
|
4
|
+
> controller-state inventory below from tool writes. Checkpoint persistence also
|
|
5
|
+
> uses pinned fd-relative no-follow directory operations. Process containment
|
|
6
|
+
> owns detached tool jobs until mission completion/cancellation; it is not a
|
|
7
|
+
> substitute for filesystem protection. Unspecified tool writes use
|
|
8
|
+
> `~/.pwn/workspaces/runtime`. A path is writable outside that directory only
|
|
9
|
+
> when the original operator request names it. An explicit destination grants
|
|
10
|
+
> its parent even when that parent contains unrelated unreadable directories,
|
|
11
|
+
> so a new file can be created there. Source checkouts stay read-only
|
|
12
|
+
> even if named. See [Mission-Cancellation](Mission-Cancellation.md).
|
|
13
|
+
|
|
14
|
+
A pwn-ai RequestRuntime dispatch executes its registered handler in an AISandbox
|
|
15
|
+
worker. This boundary is mandatory even when the optional `ai_sandbox` profile
|
|
16
|
+
is `off`. It covers shell, Ruby evaluation, other registered handlers, nested
|
|
17
|
+
Dispatch calls, and fork/exec descendants including durable Jobs supervisors.
|
|
18
|
+
Direct library calls made by an operator outside a RequestRuntime are not AI
|
|
19
|
+
runtime tool calls and are unchanged. Legacy regex-ReAct Ruby and shell blocks
|
|
20
|
+
also use the mandatory worker boundary (inside their enclosing mission); they
|
|
21
|
+
no longer evaluate directly in the mission controller. The source-denial
|
|
22
|
+
regression drives both languages through the actual Pry after_read hook.
|
|
23
|
+
|
|
24
|
+
The host protects `/opt/pwn` when present and the real source root containing the
|
|
25
|
+
loaded package. Linux Landlock ABI 3 or newer denies content writes, truncation,
|
|
26
|
+
creation, removal, and linking under those roots. It resolves symlinks and `..`
|
|
27
|
+
in the kernel: scripts are not rewritten. Repo reads remain available. The UI
|
|
28
|
+
process does not change cwd. Relative reads use the task directory when it is
|
|
29
|
+
outside protected source; otherwise they use `~/.pwn/workspaces/runtime`.
|
|
30
|
+
Unnamed new files and temporary files go to that runtime directory. `/tmp`, the
|
|
31
|
+
launch directory, and the rest of `~/.pwn` are not default write grants. A path
|
|
32
|
+
named by the original operator request is created and granted; naming a file
|
|
33
|
+
grants its parent so the file can be created. That parent grant is a directory
|
|
34
|
+
rule, so a new file can still be created when the parent contains unrelated
|
|
35
|
+
unreadable directories. Do not create the missing destination as a directory.
|
|
36
|
+
Protected source is never granted.
|
|
37
|
+
Standard null/zero/random devices are available. Other filesystem writes fail
|
|
38
|
+
closed. This bounded write set permits hardlink-alias exclusion without scanning
|
|
39
|
+
all mounted filesystems or changing checkout permissions.
|
|
40
|
+
|
|
41
|
+
## Fail-closed requirements and restrictions
|
|
42
|
+
|
|
43
|
+
- Supported syscall ABIs are Linux x86_64 and aarch64; libseccomp is required.
|
|
44
|
+
Missing enforcement prevents handler execution, rather than falling back to
|
|
45
|
+
regex checks or unsandboxed execution.
|
|
46
|
+
- Landlock does not mediate file metadata changes. The worker therefore denies
|
|
47
|
+
chmod/chown, timestamp and extended-attribute mutation system-wide, including
|
|
48
|
+
outside source. Ordinary outside content writes and file creation still work.
|
|
49
|
+
Tools that need those metadata operations require a different supported
|
|
50
|
+
execution environment, not an exception to source protection.
|
|
51
|
+
- Mount/namespace manipulation, ptrace/process-memory writes, and io_uring setup
|
|
52
|
+
are denied. Existing descriptors into protected roots are closed in the child.
|
|
53
|
+
- Host preflight inventories multiply linked protected file identities and
|
|
54
|
+
excludes matching aliases in every writable tree. Aliases elsewhere receive
|
|
55
|
+
no write grant. Alias inventories are cached against source inode/link-count/
|
|
56
|
+
ctime fingerprints and writable-root identity; source link changes invalidate
|
|
57
|
+
that cache. Unreadable subtrees encountered during alias scanning are excluded.
|
|
58
|
+
This includes generated rdoc assets linked to installed gem assets; no source
|
|
59
|
+
files are chmodded, deleted, or automatically rewritten.
|
|
60
|
+
- Protected root ancestors cannot grant inherited write permission without also
|
|
61
|
+
granting it to source. Creating a new sibling directly in such an ancestor is
|
|
62
|
+
consequently denied; use an existing writable outside directory.
|
|
63
|
+
- This is a local process/filesystem effect boundary, not isolation of remote
|
|
64
|
+
services or already-running privileged daemons commanded over IPC/network.
|
|
65
|
+
It does not defend against a concurrent external actor replacing policy paths
|
|
66
|
+
or introducing new hardlink aliases after preflight. Do not run untrusted
|
|
67
|
+
external writers against the protected installation.
|
|
68
|
+
- Handler-local Ruby variables and in-memory plugin state do not propagate back
|
|
69
|
+
to the UI. Persistent outputs and durable job state do. A handler that requires
|
|
70
|
+
process-local state across calls must not assume the old in-process evaluator.
|
|
71
|
+
|
|
72
|
+
## Sandboxed swarm control
|
|
73
|
+
|
|
74
|
+
`agent_spawn` and `agent_ask` handlers still run inside the mandatory worker.
|
|
75
|
+
Their Swarm calls use a private socket to request only the controller's typed
|
|
76
|
+
`spawn`/`ask` operations. The controller checks request tool permissions, rejects
|
|
77
|
+
unknown fields/operations and traversal identifiers, and never invokes a
|
|
78
|
+
worker-selected Registry handler, callback, Ruby expression, or filesystem path.
|
|
79
|
+
Nested persona tools pass through Dispatch and get their own mandatory workers.
|
|
80
|
+
|
|
81
|
+
Before launch the controller provisions the fixed swarm directory, persona file,
|
|
82
|
+
and continuation lock with no-follow ancestry and regular-file/single-link
|
|
83
|
+
checks. Workers cannot write the persona file, swarm subtree, or request
|
|
84
|
+
checkpoint tree, nor rename their ancestors. No parent-directory write grant is
|
|
85
|
+
added. Child Loop receipts remain controller-observed and are rechecked when
|
|
86
|
+
merged into the parent. This preserves sandboxed spawn/ask state creation without
|
|
87
|
+
allowing arbitrary controller callbacks.
|
|
88
|
+
|
|
89
|
+
## Finite parent-writer audit
|
|
90
|
+
|
|
91
|
+
The worker deny set now includes these controller-owned stores, even before a
|
|
92
|
+
store exists. Missing paths still split the ancestor's Landlock grant, preventing
|
|
93
|
+
first-write symlink planting. Existing inherited descriptors and hardlink aliases
|
|
94
|
+
are covered by the same preflight as source. Store constants are resolved in the
|
|
95
|
+
controller, not from model/tool output. Both lexical paths and canonical store
|
|
96
|
+
aliases are denied, so a configured symlink cannot expose controller state
|
|
97
|
+
through another otherwise writable directory.
|
|
98
|
+
|
|
99
|
+
| Parent writer | Protected state |
|
|
100
|
+
| --- | --- |
|
|
101
|
+
| RequestRuntime checkpoints and EngagementMemory | Request-specific artifact root; checkpoint lock/temp/final persistence is also fd-relative/no-follow |
|
|
102
|
+
| Sessions and SessionTrace | Sessions root, including support, leases, traces and requests |
|
|
103
|
+
| Loop transcript compaction, ArtifactRegistry, swarm bus spills | Default artifacts root and configured ArtifactRegistry root |
|
|
104
|
+
| Learning, Policy, Metrics, Reward, Mistakes, ToolGuard | Declared files/directories, learning and metrics subtrees; absent sibling staging paths cannot be planted |
|
|
105
|
+
| Memory and MemoryIndex | Memory, archive and index files |
|
|
106
|
+
| OpenGoal, Mission and TaskDAG | Goal file, missions and runs roots |
|
|
107
|
+
| SkillReview and Curriculum | Ledger, curriculum/finetune roots, default/configured skill directories and loaded skill parents |
|
|
108
|
+
| Provider credential persistence and local model configuration | Default vault/decryptor and configured driver paths |
|
|
109
|
+
| Session redaction's Vault persistence | Engagements tree, legacy vault file and master-key path |
|
|
110
|
+
| Log and Extrospection | Default logs and declared Extrospection stores |
|
|
111
|
+
| Typed swarm controller | Swarm subtree, personas and continuation lock |
|
|
112
|
+
|
|
113
|
+
The regression first reproduced an actual worker redirect of the transcript
|
|
114
|
+
spill directory: after the worker returned, Loop created a file in synthetic
|
|
115
|
+
protected source. It now receives permission denied, as does the earlier
|
|
116
|
+
RequestRuntime spill reproducer. An independent fixture attempts 29 state
|
|
117
|
+
mutations across existing directories/files and an absent staging path in both
|
|
118
|
+
ordinary and symlinked-store layouts, while also creating a legitimate output in
|
|
119
|
+
a disjoint workspace.
|
|
120
|
+
|
|
121
|
+
Tools that directly mutate these controller stores are deliberately denied;
|
|
122
|
+
only spawn/ask currently have the typed broker exception. This is not a promise
|
|
123
|
+
that arbitrary in-process stateful plugins retain their old behavior. New parent
|
|
124
|
+
writers or custom stores require an inventory update. The guarantee assumes a
|
|
125
|
+
trusted initial controller layout and excludes concurrent external filesystem
|
|
126
|
+
writers as described above; it is not a general host sandbox.
|
|
127
|
+
|
|
128
|
+
## Completion evidence and uncertainty
|
|
129
|
+
|
|
130
|
+
Required artifact names come from the original operator request (including
|
|
131
|
+
explicit amendments), not cached model guesses or tool transcripts. Unquoted
|
|
132
|
+
prose such as `i.e.` does not create a required file named `i.e`; explicitly
|
|
133
|
+
quoted filenames are still honored.
|
|
134
|
+
|
|
135
|
+
RequestRuntime snapshots required artifacts before dispatch and, on success,
|
|
136
|
+
reads their stat, bounded head/tail and SHA-256 from the host. Successful actual
|
|
137
|
+
file deltas count even if payload classification called the tool `eval` rather
|
|
138
|
+
than `write`. Receipts accumulate across separate calls/iterations and survive
|
|
139
|
+
transcript compaction. A failed tool, unchanged stale file, or tool stdout claim
|
|
140
|
+
cannot create a receipt. Current bytes/identity must still match at completion.
|
|
141
|
+
A combined write/read call does not require a ritual second call.
|
|
142
|
+
|
|
143
|
+
Unknown side effects remain replay-fenced. A timeout/interruption or failed
|
|
144
|
+
mutation is not erased by unrelated successful artifacts. On an attempted final
|
|
145
|
+
answer the loop returns a structured `blocked` outcome with action ID and payload
|
|
146
|
+
hash, instead of endlessly asking for rewrites. Exact-target operator-approved
|
|
147
|
+
reconciliation is still required for genuine uncertainty; the existing HTTP
|
|
148
|
+
reconciliation API is unchanged. Kernel/preflight failure before the handler
|
|
149
|
+
starts is recorded as `rejected`, not falsely labeled an uncertain mutation.
|
|
150
|
+
|
|
151
|
+
## Verification and deployment
|
|
152
|
+
|
|
153
|
+
Offline specs exercise actual kernel workers, symlink/parent traversal denial,
|
|
154
|
+
metadata denial, nested Dispatch, a detached Jobs worker, fail-closed unsupported
|
|
155
|
+
protection/hardlinks, and the Loop → Dispatch → cumulative host receipt path with
|
|
156
|
+
an actual generated PDF and separate text output. Provider messages in that
|
|
157
|
+
replay are fixtures, not a live remote-model test.
|
|
158
|
+
|
|
159
|
+
Source changes do not update an installed gem or a running pwn-ai process.
|
|
160
|
+
Deploy the matching source/package files and restart the remote process through
|
|
161
|
+
the operator's normal deployment procedure. Inspect the reported root/hardlink
|
|
162
|
+
and kernel requirements before claiming that host is operational.
|
|
@@ -52,5 +52,16 @@ All four honor `proxy:` (Burp / `tor`) so attribution stays controlled, reuse
|
|
|
52
52
|
**one** browser handle across anchors, and `close` in an `ensure`. See
|
|
53
53
|
[Extrospection](Extrospection.md) for the full loop.
|
|
54
54
|
|
|
55
|
+
## Jev action loop
|
|
56
|
+
|
|
57
|
+
`act` and `browser_act` run only when Open WebUI is configured and its model
|
|
58
|
+
list contains a Jev model. Jev receives the visible control table and returns
|
|
59
|
+
one operation plus one index: `CLICK`, `TYPE_TEXT`, `SELECT`, `SCROLL_UP`,
|
|
60
|
+
`SCROLL_DOWN`, `WAIT`, `DONE`, or `BLOCKED`. It does not receive screenshots
|
|
61
|
+
and it does not emit selectors. If the active pwn-ai model is not Jev, that
|
|
62
|
+
model still writes the field text for `TYPE_TEXT`. Other pwn-ai work stays on
|
|
63
|
+
the active model. This is the indexed-action idea from
|
|
64
|
+
[jev-ultrafast](https://github.com/browser-use/jev-ultrafast), not TypeSafe's
|
|
65
|
+
multi-head API and not a claim of its measured latency.
|
|
55
66
|
|
|
56
67
|
[← Home](Home.md) · [BurpSuite](BurpSuite.md) · [WWW](WWW.md) · [Extrospection](Extrospection.md)
|
|
@@ -32,8 +32,9 @@ $ pwn setup --migrate --dry-run # report only
|
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
Corrupt / incompatible files are moved to `~/.pwn/quarantine/` (never
|
|
35
|
-
deleted)
|
|
36
|
-
first
|
|
35
|
+
deleted). Recovery copies go to one shared generation under `~/.pwn/backup/`
|
|
36
|
+
first; the store keeps seven generations total. See
|
|
37
|
+
[Backup Retention](Backup-Retention.md). Missing config keys added by the new release are deep-merged into
|
|
37
38
|
your encrypted `~/.pwn/pwn.yaml` **under** your existing values. See
|
|
38
39
|
[Installation § Upgrading](Installation.md#upgrading--pwn-state-migration-pwnmigrate).
|
|
39
40
|
|
|
@@ -12,7 +12,7 @@ with a **tool-calling AI agent** on top that can run the same methods.
|
|
|
12
12
|
|
|
13
13
|
| Namespace | Count | What it is |
|
|
14
14
|
|---|---|---|
|
|
15
|
-
| `PWN::Plugins::*` | **
|
|
15
|
+
| `PWN::Plugins::*` | **108** | Wrappers for external and native tooling (Burp, Nmap, Metasploit, Shodan, browsers, serial, YubiKey, ...) |
|
|
16
16
|
| `PWN::SAST::*` | **48** | Static-analysis rules across C/Java/Go/Python/Ruby/Scala/PHP/TS |
|
|
17
17
|
| `PWN::AWS::*` | **90** | One module per AWS service for cloud enumeration |
|
|
18
18
|
| `PWN::WWW::*` | **22** | Site-specific browser automations (HackerOne, BugCrowd, GitHub, Google, LinkedIn, ...) |
|
|
@@ -20,7 +20,7 @@ with a **tool-calling AI agent** on top that can run the same methods.
|
|
|
20
20
|
| `PWN::FFI::*` | **11** | Native bindings (including DSPNative, Capstone and Keystone): Volk · Liquid · FFTW · RTLSdr · HackRF · AdalmPluto · SoapySDR · Stdio |
|
|
21
21
|
| `PWN::AI::*` | **6** engines | OpenAI, Anthropic, Grok (OAuth device-flow), Gemini, Ollama, Open WebUI |
|
|
22
22
|
| `bin/` (including `pwn-ai` and `pwn-capd`) | **56** | Headless CLI executables for CI/CD |
|
|
23
|
-
| Agent toolsets | **16** · **
|
|
23
|
+
| Agent toolsets | **16** · **152 tools** | terminal · pwn · memory · skills · sessions · learning · metrics · policy · extrospection · cron · swarm · reward · curriculum · http · mcp · manifest |
|
|
24
24
|
|
|
25
25
|
## Three ways to use it
|
|
26
26
|
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# YubiKey-backed vaults and authentication
|
|
2
|
+
|
|
3
|
+
See [YubiKey device operations](YubiKey.md) for the `ykman` command families,
|
|
4
|
+
provisioning safeguards and supported hardware/firmware boundaries.
|
|
5
|
+
|
|
6
|
+
## Encryption model
|
|
7
|
+
|
|
8
|
+
This is **hardware-derived key encryption**, not bulk encryption inside the
|
|
9
|
+
YubiKey. An already provisioned OTP HMAC-SHA1 slot answers a fresh random
|
|
10
|
+
32-byte challenge. Ruby derives a 32-byte encryption key using HKDF-SHA256 with
|
|
11
|
+
a fresh 16-byte salt and a domain-specific context, then uses AES-256-GCM with
|
|
12
|
+
a fresh nonce and a full 16-byte tag. The HMAC response and derived key exist
|
|
13
|
+
transiently in the Ruby process; the slot secret is not exported. Ruby does not
|
|
14
|
+
promise zeroization of copied strings.
|
|
15
|
+
|
|
16
|
+
The versioned `PWN-YUBIKEY-VAULT:1` envelope authenticates its metadata as AAD.
|
|
17
|
+
The public challenge, salt, slot and optional serial are stored with ciphertext,
|
|
18
|
+
not in a secret sidecar. Executable paths and timeout overrides are supplied
|
|
19
|
+
by the caller, never loaded from ciphertext. PINs, OTP codes and serial numbers
|
|
20
|
+
are not encryption keys. HMAC-SHA1 is used as the device PRF, not as an
|
|
21
|
+
unauthenticated document hash; it provides at most the slot/response security,
|
|
22
|
+
not 256 bits of entropy merely because AES-256 is used.
|
|
23
|
+
|
|
24
|
+
Existing Base64 AES-256-CBC files and software loot remain readable. New
|
|
25
|
+
hardware protection is opt-in; no existing configuration is migrated merely by
|
|
26
|
+
loading PWN. A hardware envelope never falls back to a software master key,
|
|
27
|
+
passphrase or unauthenticated plaintext when a device is missing or a tag fails.
|
|
28
|
+
Do not combine a software key/IV or passphrase/keyring with hardware selection.
|
|
29
|
+
|
|
30
|
+
## Use an existing HMAC slot
|
|
31
|
+
|
|
32
|
+
Use a key model supporting OTP HMAC challenge-response. FIDO-only Security Keys
|
|
33
|
+
do not support this vault backend. Set up the slot explicitly using the device
|
|
34
|
+
management interface; prefer its physical-touch policy. PWN never provisions,
|
|
35
|
+
replaces, unlocks by guessing, or resets a slot in order to open a vault.
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
# The named file must already contain the plaintext you intend to encrypt.
|
|
39
|
+
PWN::Plugins::Vault.create(file: '/path/to/private.yaml', yubikey: { slot: 2 })
|
|
40
|
+
|
|
41
|
+
# With multiple devices, explicitly select the intended device serial.
|
|
42
|
+
# Serial is a placeholder; replace locally, never paste secrets into a transcript.
|
|
43
|
+
selector = { slot: 2, serial: '12345678' }
|
|
44
|
+
PWN::Plugins::Vault.encrypt(file: '/path/to/another.yaml', yubikey: selector)
|
|
45
|
+
|
|
46
|
+
# Read-only: decrypted data exists in memory, not an intermediate file.
|
|
47
|
+
config = PWN::Plugins::Vault.dump(file: '/path/to/private.yaml'); nil
|
|
48
|
+
|
|
49
|
+
# Mutate YAML in memory and atomically publish ciphertext, preserving the backend.
|
|
50
|
+
PWN::Plugins::Vault.update(file: '/path/to/private.yaml') do |document|
|
|
51
|
+
document[:setting] = 'replacement'
|
|
52
|
+
end
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`yubikey` is a Hash accepting `slot` (integer 1 or 2; default 2), optional
|
|
56
|
+
`serial`, optional local `ykman` executable path and bounded `timeout` seconds.
|
|
57
|
+
`dump`, `decrypt`, `open_credentials` and hardware loot retrieval otherwise use
|
|
58
|
+
the slot/serial stored in their envelope. Selecting another serial permits an
|
|
59
|
+
explicitly provisioned recovery key with the same slot secret; the authentication
|
|
60
|
+
tag still has to verify. A different slot requires explicit rewrapping.
|
|
61
|
+
|
|
62
|
+
`encrypt_data` / `decrypt_data` are in-memory String APIs, including arbitrary
|
|
63
|
+
binary data and empty plaintext. `seal_credentials` / `open_credentials` work
|
|
64
|
+
on JSON-compatible credential values. Neither API opens the live configuration
|
|
65
|
+
or writes keys. `file_encrypted?` / `hardware_encrypted?` inspect format only;
|
|
66
|
+
they do not prove the device is present or that a ciphertext authenticates.
|
|
67
|
+
|
|
68
|
+
`decrypt(file:)` explicitly replaces ciphertext with plaintext. Use `dump`
|
|
69
|
+
instead when plaintext-on-disk is unnecessary. `edit` explicitly gives a private
|
|
70
|
+
0600 temporary copy to the chosen editor under `~/.pwn/workspaces/runtime`, then
|
|
71
|
+
removes its private working directory. The original stays encrypted until a
|
|
72
|
+
successful re-encryption and atomic replacement. Editors are trusted programs:
|
|
73
|
+
their external backups, OS swap, crash dumps and an abruptly killed process are
|
|
74
|
+
not a secure-erasure guarantee. The curses `/vault edit` editor works in memory
|
|
75
|
+
and writes only ciphertext. Built-in file writers share its parent-directory
|
|
76
|
+
advisory lock across the final baseline check and atomic rename. A stale edit
|
|
77
|
+
raises rather than overwriting a newer publication. This is not a filesystem
|
|
78
|
+
compare-and-swap guarantee against external writers that ignore the lock.
|
|
79
|
+
|
|
80
|
+
## Conversion and recovery
|
|
81
|
+
|
|
82
|
+
Before converting a legacy vault, retain its verified encrypted backup and
|
|
83
|
+
legacy decryptor somewhere secure. Conversion is explicit:
|
|
84
|
+
|
|
85
|
+
```ruby
|
|
86
|
+
PWN::Plugins::Vault.refresh_encryption_secrets(
|
|
87
|
+
file: '/path/to/legacy.yaml',
|
|
88
|
+
key: legacy_key, iv: legacy_iv,
|
|
89
|
+
new_yubikey: { slot: 2 }
|
|
90
|
+
)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
No temporary plaintext is published during conversion. On an existing hardware
|
|
94
|
+
vault, `refresh_encryption_secrets(file:)` rewraps with fresh challenge/salt/nonce;
|
|
95
|
+
it does **not** change the device secret. Supply `new_yubikey:` to move to another
|
|
96
|
+
already provisioned slot/device while the old one is available. An explicit
|
|
97
|
+
`new_yubikey:` must be a valid selector Hash; values such as `false` are rejected
|
|
98
|
+
before opening the source vault, not treated as a request for software rotation.
|
|
99
|
+
Hardware access or encryption failure leaves the original ciphertext intact. Old software
|
|
100
|
+
sidecars and backups are not silently deleted; retire them deliberately after
|
|
101
|
+
verifying recovery.
|
|
102
|
+
|
|
103
|
+
Losing or reprogramming the only usable slot loses access. A ciphertext backup
|
|
104
|
+
alone is not an independent recovery key. Establish and test an appropriate
|
|
105
|
+
recovery device/secret before relying on hardware-only storage. Removing a
|
|
106
|
+
YubiKey does not erase an already unlocked `PWN::Env` or revoke remote tokens;
|
|
107
|
+
the application retains its in-memory configuration until exit/refresh.
|
|
108
|
+
|
|
109
|
+
## Integration coverage
|
|
110
|
+
|
|
111
|
+
| Entry point | Hardware behavior |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `Vault.create/encrypt/decrypt/dump/edit/refresh_encryption_secrets` | Explicit creation/conversion, automatic envelope detection on read, backend-preserving edits |
|
|
114
|
+
| `Vault.seal_credentials/open_credentials` | Authenticated in-memory hardware envelopes alongside existing passphrase/keyring formats |
|
|
115
|
+
| `Vault.store/fetch/offer/ingest/expand/redact` | Optional hardware-protected engagement records; metadata-only `query` does not touch hardware |
|
|
116
|
+
| `BasicAuth.encode(host:)` | Resolves matching protected loot through Vault, not a separate crypto implementation |
|
|
117
|
+
| `Redaction.capture` and `Recon` loot ingestion | Explicit hardware selector for new captures; locked-store failure never creates a software-key fallback |
|
|
118
|
+
| `Config.default_env/refresh_env` | Explicit hardware creation; hardware loading without a legacy decryptor sidecar |
|
|
119
|
+
| `Migrate.vault_drift/backfill_vault` | Read/merge through Vault, preserving hardware format and user settings |
|
|
120
|
+
| `pwn-vault`, `/vault edit`, `/model`, `/system-role`, mesh settings | Backend-aware encrypted persistence; no duplicate CBC-only write path |
|
|
121
|
+
| OpenAI, Anthropic, Grok and Google Workspace OAuth persistence | In-memory configuration merge, ciphertext-only atomic save; hardware unavailability reports persistence failure |
|
|
122
|
+
| `AuthenticationHelper.mfa` and supported WWW login methods | Explicit exact-account OATH code lookup, separate from ordinary manual MFA |
|
|
123
|
+
|
|
124
|
+
Hardware-protected loot reads may require a touch, including explicit expansion
|
|
125
|
+
and secret-value redaction. Do not enable it for unattended workflows expecting
|
|
126
|
+
unbounded automatic access. Background metadata discovery and help do not unlock
|
|
127
|
+
hardware. Existing unrelated records are not implicitly re-encrypted. Missing
|
|
128
|
+
loot stores are empty; an existing unreadable store, malformed JSON, or invalid
|
|
129
|
+
record/envelope shape raises `IOError` on reads and writes, including metadata
|
|
130
|
+
queries. PWN does not infer a software backend from corrupt records, generate a
|
|
131
|
+
replacement master key, or overwrite the damaged store. Restore a verified backup
|
|
132
|
+
before retrying.
|
|
133
|
+
|
|
134
|
+
## Explicit OATH authentication
|
|
135
|
+
|
|
136
|
+
Select an exact account and authorize its effects explicitly:
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
code = PWN::Plugins::AuthenticationHelper.mfa(
|
|
140
|
+
yubikey: { account: 'Example:alice', serial: '12345678', confirm: true }
|
|
141
|
+
); nil
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The same `yubikey:` Hash is accepted by GitHub, Synack, Twitter, BugCrowd,
|
|
145
|
+
CoinbasePro and AppCobaltIO login methods. Lookup occurs at the authenticator
|
|
146
|
+
form, not during option validation. Missing/nonliteral consent is rejected before
|
|
147
|
+
password prompts or navigation. Device errors do not fall back to manual MFA;
|
|
148
|
+
explicit manual tokens cannot be combined with the hardware selector. PayPal's
|
|
149
|
+
current SMS-only adapter rejects OATH even with consent, and GitHub's SMS-only
|
|
150
|
+
challenge does not accept an authenticator code.
|
|
151
|
+
|
|
152
|
+
For `pwn_web_cache_deception`, add `--yubikey-account='Example:alice'`, optionally
|
|
153
|
+
`--yubikey-serial=12345678`, and the required `--yubikey-confirm` to the normal
|
|
154
|
+
arguments for a compatible login module. The flag authorizes HOTP counter
|
|
155
|
+
advancement, remembered-key authentication and deletion of invalid cached keys
|
|
156
|
+
during account listing, and upstream `ykman` cleanup that may delete a corrupted
|
|
157
|
+
OATH credential. It is required for TOTP too; PWN never silently supplies consent.
|
|
158
|
+
Confirmation/serial flags without an account are rejected before login.
|
|
159
|
+
|
|
160
|
+
## Scope boundaries
|
|
161
|
+
|
|
162
|
+
YubiKey FIDO management is not a WebAuthn relying-party implementation. Website
|
|
163
|
+
passkey login still requires the browser's genuine security-key ceremony and
|
|
164
|
+
site enrollment; a generated OATH code must never be submitted to an SMS-only
|
|
165
|
+
challenge. PIV/OpenPGP key management does not export non-exportable keys or
|
|
166
|
+
magically replace TLS, SSH-agent or GPG-provider integrations.
|
|
167
|
+
|
|
168
|
+
Radio protocol keys, packet AES-CCM, TLS inspection certificates, OAuth PKCE,
|
|
169
|
+
artifact hashes, cloud KMS/HSM API clients and Jenkins private-key uploads are
|
|
170
|
+
not rewritten to use hardware-derived bytes. Their stored credentials can be
|
|
171
|
+
protected through Vault where appropriate.
|
|
172
|
+
|
|
173
|
+
Hardware-backed loot does not encrypt Recon's raw evidence/asset files, generic
|
|
174
|
+
tool-result artifacts, exports, or the filesystem as a whole. Those retain their
|
|
175
|
+
existing evidence-storage behavior and need separate access/at-rest protection.
|
|
176
|
+
`recon_run` advertises the same nonsecret hardware selector as `loot_query` for
|
|
177
|
+
harvested loot; metadata-only Vault queries do not unlock a device, but Dispatch's
|
|
178
|
+
separate output-redaction step can still require access to protected secrets.
|
|
179
|
+
|
|
180
|
+
Verification uses fake device processes and synthetic HMAC responses. Tests
|
|
181
|
+
exercise real Ruby encryption, authentication failures, selector validation,
|
|
182
|
+
subprocess cleanup and persistence entry points, but are not evidence of a
|
|
183
|
+
physical YubiKey, live website authentication or every firmware variant.
|