pwn 0.5.785 → 0.5.787
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/build_gem.sh +1 -1
- data/documentation/Backup-Retention.md +8 -9
- data/documentation/Harness-Evaluation.md +1 -1
- data/documentation/Installation.md +1 -1
- data/documentation/Operability.md +1 -0
- data/documentation/Plugin-Degradation.md +5 -3
- data/documentation/Plugins.md +1 -1
- data/documentation/Policy-Benchmark.md +32 -33
- data/documentation/YubiKey-Vaults.md +13 -11
- data/documentation/YubiKey.md +149 -270
- data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +1 -1
- data/documentation/diagrams/dot/reinforcement-learning.dot +2 -2
- data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +1 -1
- data/documentation/diagrams/reinforcement-learning.svg +89 -89
- data/lib/pwn/ai/agent/policy_evaluation.rb +326 -28
- data/lib/pwn/backups.rb +3 -1
- data/lib/pwn/plugins/repl/mesh.rb +11 -3
- data/lib/pwn/plugins/repl.rb +8 -0
- data/lib/pwn/version.rb +1 -1
- data/spec/lib/pwn/ai/agent/policy_evaluation_spec.rb +10 -23
- data/spec/lib/pwn/ai/cli_spec.rb +2 -7
- data/spec/lib/pwn/backups_spec.rb +15 -0
- data/spec/lib/pwn/plugins/repl_mesh_layout_spec.rb +2 -0
- data/third_party/pwn_rdoc.jsonl +16 -0
- metadata +1 -4
- data/scripts/benchmark_policy.rb +0 -376
- data/scripts/build_gate.rb +0 -58
- data/spec/integration/build_gate_spec.rb +0 -73
data/documentation/YubiKey.md
CHANGED
|
@@ -1,181 +1,123 @@
|
|
|
1
1
|
# YubiKey device operations
|
|
2
2
|
|
|
3
|
-
`PWN::Plugins::YubiKey`
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
`PWN::Plugins::YubiKey` implements YubiKey application protocols in Ruby. It
|
|
4
|
+
talks to the device through HIDAPI and PC/SC (`::FFI` bindings to those host
|
|
5
|
+
libraries). It does not start `ykman`, another device CLI, a Python helper, or
|
|
6
|
+
any subprocess. It is not a WebAuthn relying party.
|
|
7
|
+
|
|
8
|
+
Hardware capability and firmware still decide which operations succeed. Fixture
|
|
9
|
+
tests are not physical-key interoperability, and this page does not claim every
|
|
10
|
+
model or firmware revision.
|
|
7
11
|
|
|
8
12
|
For encrypted configuration, credential storage, conversion and recovery, see
|
|
9
13
|
[YubiKey-backed vaults and authentication](YubiKey-Vaults.md).
|
|
10
14
|
|
|
11
15
|
## Dependency and discovery
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
`required_bins` is empty. Core setup does not install hardware packages. The
|
|
18
|
+
`hardware` profile maps optional host libraries (`hidapi`, `pcsc`), not an
|
|
19
|
+
executable. Loading the module does not open a device. `available?` only probes
|
|
20
|
+
those libraries. A missing library, a missing device, a permission failure and
|
|
21
|
+
an unsupported application are different conditions. Preflight reports
|
|
22
|
+
`FIDO native transport` and `PC/SC native transport` without discovering
|
|
23
|
+
hardware. See [Plugin Degradation](Plugin-Degradation.md#pwn-plugins-yubikey).
|
|
19
24
|
|
|
20
25
|
```ruby
|
|
21
26
|
require 'pwn'
|
|
22
27
|
yk = PWN::Plugins::YubiKey
|
|
23
|
-
yk.required_bins
|
|
24
|
-
yk.available?
|
|
25
|
-
yk.devices
|
|
26
|
-
yk.info(serial: '12345678')
|
|
28
|
+
yk.required_bins # => []
|
|
29
|
+
yk.available?(backend: 'hid') # library probe; no device open
|
|
30
|
+
yk.devices # explicit listing; may be []
|
|
31
|
+
yk.info(serial: '12345678') # example serial; replace locally
|
|
27
32
|
yk.otp(args: ['info'], serial: '12345678')
|
|
28
|
-
yk.help
|
|
29
|
-
yk.cli_help
|
|
33
|
+
yk.help # public methods and option descriptions
|
|
34
|
+
yk.cli_help # local native help metadata, not a CLI process
|
|
30
35
|
yk.cli_help(path: %w[piv keys generate])
|
|
31
36
|
```
|
|
32
37
|
|
|
33
|
-
`ykman
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
There is no `ykman:` path option. Executable paths, stdin, log files and inline
|
|
39
|
+
credential argv are rejected. Serial values must be decimal Strings; they are
|
|
40
|
+
not trimmed or coerced. Omit the serial only when selection is unambiguous.
|
|
41
|
+
PWN never chooses the first of several devices. `reader:` and `device_path:`
|
|
42
|
+
are mutually exclusive with each other and with `serial:` when more than one
|
|
43
|
+
is set. A caller-owned `connection:` stays open; PWN closes only handles it
|
|
44
|
+
opened.
|
|
39
45
|
|
|
40
|
-
##
|
|
46
|
+
## Native application coverage
|
|
41
47
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
the complete
|
|
45
|
-
|
|
48
|
+
Family methods take `args:` as an argv Array **after the family name**. With
|
|
49
|
+
no `args`, they return that family's local help metadata. `command(args:)`
|
|
50
|
+
takes the complete nonsecret argv, including the family name, and dispatches
|
|
51
|
+
to the matching Ruby application. It returns the application result; it does
|
|
52
|
+
not print or log it.
|
|
46
53
|
|
|
47
|
-
| Method |
|
|
54
|
+
| Method | Application | Covered operations |
|
|
48
55
|
|---|---|---|
|
|
49
|
-
| `config` |
|
|
50
|
-
| `otp` |
|
|
51
|
-
| `oath` |
|
|
52
|
-
| `fido` |
|
|
53
|
-
| `piv` |
|
|
54
|
-
| `openpgp` |
|
|
55
|
-
| `hsmauth` |
|
|
56
|
-
| `security_domain` |
|
|
57
|
-
| `apdu` |
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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:
|
|
56
|
+
| `config` | management | USB/NFC application enablement, mode, lock code, timeouts, reset |
|
|
57
|
+
| `otp` | OTP | Slot inventory, Yubico OTP, static password, HOTP, HMAC challenge-response, settings, NDEF, swap, delete |
|
|
58
|
+
| `oath` | OATH | Account list/add/URI/import/rename/delete/code, access password, caller-owned cache, reset |
|
|
59
|
+
| `fido` | FIDO | PIN changes/verification, minimum PIN length, resident credential list/delete, fingerprints, UV/attestation policy, reset |
|
|
60
|
+
| `piv` | PIV | PIN/PUK/management key, key generation/import/export/move/delete/attestation, certificates, CSR and object management, reset |
|
|
61
|
+
| `openpgp` | OpenPGP | PIN/admin/reset code and retry policy, key import/attestation/touch policy, certificates, reset |
|
|
62
|
+
| `hsmauth` | HSM Auth | Asymmetric/symmetric/derived credentials, credential passwords, management protection, reset |
|
|
63
|
+
| `security_domain` | Security Domain | SCP key information, generation/import/export/deletion/allowlists and reset |
|
|
64
|
+
| `apdu` | smartcard | Explicit APDUs. Mutations require `confirm: true` |
|
|
65
|
+
|
|
66
|
+
Unknown command grammar is rejected. Do not pass a shell string. Use separate
|
|
67
|
+
argv elements: `args: ['keys', 'info', '9a']`, not `args: 'keys info 9a'`.
|
|
68
|
+
Short aliases and `--option=value` are rejected. `--` is available before a
|
|
69
|
+
positional identifier that begins with a dash.
|
|
70
|
+
|
|
71
|
+
### Confirmation, secrets and deadlines
|
|
72
|
+
|
|
73
|
+
Existing-slot HMAC calculation is the vault unlock path. Omitted `confirm` is
|
|
74
|
+
allowed. If `confirm` is present it must be literal `true`; `false`, `nil` and
|
|
75
|
+
`'true'` are rejected before any open.
|
|
76
|
+
|
|
77
|
+
Mutations, OATH calculation, provisioning and raw APDUs require literal
|
|
78
|
+
`confirm: true` before the device is opened. Confirmation does not guess
|
|
79
|
+
factory PINs, retry a blocked application, or delete a credential. Native OATH
|
|
80
|
+
does not delete or repair a corrupted credential. HOTP still advances its
|
|
81
|
+
counter. A password-protected OATH account needs an in-memory `password:` or
|
|
82
|
+
`access_key:`, or a caller `secret_provider`.
|
|
83
|
+
|
|
84
|
+
PINs, PUKs, management keys, access codes and OATH passwords stay in memory or
|
|
85
|
+
come from that provider. They are not argv, exception text, or logs. For a
|
|
86
|
+
private operator terminal, outside an agent request:
|
|
124
87
|
|
|
125
88
|
```ruby
|
|
126
89
|
yk.interact(
|
|
127
90
|
args: %w[fido access change-pin], serial: '12345678',
|
|
128
|
-
confirm: true, timeout: 90
|
|
91
|
+
confirm: true, operator: true, timeout: 90
|
|
129
92
|
)
|
|
130
93
|
```
|
|
131
94
|
|
|
132
|
-
|
|
133
|
-
readable
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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.
|
|
95
|
+
`interact` prompts on the controlling console, or on an explicitly supplied
|
|
96
|
+
readable and writable `terminal:` IO, then runs one native command. It returns
|
|
97
|
+
only `:completed`. It does not start a process, retain a transcript, or close
|
|
98
|
+
caller-owned IO. Run it outside curses and recorded tool sessions. Ruby does
|
|
99
|
+
not guarantee string zeroization.
|
|
100
|
+
|
|
101
|
+
`timeout:` is one finite positive budget in seconds, default **30**. It covers
|
|
102
|
+
open, secure-channel setup, authentication and commands. Remaining time is
|
|
103
|
+
what later exchanges receive; each step does not get a fresh 30 seconds.
|
|
104
|
+
`SCardCancel` does not universally interrupt `SCardTransmit`, and killing a
|
|
105
|
+
Ruby thread does not cancel a native driver call. After a timeout or
|
|
106
|
+
interruption, inspect device state before retrying a mutation.
|
|
107
|
+
|
|
108
|
+
Missing libraries, command failure, timeout, output limits and malformed
|
|
109
|
+
responses raise `DependencyError`, `CommandError`, `TimeoutError`,
|
|
110
|
+
`OutputLimitError` or `ResponseError`. These inherit from `YubiKey::Error`.
|
|
111
|
+
Missing consent raises `ConfirmationRequired`. Invalid caller values raise
|
|
112
|
+
`ArgumentError`. Errors do not include request bytes.
|
|
113
|
+
|
|
114
|
+
### Secure channel
|
|
115
|
+
|
|
116
|
+
`secure_channel:` is an explicit Hash, not a file of inline CLI keys. It
|
|
117
|
+
requires `scp:` (`:scp03`, `:scp11a`, `:scp11b` or `:scp11c`) and integer
|
|
118
|
+
`kvn:`. SCP03 also requires 16-byte in-memory `key_enc` and `key_mac`. A
|
|
119
|
+
failed secure-channel handshake does not fall back to plaintext. The owned
|
|
120
|
+
handle is still closed.
|
|
179
121
|
|
|
180
122
|
## Existing-slot HMAC challenge-response
|
|
181
123
|
|
|
@@ -190,150 +132,87 @@ response = PWN::Plugins::YubiKey.challenge_response(
|
|
|
190
132
|
); nil # Suppress sensitive return-value echo in an interactive console.
|
|
191
133
|
```
|
|
192
134
|
|
|
193
|
-
`challenge:` is a raw Ruby String
|
|
194
|
-
|
|
135
|
+
`challenge:` is a raw Ruby String of **1–64 bytes**, not pre-encoded hex.
|
|
136
|
+
`slot:` is integer **1 or 2**, default **2**. The return value is exactly
|
|
137
|
+
**20 raw bytes**, encoding `ASCII-8BIT`. A touch-enabled slot requires a
|
|
138
|
+
physical touch before timeout. Missing or incompatible slots fail. This method
|
|
139
|
+
never programs, resets or repairs a slot. FIDO-only Security Key models cannot
|
|
140
|
+
provide this OTP HMAC operation.
|
|
195
141
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
142
|
+
The challenge is not placed on a child argv, because no child is started. Do
|
|
143
|
+
not use a password as the challenge. The HMAC response is sensitive key
|
|
144
|
+
material in the Ruby process.
|
|
199
145
|
|
|
200
|
-
|
|
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.
|
|
146
|
+
## Explicit HMAC provisioning
|
|
207
147
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
148
|
+
Provisioning is separate from authentication and vault unlock. It **overwrites
|
|
149
|
+
the chosen slot**. The existing HMAC secret cannot be read back. Keep another
|
|
150
|
+
authentication method, and test recovery before discarding the new key.
|
|
211
151
|
|
|
212
|
-
|
|
152
|
+
```ruby
|
|
153
|
+
require 'securerandom'
|
|
154
|
+
secret_key = SecureRandom.random_bytes(20); nil
|
|
155
|
+
PWN::Plugins::YubiKey.provision_challenge_response(
|
|
156
|
+
key: secret_key,
|
|
157
|
+
serial: '12345678',
|
|
158
|
+
slot: 2,
|
|
159
|
+
confirm: true,
|
|
160
|
+
timeout: 30
|
|
161
|
+
) # => :verified only after a fresh challenge matches the supplied key
|
|
162
|
+
```
|
|
213
163
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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.
|
|
164
|
+
`confirm: true` is required before open. An explicit serial, reader,
|
|
165
|
+
device path or caller-owned connection is required. `touch:` defaults to
|
|
166
|
+
`true`. Optional access codes are six raw bytes, supplied in memory, not at a
|
|
167
|
+
CLI prompt. The method checks a fresh challenge with Ruby OpenSSL HMAC-SHA1
|
|
168
|
+
and returns `:verified` only when that check passes. Touch the device when the
|
|
169
|
+
slot requires it. If programming succeeds and readback fails, the slot may
|
|
170
|
+
already have changed: inspect it before retrying. Do not assume rollback.
|
|
257
171
|
|
|
258
172
|
## Exact OATH retrieval
|
|
259
173
|
|
|
260
174
|
```ruby
|
|
261
175
|
code = PWN::Plugins::YubiKey.oath_code(
|
|
262
|
-
account: 'Example:alice', # Exact identifier
|
|
176
|
+
account: 'Example:alice', # Exact identifier, not a substring.
|
|
263
177
|
serial: '12345678',
|
|
264
178
|
confirm: true,
|
|
265
179
|
timeout: 30
|
|
266
180
|
); nil
|
|
267
181
|
```
|
|
268
182
|
|
|
269
|
-
The result
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
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.
|
|
183
|
+
The result is **6–8 decimal digits**, preserving leading zeros. The account
|
|
184
|
+
must be an exact control-free String of 1 to 64 bytes. Steam alphanumeric
|
|
185
|
+
codes are outside this method. `confirm: true` is required before open, including
|
|
186
|
+
for TOTP, because HOTP advances its counter and a protected account may
|
|
187
|
+
authenticate. Consent does not authorize deleting a corrupted credential.
|
|
188
|
+
Device errors do not fall back to a manual token.
|
|
295
189
|
|
|
296
190
|
## Authentication and interoperability limits
|
|
297
191
|
|
|
298
|
-
FIDO PIN
|
|
299
|
-
|
|
300
|
-
party
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
or passkey challenge.
|
|
192
|
+
FIDO PIN, resident-credential and fingerprint management is **not website
|
|
193
|
+
login**. U2F/FIDO2/WebAuthn enrollment and assertions belong to the browser and
|
|
194
|
+
relying party. This module does not fabricate assertions. Submit an OATH code
|
|
195
|
+
only to a matching authenticator-code challenge, never an SMS-only or passkey
|
|
196
|
+
challenge. PayPal's SMS adapter rejects hardware OATH before login.
|
|
304
197
|
|
|
305
|
-
PIV
|
|
306
|
-
and
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
198
|
+
PIV and OpenPGP management do not supply a TLS client, SSH agent or GPG
|
|
199
|
+
middleware, and do not export non-exportable private keys. YubiHSM Auth
|
|
200
|
+
credentials are not a YubiHSM. Device and firmware errors stay errors. They do
|
|
201
|
+
not trigger reset, provisioning, a software-secret fallback, or repeated PIN
|
|
202
|
+
attempts.
|
|
310
203
|
|
|
311
|
-
## Offline verification
|
|
204
|
+
## Offline verification
|
|
312
205
|
|
|
313
206
|
```text
|
|
314
207
|
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
208
|
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
209
|
```
|
|
317
210
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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)
|
|
211
|
+
Those specs use synthetic connections and credentials, including an independent
|
|
212
|
+
RFC 2202 HMAC-SHA1 vector. They do not open a physical key, log in to a website,
|
|
213
|
+
or prove every firmware variant. USB/NFC, touch, PIN protection and real
|
|
214
|
+
relying-party login remain separate opt-in checks.
|
|
215
|
+
|
|
339
216
|
- [RFC 2202 HMAC test vectors](https://www.rfc-editor.org/rfc/rfc2202)
|
|
217
|
+
- [GlobalPlatform Card Specification](https://globalplatform.org/specs-library/card-specification/)
|
|
218
|
+
- [Yubico OTP protocol notes](https://developers.yubico.com/OTP/)
|
|
@@ -50,6 +50,6 @@ digraph PWN_Feedback {
|
|
|
50
50
|
{rank=same; Retain; Receipt}
|
|
51
51
|
|
|
52
52
|
Trainer [fillcolor="#1e293b", fontcolor="#cbd5e1", style="rounded,dashed,filled",
|
|
53
|
-
label="SEPARATE OPTIONAL WEIGHT PATH\nCurriculum export / configured trainer is opt-in\nNot routing-policy promotion or proof of adapter gains\
|
|
53
|
+
label="SEPARATE OPTIONAL WEIGHT PATH\nCurriculum export / configured trainer is opt-in\nNot routing-policy promotion or proof of adapter gains\nCurriculum jobs are not seeded"];
|
|
54
54
|
{rank=same; Reuse; Trainer}
|
|
55
55
|
}
|
|
@@ -27,13 +27,13 @@ digraph "PWN_Reinforcement_Learning" {
|
|
|
27
27
|
subgraph cluster_curriculum {
|
|
28
28
|
label="OPTIONAL CURRICULUM · independent invocation"; fontsize=12;
|
|
29
29
|
style="rounded,dashed,filled"; color="#94a3b8"; fillcolor="#1e293b";
|
|
30
|
-
Schedule [fillcolor="#7dd3fc", label="A OPT IN / INVOKE EXPLICITLY\
|
|
30
|
+
Schedule [fillcolor="#7dd3fc", label="A OPT IN / INVOKE EXPLICITLY\nCurriculum jobs are not seeded\nCreate a CURRICULUM_JOBS template only when wanted\nTemplates stay disabled until explicitly enabled\nSeeding does not install system crontab"];
|
|
31
31
|
Practice [fillcolor="#6ee7b7", label="B PRACTICE / OFFLINE JUDGING\nPractice: budget-first; real tools may run\nJudge-qualified resolution + winning traces\nOffline judge: backfill, calibrate, warm sentinel\nRecords: curriculum/ + mistakes / preferences"];
|
|
32
32
|
Export [fillcolor="#fcd34d", label="C EXPORT TRAINING DATA\nLearning.export_finetune + Reward.export_dpo\nEligible sessions / outcomes + preference pairs\nScrub, geometry and source-balance filters\nOutput: finetune/*.jsonl + evaluation set"];
|
|
33
33
|
Train [fillcolor="#fda4af", label="D train_and_gate\nDry run or no trainer → export_ready only\nOtherwise: configured trainer → LoRA adapter\nollama create → candidate vs baseline gate\nPreference-diet gate also required"];
|
|
34
34
|
Model [fillcolor="#6ee7b7", label="E RETAIN GATED ADAPTER VERSION\nOn passing gates: update curriculum model state\nOptional local weight path, not routing policy\nExport alone is not training or improvement"];
|
|
35
35
|
Hygiene [fillcolor="#1e293b", fontcolor="#cbd5e1", style="rounded,dashed,filled",
|
|
36
|
-
label="SEPARATE ENABLED HYGIENE SEED\
|
|
36
|
+
label="SEPARATE ENABLED HYGIENE SEED\nsession_cleanup at 03:45 daily\nIncludes memory consolidation; not model training\nESR = verified_exploit_tools / vulnerable_tools\nASR = successful_attacks / total_attack_attempts"];
|
|
37
37
|
Schedule -> Practice [label="independent jobs; not a job chain", style=dashed];
|
|
38
38
|
Practice -> Export [label="eligible retained data", style=dashed];
|
|
39
39
|
Export -> Train -> Model;
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
<text xml:space="preserve" text-anchor="middle" x="555" y="-71.07" font-family="sans-Serif" font-size="11.00" fill="#cbd5e1">SEPARATE OPTIONAL WEIGHT PATH</text>
|
|
188
188
|
<text xml:space="preserve" text-anchor="middle" x="555" y="-57.57" font-family="sans-Serif" font-size="11.00" fill="#cbd5e1">Curriculum export / configured trainer is opt-in</text>
|
|
189
189
|
<text xml:space="preserve" text-anchor="middle" x="555" y="-44.07" font-family="sans-Serif" font-size="11.00" fill="#cbd5e1">Not routing-policy promotion or proof of adapter gains</text>
|
|
190
|
-
<text xml:space="preserve" text-anchor="middle" x="555" y="-30.57" font-family="sans-Serif" font-size="11.00" fill="#cbd5e1">
|
|
190
|
+
<text xml:space="preserve" text-anchor="middle" x="555" y="-30.57" font-family="sans-Serif" font-size="11.00" fill="#cbd5e1">Curriculum jobs are not seeded</text>
|
|
191
191
|
</g>
|
|
192
192
|
</g>
|
|
193
193
|
</svg>
|