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
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
# YubiKey device operations
|
|
2
|
+
|
|
3
|
+
`PWN::Plugins::YubiKey` is a native Ruby wrapper around Yubico's official
|
|
4
|
+
`ykman` executable. It is not a USB driver, a replacement for Yubico's CLI, or a
|
|
5
|
+
WebAuthn relying party. The command grammar is based on **YubiKey Manager
|
|
6
|
+
5.9.1**. Hardware capability and firmware still determine which commands work.
|
|
7
|
+
|
|
8
|
+
For encrypted configuration, credential storage, conversion and recovery, see
|
|
9
|
+
[YubiKey-backed vaults and authentication](YubiKey-Vaults.md).
|
|
10
|
+
|
|
11
|
+
## Dependency and discovery
|
|
12
|
+
|
|
13
|
+
Install the official **yubikey-manager** package using Yubico's installation
|
|
14
|
+
instructions or your platform package manager. PWN reports `ykman` as an optional
|
|
15
|
+
hardware tool; merely loading this module does not install software or access a
|
|
16
|
+
device. The official executable has its own Python/native-library dependencies;
|
|
17
|
+
PWN does not ship a Python helper. PC/SC, USB permissions and enabled device
|
|
18
|
+
interfaces must be configured locally as appropriate.
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
require 'pwn'
|
|
22
|
+
yk = PWN::Plugins::YubiKey
|
|
23
|
+
yk.required_bins # => ['ykman']
|
|
24
|
+
yk.available? # --version only, no device operation
|
|
25
|
+
yk.devices # decimal serial Strings, or []
|
|
26
|
+
yk.info(serial: '12345678') # example serial; replace locally
|
|
27
|
+
yk.otp(args: ['info'], serial: '12345678')
|
|
28
|
+
yk.help # all public methods and option descriptions
|
|
29
|
+
yk.cli_help # official --full-help, including sd and apdu
|
|
30
|
+
yk.cli_help(path: %w[piv keys generate])
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`ykman: '/trusted/path/to/ykman'` selects an executable explicitly. Do not load
|
|
34
|
+
executable paths from untrusted vault metadata. Serial values must be decimal
|
|
35
|
+
**Strings**; they are not trimmed, coerced or repaired. Omit the serial only when
|
|
36
|
+
device selection is unambiguous. PWN never chooses the first of several devices.
|
|
37
|
+
`reader:` selects a smartcard reader instead and cannot be combined with `serial:`;
|
|
38
|
+
it is not supported by the upstream `list` command.
|
|
39
|
+
|
|
40
|
+
## Management coverage
|
|
41
|
+
|
|
42
|
+
Every family method accepts `args:` as an argv Array **after the family name**.
|
|
43
|
+
With no `args`, it returns that family's official help. `command(args:)` accepts
|
|
44
|
+
the complete management argv after global selection/security options. It returns
|
|
45
|
+
raw binary-tagged stdout; it does not print or log the result.
|
|
46
|
+
|
|
47
|
+
| Method | Official family | Covered management operations |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| `config` | `config` | USB/NFC application enablement, mode, lock code, timeouts, reset |
|
|
50
|
+
| `otp` | `otp` | Slot inventory, Yubico OTP, static password, HOTP, HMAC/TOTP challenge-response, settings, NDEF, swap, delete |
|
|
51
|
+
| `oath` | `oath` | Account list/add/URI/import/rename/delete/code, access password, remembered-password state, reset |
|
|
52
|
+
| `fido` | `fido` | PIN changes/verification, minimum PIN length, resident credential list/delete, fingerprints, UV/attestation policy, reset |
|
|
53
|
+
| `piv` | `piv` | PIN/PUK/management key, key generation/import/export/move/delete/attestation, certificates, CSR and object management, reset |
|
|
54
|
+
| `openpgp` | `openpgp` | PIN/admin/reset code and retry policy, key import/attestation/touch policy, certificates, reset |
|
|
55
|
+
| `hsmauth` | `hsmauth` | YubiHSM Auth asymmetric/symmetric/derived credentials, credential passwords, management protection, reset |
|
|
56
|
+
| `security_domain` | **`sd`** | SCP key information, generation/import/export/deletion/allowlists and reset |
|
|
57
|
+
| `apdu` | `apdu` | Explicit raw APDUs, application selection, full-APDU mode and response formatting |
|
|
58
|
+
|
|
59
|
+
The wrapper recognizes the complete 5.9.1 management command tree, including
|
|
60
|
+
hidden `sd` and `apdu`. It intentionally does **not** run `ykman script`, arbitrary
|
|
61
|
+
Python, diagnostic logging, inline credential options, or unknown future commands.
|
|
62
|
+
New command grammar must be reviewed before extending the allowlist. All known
|
|
63
|
+
commands remain discoverable through `cli_help`. Protected prompts use the
|
|
64
|
+
explicit private-terminal `interact` method rather than secret command arguments.
|
|
65
|
+
|
|
66
|
+
Use **long options as separate argv elements**. Short aliases and `--option=value`
|
|
67
|
+
are rejected to avoid credential-alias ambiguity; `--` is available before a
|
|
68
|
+
positional identifier beginning with a dash. Do not pass shell command strings.
|
|
69
|
+
For example, `args: ['keys', 'info', '9a']`, not `args: 'keys info 9a'`.
|
|
70
|
+
|
|
71
|
+
### Confirmation and execution boundaries
|
|
72
|
+
|
|
73
|
+
Only a narrow read-only allowlist runs without confirmation: device inventory,
|
|
74
|
+
basic application information, interface `--list`, HSM Auth credential listing,
|
|
75
|
+
canonical help/version calls, and validated HMAC calculation. Other operations
|
|
76
|
+
require **literal `confirm: true`**. This includes key provisioning, reset,
|
|
77
|
+
authentication attempts, local exports, unknown commands, OATH account listing
|
|
78
|
+
and code generation, and **every raw APDU**, even an APDU the
|
|
79
|
+
caller believes is a read. Confirmation does not make unknown grammar acceptable.
|
|
80
|
+
|
|
81
|
+
OATH account listing requires consent even without `--remember`: upstream
|
|
82
|
+
authenticates with a remembered credential and may delete and persist that
|
|
83
|
+
remembered key on authentication failure before prompting.
|
|
84
|
+
Device discovery may still update ykman's noncredential local device-history cache;
|
|
85
|
+
the allowlist is not a guarantee of no host filesystem writes.
|
|
86
|
+
|
|
87
|
+
PWN never adds `--force` to destructive operations. A caller may explicitly supply
|
|
88
|
+
that flag after consenting, but `confirm: true` alone does not automatically answer
|
|
89
|
+
the CLI's prompts. Normal commands close stdin and capture output; they are not
|
|
90
|
+
interactive terminal sessions. A prompt may abort or time out. Do not retry an
|
|
91
|
+
uncertain mutation blindly: inspect device state first. The one automated secret
|
|
92
|
+
input path is the fixed, version-checked HMAC provisioning method below.
|
|
93
|
+
|
|
94
|
+
- Execution uses argv vectors, never a shell. Arguments and outputs are bounded.
|
|
95
|
+
A child-only `0077` umask restricts newly created output files; it does not
|
|
96
|
+
repair permissions on existing files or suppress the CLI's generated secrets.
|
|
97
|
+
- `timeout:` is a finite positive number of seconds, default **30** per child.
|
|
98
|
+
OATH retrieval shares one budget across inventory and calculation; explicit
|
|
99
|
+
provisioning uses a separate budget for each of its three subprocesses.
|
|
100
|
+
- `max_output:` defaults to **1,048,576 bytes**, counting both stdout and stderr.
|
|
101
|
+
Exceeding it terminates the operation rather than returning partial output.
|
|
102
|
+
- Cleanup sends TERM, then KILL to the child's process group and reaps the direct
|
|
103
|
+
child. Unix process-group semantics are required. This is not a sandbox for a
|
|
104
|
+
malicious replacement executable or a process that deliberately escapes its group.
|
|
105
|
+
- Missing executable, nonzero exit, timeout, output limit and malformed responses
|
|
106
|
+
raise `DependencyError`, `CommandError`, `TimeoutError`, `OutputLimitError` or
|
|
107
|
+
`ResponseError`. These inherit from `YubiKey::Error`. Guard failures use
|
|
108
|
+
`ConfirmationRequired`; invalid caller values use `ArgumentError`.
|
|
109
|
+
- Errors suppress stdout/stderr, argv and underlying OS exception causes. Successful
|
|
110
|
+
output can still contain generated keys, account identifiers or OTPs: do not
|
|
111
|
+
print, persist, put into agent transcripts, or send it to a logger.
|
|
112
|
+
|
|
113
|
+
### Credential and secure-channel handling
|
|
114
|
+
|
|
115
|
+
Do not pass PINs, PUKs, passwords, management/access/lock keys, OTP seeds or OATH
|
|
116
|
+
URIs in argv. Their known options and positional slots are rejected even with
|
|
117
|
+
confirmation. Unknown Ruby options, including arbitrary stdin, are rejected too.
|
|
118
|
+
Key imports take existing key **file paths**, not inline secret bytes; protect
|
|
119
|
+
those files and remove them according to your organization's retention policy.
|
|
120
|
+
|
|
121
|
+
For protected commands, use `interact` in a **private local operator terminal**,
|
|
122
|
+
omit credential arguments and answer the official CLI's prompts. Obtain specific
|
|
123
|
+
consent first. For example, after approving a PIN change on the selected device:
|
|
124
|
+
|
|
125
|
+
```ruby
|
|
126
|
+
yk.interact(
|
|
127
|
+
args: %w[fido access change-pin], serial: '12345678',
|
|
128
|
+
confirm: true, timeout: 90
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
It bridges a native PTY to the controlling console (or an explicitly supplied
|
|
133
|
+
readable **and** writable `terminal:` IO), restores terminal mode and original
|
|
134
|
+
file-descriptor status flags on exit, and returns only `:completed`.
|
|
135
|
+
There is no retained transcript or returned credential output. The byte limit
|
|
136
|
+
counts total terminal traffic, and the timeout includes human input. Timeout or
|
|
137
|
+
interruption kills the child process group and reaps the direct child, without
|
|
138
|
+
retrying a potentially completed write. Nonterminal and one-way IO callers fail
|
|
139
|
+
before spawning, including Ruby read-only/write-only wrappers of duplex descriptors.
|
|
140
|
+
Validation does not consume terminal input, and caller-owned IO is never closed.
|
|
141
|
+
Run outside active curses screens and recorded tool sessions; this is an
|
|
142
|
+
operator workflow, not an automatic agent prompt handler. The bridge does not
|
|
143
|
+
mask prompts that upstream itself echoes or guarantee Ruby-memory zeroization.
|
|
144
|
+
|
|
145
|
+
The same method accepts `args: %w[otp --access-code - settings 2
|
|
146
|
+
--delete-access-code]`: only the literal dash is accepted for that access-code
|
|
147
|
+
option, so the actual code is requested at the private prompt. Ordinary `command`
|
|
148
|
+
continues to close stdin. Equivalent official command shapes are:
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
ykman --device SERIAL piv access change-pin
|
|
152
|
+
ykman --device SERIAL fido access change-pin
|
|
153
|
+
ykman --device SERIAL oath accounts add 'Issuer:account'
|
|
154
|
+
ykman --device SERIAL otp --access-code - settings 2 --delete-access-code
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Check the installed command's `--help` first. Do not put literal credentials in
|
|
158
|
+
shell history or transcripts. Some upstream secret prompts are **not masked**;
|
|
159
|
+
turn off terminal recording and screen sharing. Do not guess PINs: failed attempts
|
|
160
|
+
can consume retries or block the application. `--remember` writes host keyring
|
|
161
|
+
state and requires explicit consent.
|
|
162
|
+
|
|
163
|
+
For file-based SCP11, pass `scp: [private_key_path, certificate_path]`,
|
|
164
|
+
`scp_ca: ca_path`, and, where needed, `scp_sd: [kid, kvn]` /
|
|
165
|
+
`scp_oce: [kid, kvn]`. References are two integer bytes. File order follows Yubico's
|
|
166
|
+
private-key/certificate-chain, leaf-last convention. No `scp-password` argument is
|
|
167
|
+
accepted; encrypted-key prompting belongs in the operator terminal.
|
|
168
|
+
|
|
169
|
+
**SCP03 limitation:** upstream 5.9.1 accepts custom SCP03 key material only inline
|
|
170
|
+
for global `--scp` and `sd keys import`; this wrapper refuses that exposure. Import
|
|
171
|
+
KID 1 and its alternate spellings are rejected before filename checks, even if a
|
|
172
|
+
file has the same name as the inline keys. File imports accept only SCP11 KIDs
|
|
173
|
+
`0x10`, `0x11`, `0x13`, `0x15`, `0x20`–`0x2f`, their unsigned decimal spellings,
|
|
174
|
+
or `SCP11a`/`SCP11b`/`SCP11c` names. Hex/name case and numeric leading zeros are
|
|
175
|
+
preserved; other spellings are rejected, not coerced. Custom SCP03 provisioning is
|
|
176
|
+
not provided through this credential-safe wrapper. Do not work around it by
|
|
177
|
+
putting keys into APDU argv. Raw APDUs are for nonsecret command bytes only; the
|
|
178
|
+
wrapper cannot infer the confidentiality of arbitrary protocol payloads.
|
|
179
|
+
|
|
180
|
+
## Existing-slot HMAC challenge-response
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
require 'securerandom'
|
|
184
|
+
challenge = SecureRandom.random_bytes(32) # Public challenge, not a provisioning key.
|
|
185
|
+
response = PWN::Plugins::YubiKey.challenge_response(
|
|
186
|
+
challenge: challenge,
|
|
187
|
+
slot: 2,
|
|
188
|
+
serial: '12345678',
|
|
189
|
+
timeout: 30
|
|
190
|
+
); nil # Suppress sensitive return-value echo in an interactive console.
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
`challenge:` is a raw Ruby String containing **1–64 bytes**, including NUL or
|
|
194
|
+
non-UTF-8 bytes. PWN encodes it once as hex for the official command:
|
|
195
|
+
|
|
196
|
+
```text
|
|
197
|
+
ykman --device SERIAL otp calculate SLOT HEX_CHALLENGE
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
`slot:` is integer **1 or 2**, default **2**. The return value is exactly **20 raw
|
|
201
|
+
bytes**, encoding `ASCII-8BIT`, not hex and not a time-based OTP. Decorated,
|
|
202
|
+
truncated, multiple or malformed responses are rejected. A touch-enabled slot
|
|
203
|
+
requires a physical touch before timeout; the wrapper does not print the CLI's
|
|
204
|
+
touch prompt. Missing or incompatible slots fail. **This method never programs,
|
|
205
|
+
resets, repairs or changes a slot**, and a default of slot 2 does not provision it.
|
|
206
|
+
FIDO-only Security Key models cannot provide this OTP HMAC operation.
|
|
207
|
+
|
|
208
|
+
The public challenge is visible in child argv. Never use a password or secret
|
|
209
|
+
key itself as a challenge. The slot secret is not exported during calculation;
|
|
210
|
+
the HMAC response nevertheless is sensitive key material in the Ruby process.
|
|
211
|
+
|
|
212
|
+
## Explicit HMAC provisioning
|
|
213
|
+
|
|
214
|
+
Provisioning is separate from authentication, inventory and vault access. It
|
|
215
|
+
**overwrites the chosen slot** and can permanently break existing uses of that
|
|
216
|
+
slot. Establish recovery before programming a device; a key's existing HMAC
|
|
217
|
+
secret cannot be read back. Preserve another independent authentication method.
|
|
218
|
+
|
|
219
|
+
1. Use `devices`, `info` and `otp(args: ['info'])` with the exact serial. Inspect
|
|
220
|
+
the target slot and its current purpose; never infer that slot 2 is unused.
|
|
221
|
+
2. Obtain explicit approval for that serial/slot. Securely generate or recover a
|
|
222
|
+
20-byte key in local memory. Decide whether an independent recovery token must
|
|
223
|
+
be provisioned with that same key **before** discarding it.
|
|
224
|
+
3. With **ykman 5.9.1**, run the dedicated method from trusted local Ruby code:
|
|
225
|
+
|
|
226
|
+
```ruby
|
|
227
|
+
require 'securerandom'
|
|
228
|
+
secret_key = SecureRandom.random_bytes(20); nil
|
|
229
|
+
PWN::Plugins::YubiKey.provision_challenge_response(
|
|
230
|
+
key: secret_key,
|
|
231
|
+
serial: '12345678',
|
|
232
|
+
slot: 2,
|
|
233
|
+
confirm: true,
|
|
234
|
+
timeout: 30
|
|
235
|
+
) # => :verified only after a fresh challenge matches the supplied key
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
The method verifies the CLI version, sends the hex key and a fixed affirmative
|
|
239
|
+
confirmation **through stdin**, and invokes `otp chalresp --touch 2` without a
|
|
240
|
+
key argv or `--force`. It then requests a fresh 32-byte challenge and checks the
|
|
241
|
+
response against Ruby OpenSSL HMAC-SHA1. **Touch the device for verification.**
|
|
242
|
+
It requires an explicit serial and always enables touch. Protected slots that
|
|
243
|
+
need an access code use the terminal workflow instead.
|
|
244
|
+
4. If version validation fails, no provisioning command runs. If provisioning or
|
|
245
|
+
readback fails later, the slot may already have changed: inspect it before
|
|
246
|
+
retrying. Do not assume rollback. Test a recovery token independently.
|
|
247
|
+
5. Discard the in-memory key only after the chosen recovery procedure is complete.
|
|
248
|
+
Ruby does not guarantee zeroization of strings and copies, and the REPL may
|
|
249
|
+
retain history/return values; this is why literals and return-value echo are
|
|
250
|
+
inappropriate for real keys.
|
|
251
|
+
|
|
252
|
+
Other CLI versions require a separately reviewed prompt contract or a private
|
|
253
|
+
operator terminal. For the latter, inspect `ykman otp chalresp --help`, then run
|
|
254
|
+
`ykman --device SERIAL otp chalresp --touch 2` **without a KEY argument** and supply
|
|
255
|
+
the key at the prompt. Upstream may echo it. Its `--generate` option also prints
|
|
256
|
+
the generated key, so it is not a secrecy-preserving shortcut.
|
|
257
|
+
|
|
258
|
+
## Exact OATH retrieval
|
|
259
|
+
|
|
260
|
+
```ruby
|
|
261
|
+
code = PWN::Plugins::YubiKey.oath_code(
|
|
262
|
+
account: 'Example:alice', # Exact identifier returned by OATH accounts list.
|
|
263
|
+
serial: '12345678',
|
|
264
|
+
confirm: true,
|
|
265
|
+
timeout: 30
|
|
266
|
+
); nil
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
The result contains only **6–8 decimal digits**, preserving leading zeros. Missing,
|
|
270
|
+
ambiguous, changed-identity, multiline and nonnumeric results fail closed. Steam
|
|
271
|
+
alphanumeric codes are deliberately outside this convenience API; the general
|
|
272
|
+
OATH interface still exposes official CLI output.
|
|
273
|
+
|
|
274
|
+
There is **no `--exact` option in official 5.9.1**. `--single` ensures one match but
|
|
275
|
+
still accepts substrings and removes the account label. Therefore this method:
|
|
276
|
+
|
|
277
|
+
1. Lists accounts with `--show-hidden --oath-type` and requires exactly one
|
|
278
|
+
case-sensitive complete identifier match.
|
|
279
|
+
2. Runs `oath accounts code --show-hidden -- ACCOUNT`, keeping the result label.
|
|
280
|
+
3. Checks that exactly one output row has the requested identifier and numeric
|
|
281
|
+
code before returning only the digits. It does not use unsupported flags or
|
|
282
|
+
falsely describe substring matching as exact matching.
|
|
283
|
+
|
|
284
|
+
`confirm: true` covers both inventory and calculation. Even `accounts list` may
|
|
285
|
+
authenticate with a remembered credential and delete/persist an incorrect
|
|
286
|
+
remembered key, without `--remember`. Consent is required even for TOTP:
|
|
287
|
+
upstream 5.9.1 `accounts code` may **automatically delete a corrupted credential**
|
|
288
|
+
after a memory error. HOTP also
|
|
289
|
+
advances its counter. This is not a read-only operation. Password-protected
|
|
290
|
+
applications that cannot unlock through the CLI's existing local state require
|
|
291
|
+
the private operator-terminal workflow; do not provide passwords in argv.
|
|
292
|
+
Two subprocesses are not an atomic device transaction. Do not concurrently change
|
|
293
|
+
accounts or swap devices; output identity is rechecked, but prior side effects
|
|
294
|
+
cannot be undone. Pin the serial and complete any required touch within timeout.
|
|
295
|
+
|
|
296
|
+
## Authentication and interoperability limits
|
|
297
|
+
|
|
298
|
+
FIDO PIN/resident-credential/fingerprint management is **not website login**.
|
|
299
|
+
Real U2F/FIDO2/WebAuthn enrollment and assertions belong to the browser and relying
|
|
300
|
+
party, including origin/RP binding, user presence and policy. This module neither
|
|
301
|
+
fabricates assertions nor bypasses security-key prompts. OATH codes must only be
|
|
302
|
+
submitted to a site's matching authenticator-code challenge, never an SMS-only
|
|
303
|
+
or passkey challenge.
|
|
304
|
+
|
|
305
|
+
PIV/OpenPGP management does not supply a TLS client, SSH agent or GPG middleware,
|
|
306
|
+
and does not export non-exportable private keys. YubiHSM Auth credentials are
|
|
307
|
+
not a replacement for a YubiHSM device. Device/firmware/application errors stay
|
|
308
|
+
errors rather than triggering reset, provisioning, software-secret fallback or
|
|
309
|
+
repeated PIN attempts.
|
|
310
|
+
|
|
311
|
+
## Offline verification and sources
|
|
312
|
+
|
|
313
|
+
```text
|
|
314
|
+
bundle exec rspec spec/lib/pwn/plugins/yubikey_spec.rb spec/lib/pwn/plugins/yubikey_security_spec.rb spec/lib/pwn/plugins/yubikey_terminal_spec.rb
|
|
315
|
+
bundle exec rubocop lib/pwn/plugins/yubikey.rb spec/lib/pwn/plugins/yubikey_spec.rb spec/lib/pwn/plugins/yubikey_security_spec.rb spec/lib/pwn/plugins/yubikey_terminal_spec.rb
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
The specs use executable Ruby fakes and synthetic credentials, including an
|
|
319
|
+
independent RFC 2202 HMAC-SHA1 vector. They exercise real process execution,
|
|
320
|
+
timeout/process-group cleanup, errors, argument guards, binary conversion,
|
|
321
|
+
exact OATH parsing, validated provisioning/readback, native PTY prompts and
|
|
322
|
+
terminal mode/status-flag restoration on success and failure, and pre-spawn duplex
|
|
323
|
+
validation without consuming input. No test opens a physical key,
|
|
324
|
+
logs in to a website or uses live credentials.
|
|
325
|
+
|
|
326
|
+
An isolated official 5.9.1 CLI was additionally exercised with `--help` at all
|
|
327
|
+
**124 recognized management command/group paths**. Its real Click provisioning
|
|
328
|
+
callback was exercised with a fake device session to validate the stdin contract.
|
|
329
|
+
These establish CLI compatibility, **not physical-device acceptance**. Hardware
|
|
330
|
+
USB/NFC, touches, PIN protection, firmware variants and real relying-party login
|
|
331
|
+
remain separate opt-in validation.
|
|
332
|
+
|
|
333
|
+
- [Yubico YubiKey Manager documentation](https://docs.yubico.com/software/yubikey/tools/ykman/)
|
|
334
|
+
- [Official 5.9.1 OTP CLI source](https://github.com/Yubico/yubikey-manager/blob/5.9.1/ykman/_cli/otp.py)
|
|
335
|
+
- [Official 5.9.1 OATH CLI source](https://github.com/Yubico/yubikey-manager/blob/5.9.1/ykman/_cli/oath.py)
|
|
336
|
+
- [OATH corrupted-credential repair](https://github.com/Yubico/yubikey-manager/blob/5.9.1/ykman/oath.py)
|
|
337
|
+
- [CLI piped-input behavior](https://github.com/Yubico/yubikey-manager/blob/5.9.1/ykman/_cli/util.py)
|
|
338
|
+
- [Security Domain CLI](https://github.com/Yubico/yubikey-manager/blob/5.9.1/ykman/_cli/securitydomain.py)
|
|
339
|
+
- [RFC 2202 HMAC test vectors](https://www.rfc-editor.org/rfc/rfc2202)
|