pwn 0.5.621 → 0.5.626
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/.rubocop.yml +2 -2
- data/Gemfile +1 -1
- data/README.md +7 -1
- data/bin/pwn_gqrx_scanner +78 -9
- data/documentation/Agent-Tool-Registry.md +3 -3
- data/documentation/Configuration.md +301 -47
- data/documentation/Cron.md +5 -3
- data/documentation/Diagrams.md +1 -1
- data/documentation/Extrospection.md +472 -26
- data/documentation/FFI.md +72 -8
- data/documentation/Home.md +4 -4
- data/documentation/How-PWN-Works.md +7 -3
- data/documentation/Mistakes.md +9 -0
- data/documentation/SDR.md +83 -10
- data/documentation/Skills-Memory-Learning.md +101 -11
- data/documentation/diagrams/agent-tool-registry.svg +56 -55
- data/documentation/diagrams/ai-integration-tool-calling.svg +24 -24
- data/documentation/diagrams/aws-cloud-security.svg +25 -25
- data/documentation/diagrams/burp-vs-zap-preference.svg +12 -12
- data/documentation/diagrams/code-scanning-sast.svg +25 -25
- data/documentation/diagrams/cron-scheduling.svg +23 -23
- data/documentation/diagrams/dot/agent-tool-registry.dot +2 -2
- data/documentation/diagrams/dot/extrospection-world-awareness.dot +33 -6
- data/documentation/diagrams/dot/hardware-hacking.dot +3 -1
- data/documentation/diagrams/dot/memory-skills-detailed.dot +4 -2
- data/documentation/diagrams/dot/mistakes-negative-feedback.dot +4 -2
- data/documentation/diagrams/dot/overall-pwn-architecture.dot +3 -3
- data/documentation/diagrams/dot/persistence-filesystem.dot +3 -3
- data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +10 -4
- data/documentation/diagrams/dot/sdr-radio-flow.dot +39 -16
- data/documentation/diagrams/driver-framework.svg +13 -13
- data/documentation/diagrams/extrospection-world-awareness.svg +383 -177
- data/documentation/diagrams/fuzzing-workflow.svg +24 -24
- data/documentation/diagrams/hardware-hacking.svg +84 -69
- data/documentation/diagrams/history-to-drivers.svg +18 -18
- data/documentation/diagrams/memory-skills-detailed.svg +137 -120
- data/documentation/diagrams/mistakes-negative-feedback.svg +152 -137
- data/documentation/diagrams/network-infra-testing.svg +27 -27
- data/documentation/diagrams/overall-pwn-architecture.svg +97 -97
- data/documentation/diagrams/penetration-testing-workflow.svg +30 -30
- data/documentation/diagrams/persistence-filesystem.svg +100 -94
- data/documentation/diagrams/plugin-ecosystem.svg +35 -35
- data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +254 -207
- data/documentation/diagrams/pwn-repl-prototyping.svg +20 -20
- data/documentation/diagrams/reporting-pipeline.svg +18 -18
- data/documentation/diagrams/reverse-engineering-flow.svg +21 -21
- data/documentation/diagrams/sdr-radio-flow.svg +223 -91
- data/documentation/diagrams/sessions-cron-automation.svg +18 -18
- data/documentation/diagrams/swarm-multi-agent.svg +39 -39
- data/documentation/diagrams/web-application-testing.svg +26 -26
- data/documentation/diagrams/zero-day-research-flow.svg +25 -25
- data/documentation/pwn-ai-Agent.md +16 -10
- data/documentation/pwn_silent_help_learn_demo.gif +0 -0
- data/lib/pwn/ai/agent/assembly.rb +1 -1
- data/lib/pwn/ai/agent/btc.rb +1 -1
- data/lib/pwn/ai/agent/burp_suite.rb +1 -1
- data/lib/pwn/ai/agent/extrospection.rb +2562 -57
- data/lib/pwn/ai/agent/gqrx.rb +2 -2
- data/lib/pwn/ai/agent/hacker_one.rb +1 -1
- data/lib/pwn/ai/agent/learning.rb +16 -16
- data/lib/pwn/ai/agent/loop.rb +1 -1
- data/lib/pwn/ai/agent/{introspection.rb → reflect.rb} +12 -12
- data/lib/pwn/ai/agent/sast.rb +1 -1
- data/lib/pwn/ai/agent/tools/extrospection.rb +311 -8
- data/lib/pwn/ai/agent/tools/learning.rb +7 -7
- data/lib/pwn/ai/agent/transparent_browser.rb +1 -1
- data/lib/pwn/ai/agent/vuln_gen.rb +2 -2
- data/lib/pwn/ai/agent.rb +1 -1
- data/lib/pwn/ai/open_ai.rb +10 -6
- data/lib/pwn/config.rb +5 -4
- data/lib/pwn/ffi/adalm_pluto.rb +498 -0
- data/lib/pwn/ffi/fftw.rb +192 -0
- data/lib/pwn/ffi/hack_rf.rb +193 -0
- data/lib/pwn/ffi/liquid.rb +244 -0
- data/lib/pwn/ffi/rtl_sdr.rb +210 -0
- data/lib/pwn/ffi/soapy_sdr.rb +177 -0
- data/lib/pwn/ffi/stdio.rb +9 -1
- data/lib/pwn/ffi/volk.rb +241 -0
- data/lib/pwn/ffi.rb +45 -2
- data/lib/pwn/plugins/burp_suite.rb +2 -2
- data/lib/pwn/sast/pom_version.rb +2 -2
- data/lib/pwn/sast/test_case_engine.rb +1 -1
- data/lib/pwn/sdr/decoder/adsb.rb +201 -12
- data/lib/pwn/sdr/decoder/apt.rb +19 -5
- data/lib/pwn/sdr/decoder/base.rb +314 -1
- data/lib/pwn/sdr/decoder/bluetooth.rb +91 -18
- data/lib/pwn/sdr/decoder/dect.rb +81 -23
- data/lib/pwn/sdr/decoder/dsp.rb +229 -15
- data/lib/pwn/sdr/decoder/flex.rb +23 -6
- data/lib/pwn/sdr/decoder/gps.rb +80 -18
- data/lib/pwn/sdr/decoder/gsm.rb +83 -28
- data/lib/pwn/sdr/decoder/iridium.rb +80 -18
- data/lib/pwn/sdr/decoder/lora.rb +84 -28
- data/lib/pwn/sdr/decoder/lte.rb +80 -18
- data/lib/pwn/sdr/decoder/morse.rb +23 -6
- data/lib/pwn/sdr/decoder/p25.rb +90 -31
- data/lib/pwn/sdr/decoder/pager.rb +23 -6
- data/lib/pwn/sdr/decoder/pocsag.rb +23 -6
- data/lib/pwn/sdr/decoder/rds.rb +219 -52
- data/lib/pwn/sdr/decoder/rfid.rb +81 -27
- data/lib/pwn/sdr/decoder/rtl433.rb +85 -27
- data/lib/pwn/sdr/decoder/rtty.rb +23 -6
- data/lib/pwn/sdr/decoder/wifi.rb +86 -32
- data/lib/pwn/sdr/decoder/zigbee.rb +88 -35
- data/lib/pwn/sdr/decoder.rb +6 -5
- data/lib/pwn/sdr/frequency_allocation.rb +124 -81
- data/lib/pwn/sdr/gqrx.rb +1513 -165
- data/lib/pwn/version.rb +1 -1
- data/spec/lib/pwn/ai/agent/extrospection_spec.rb +96 -0
- data/spec/lib/pwn/ai/agent/{introspection_spec.rb → reflect_spec.rb} +3 -3
- data/spec/lib/pwn/ai/agent/tools/extrospection_spec.rb +8 -24
- data/spec/lib/pwn/ffi/adalm_pluto_spec.rb +37 -0
- data/spec/lib/pwn/ffi/fftw_spec.rb +26 -0
- data/spec/lib/pwn/ffi/hack_rf_spec.rb +25 -0
- data/spec/lib/pwn/ffi/liquid_spec.rb +42 -0
- data/spec/lib/pwn/ffi/rtl_sdr_spec.rb +24 -0
- data/spec/lib/pwn/ffi/soapy_sdr_spec.rb +25 -0
- data/spec/lib/pwn/ffi/volk_spec.rb +36 -0
- data/spec/lib/pwn/sdr/decoder/base_iq_spec.rb +65 -0
- data/spec/lib/pwn/sdr/decoder/dsp_spec.rb +50 -4
- data/spec/lib/pwn/sdr/decoder/rds_spec.rb +45 -4
- data/third_party/pwn_rdoc.jsonl +279 -30
- metadata +21 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 67a226a1a110698db44ee0378d3f9a5fd290d96d633487a3dd4a7e72c1ac09d9
|
|
4
|
+
data.tar.gz: 8acea5ce6ab68d30486aef426c176611f379a31acf3092cdea7ced91e8dbf8e9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 48c6bca36c123d6419ee8fd12ff6813e2ab405b4fbd92fb31d1c64aea4ca3a2f75ee25e06e5db61d6db9d58775f8228b51783396c1c8e688dcf6afd224720025
|
|
7
|
+
data.tar.gz: 022c9adac00e0ccab76bbd4f6c86d603a32a55ce41e4e0b7d6093a59e52834b4692dbb700bb0e1c8ee2ba50bc0be1a5dd6db0fc80b76308d34188be1f623ce25
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|

|
|
2
2
|
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="documentation/pwn_silent_help_learn_demo.gif" alt="PWN Silent Demo — Help Surfaces + Learning Feedback Loop" width="640">
|
|
5
|
+
<br>
|
|
6
|
+
<em>Silent walkthrough: <code>pwn</code> help surfaces → <code>pwn-ai</code> → recon → mistakes / learning / extrospection feedback loop</em>
|
|
7
|
+
</p>
|
|
8
|
+
|
|
3
9
|
### **Table of Contents** ###
|
|
4
10
|
|
|
5
11
|
- [Intro](#intro)
|
|
@@ -52,7 +58,7 @@ Five layers, edges only ever go down:
|
|
|
52
58
|
|
|
53
59
|
The AI layer closes a **self-improvement loop** on every turn — Metrics +
|
|
54
60
|
Learning + **Mistakes** (introspection / negative feedback) joined with
|
|
55
|
-
Snapshot + Drift + Intel + RF + **Web** (extrospection) — plus browser-backed **`extro_verify`**
|
|
61
|
+
Snapshot + Drift + Intel + RF + **Web** (extrospection) — plus browser-backed **`extro_verify`** / **`extro_watch`** and RF **`extro_rf_tune`** sensing — via `extro_correlate`, so the
|
|
56
62
|
agent knows whether a failure was *its* fault or *the world* changed —
|
|
57
63
|
**and does not repeat the same mistake twice**:
|
|
58
64
|
|
data/bin/pwn_gqrx_scanner
CHANGED
|
@@ -76,8 +76,8 @@ PWN::Driver::Parser.new do |options|
|
|
|
76
76
|
opts[:fft_scan] = f
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
options.on('--
|
|
80
|
-
opts[:
|
|
79
|
+
options.on('--input-rate=RATE', '<Optional --fft-scan - GQRX Input rate / visible span in Hz (default 1_000_000). NOTE: no short flag; -S is --strength-lock>') do |s|
|
|
80
|
+
opts[:input_rate] = s
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
options.on('-NINT', '--nfft=INT', '<Optional --fft-scan - FFT bin size (default 2048)>') do |n|
|
|
@@ -100,13 +100,21 @@ PWN::Driver::Parser.new do |options|
|
|
|
100
100
|
opts[:strength_offset_db] = o
|
|
101
101
|
end
|
|
102
102
|
|
|
103
|
-
options.on('--min-snr-db=FLOAT', '<Optional --fft-scan - Minimum SNR (dB above per-chunk noise floor) to report a signal (default
|
|
103
|
+
options.on('--min-snr-db=FLOAT', '<Optional --fft-scan - Minimum SNR (dB above per-chunk noise floor) to report a signal (default 18.0)>') do |m|
|
|
104
104
|
opts[:min_snr_db] = m
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
-
options.on('--min-bw-ratio=FLOAT', '<Optional --fft-scan - Reject FFT peaks narrower than RATIO * band-plan bandwidth as spurs (default 0.
|
|
107
|
+
options.on('--min-bw-ratio=FLOAT', '<Optional --fft-scan - Reject FFT peaks narrower than RATIO * band-plan bandwidth as spurs (default 0.0 = off)>') do |r|
|
|
108
108
|
opts[:min_bw_ratio] = r
|
|
109
109
|
end
|
|
110
|
+
|
|
111
|
+
options.on('--no-refine', '<Optional --fft-scan - Skip the post-FFT iterative edge/peak refine pass that locks the exact channel frequency (default: refine ON)>') do
|
|
112
|
+
opts[:refine] = false
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
options.on('--refine-mode=MODE', '<Optional --fft-scan - Refine strategy: lock (default, fast S-meter raster hunt), fft (legacy local high-res FFT zoom), hybrid (both)>') do |m|
|
|
116
|
+
opts[:refine_mode] = m
|
|
117
|
+
end
|
|
110
118
|
end.parse!
|
|
111
119
|
|
|
112
120
|
begin
|
|
@@ -122,13 +130,55 @@ begin
|
|
|
122
130
|
end
|
|
123
131
|
|
|
124
132
|
profile = opts[:profile]
|
|
133
|
+
|
|
134
|
+
# Common user-facing aliases → canonical band_plans keys.
|
|
135
|
+
# (historical/typo names should not crash with Hash#merge! TypeError)
|
|
136
|
+
profile_aliases = {
|
|
137
|
+
'flex_pager' => 'pager_flex',
|
|
138
|
+
'flex' => 'pager_flex',
|
|
139
|
+
'pocsag_pager' => 'pager_pocsag',
|
|
140
|
+
'pocsag' => 'pager_pocsag',
|
|
141
|
+
'pager' => 'pager_all',
|
|
142
|
+
'pagers' => 'pager_all',
|
|
143
|
+
'adsb' => 'ads_b1090',
|
|
144
|
+
'adsb1090' => 'ads_b1090',
|
|
145
|
+
'adsb978' => 'ads_b978',
|
|
146
|
+
'fm' => 'fm_radio',
|
|
147
|
+
'noaa' => 'noaa_weather',
|
|
148
|
+
'wx' => 'noaa_weather',
|
|
149
|
+
'weather' => 'noaa_weather'
|
|
150
|
+
}.freeze
|
|
151
|
+
|
|
152
|
+
resolve_band_plan = lambda do |name|
|
|
153
|
+
return nil if name.nil?
|
|
154
|
+
|
|
155
|
+
key = name.to_s.strip.downcase.tr('-', '_').to_sym
|
|
156
|
+
key = profile_aliases[key.to_s].to_sym if profile_aliases.key?(key.to_s)
|
|
157
|
+
return key if band_plans.key?(key)
|
|
158
|
+
|
|
159
|
+
# fuzzy suggestions for helpful errors
|
|
160
|
+
cand = band_plans.keys.map(&:to_s)
|
|
161
|
+
suggestions = cand.select do |k|
|
|
162
|
+
k.include?(key.to_s) || key.to_s.include?(k) ||
|
|
163
|
+
k.split('_').intersect?(key.to_s.split('_'))
|
|
164
|
+
end
|
|
165
|
+
suggestions = cand.grep(/#{Regexp.escape(key.to_s.split('_').first)}/i) if suggestions.empty? && !key.to_s.empty?
|
|
166
|
+
msg = "ERROR: Unknown band plan profile: #{name.inspect}."
|
|
167
|
+
msg += " Did you mean: #{suggestions.sort.first(8).join(', ')}?" unless suggestions.empty?
|
|
168
|
+
msg += ' Use --list-band-plans to display supported profiles.'
|
|
169
|
+
raise msg
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
profile_key = resolve_band_plan.call(profile)
|
|
173
|
+
warn "[*] alias #{profile.inspect} → band plan #{profile_key}" if profile_key && profile.to_s.strip.downcase.tr('-', '_') != profile_key.to_s
|
|
174
|
+
|
|
125
175
|
# Merge opts with profile values if profile provided
|
|
126
|
-
opts.merge!(band_plans[
|
|
176
|
+
opts.merge!(band_plans[profile_key]) unless profile_key.nil?
|
|
127
177
|
|
|
128
178
|
scan_ranges = opts[:scan_ranges]
|
|
129
|
-
raise 'ERROR: --assume-band-plan || --scan-ranges is required.' if scan_ranges.nil? &&
|
|
179
|
+
raise 'ERROR: --assume-band-plan || --scan-ranges is required.' if scan_ranges.nil? && profile_key.nil?
|
|
130
180
|
|
|
131
|
-
ranges = band_plans[
|
|
181
|
+
ranges = band_plans[profile_key][:ranges] unless profile_key.nil?
|
|
132
182
|
if ranges.nil?
|
|
133
183
|
# Convert comma-delimited string to array of hashes
|
|
134
184
|
ranges = scan_ranges.split(',').map do |r|
|
|
@@ -179,11 +229,19 @@ begin
|
|
|
179
229
|
location = opts[:location]
|
|
180
230
|
|
|
181
231
|
# Merge opts one last time to ensure parameters passed to the driver are included
|
|
182
|
-
opts.merge!(band_plans[
|
|
232
|
+
opts.merge!(band_plans[profile_key]) unless profile_key.nil?
|
|
183
233
|
|
|
184
234
|
fft_scan = opts[:fft_scan]
|
|
185
|
-
|
|
235
|
+
# Prefer (1) explicit --input-rate, (2) band-plan :input_rate from
|
|
236
|
+
# FrequencyAllocation (merged above), (3) historic 1 Msps default.
|
|
237
|
+
# GQRX device Input rate is separate from this *assumption* — use
|
|
238
|
+
# PWN::SDR::GQRX.apply_band_plan_input_rate to push the plan rate into
|
|
239
|
+
# ~/.config/gqrx/*.conf for the connected SDR.
|
|
240
|
+
# Local var + fast_scan_range kwarg remain sample_rate for library parity.
|
|
241
|
+
sample_rate = opts[:input_rate] || 1_000_000
|
|
186
242
|
sample_rate = sample_rate.to_i
|
|
243
|
+
puts "[*] input_rate (FFT/scan chunk / IQ span assumption): #{sample_rate} Hz" \
|
|
244
|
+
"#{" (band plan #{profile_key})" if profile_key}"
|
|
187
245
|
nfft = opts[:nfft] || 2048
|
|
188
246
|
nfft = nfft.to_i
|
|
189
247
|
avgv = opts[:avg] || 8
|
|
@@ -200,6 +258,11 @@ begin
|
|
|
200
258
|
|
|
201
259
|
if fft_scan
|
|
202
260
|
puts '[*] --fft-scan requested: using fast FFT panoramic mode (#fast_scan_range)'
|
|
261
|
+
refine_flag = opts.fetch(:refine, true)
|
|
262
|
+
puts "[*] band-plan / session params: mode=#{demodulator_mode.inspect} bw=#{bandwidth.inspect} " \
|
|
263
|
+
"squelch=#{squelch.inspect} precision=#{precision} decoder=#{decoder.inspect} " \
|
|
264
|
+
"rf_gain=#{rf_gain.inspect} if_gain=#{intermediate_gain.inspect} bb_gain=#{baseband_gain.inspect} " \
|
|
265
|
+
"refine=#{refine_flag}"
|
|
203
266
|
fast_resp = PWN::SDR::GQRX.fast_scan_range(
|
|
204
267
|
gqrx_sock: gqrx_sock,
|
|
205
268
|
ranges: ranges,
|
|
@@ -213,9 +276,15 @@ begin
|
|
|
213
276
|
min_snr_db: min_snr_db,
|
|
214
277
|
precision: precision,
|
|
215
278
|
min_bw_ratio: min_bw_ratio,
|
|
279
|
+
refine: opts.fetch(:refine, true),
|
|
280
|
+
refine_mode: opts[:refine_mode] || :lock,
|
|
216
281
|
demodulator_mode: demodulator_mode,
|
|
217
282
|
bandwidth: bandwidth,
|
|
218
283
|
squelch: squelch,
|
|
284
|
+
audio_gain_db: audio_gain_db,
|
|
285
|
+
rf_gain: rf_gain,
|
|
286
|
+
intermediate_gain: intermediate_gain,
|
|
287
|
+
baseband_gain: baseband_gain,
|
|
219
288
|
decoder: decoder,
|
|
220
289
|
location: location,
|
|
221
290
|
scan_log: scan_log
|
|
@@ -6,7 +6,7 @@ toolsets; the JSON-Schema for each tool is what the model actually sees.
|
|
|
6
6
|
|
|
7
7
|

|
|
8
8
|
|
|
9
|
-
## Toolsets → Tools (10 toolsets ·
|
|
9
|
+
## Toolsets → Tools (10 toolsets · 61 tools)
|
|
10
10
|
|
|
11
11
|
| Toolset | Tools | Backed by |
|
|
12
12
|
|---|---|---|
|
|
@@ -15,9 +15,9 @@ toolsets; the JSON-Schema for each tool is what the model actually sees.
|
|
|
15
15
|
| `memory` | `memory_remember` · `memory_recall` · `memory_forget` · `memory_clear` | `PWN::Memory` → `~/.pwn/memory.json` |
|
|
16
16
|
| `skills` | `skill_list` · `skill_view` · `skill_create` · `skill_add_reference` · `skill_delete` | `~/.pwn/skills/*.md` |
|
|
17
17
|
| `sessions` | `sessions_list` · `sessions_view` · `sessions_current` · `sessions_delete` · `sessions_stats` | `PWN::Sessions` → `~/.pwn/sessions/` |
|
|
18
|
-
| `learning` | `learning_note_outcome` · `learning_reflect` · `learning_distill_skill` · `learning_stats` · `learning_outcomes` · `learning_consolidate` · `learning_reset` · `
|
|
18
|
+
| `learning` | `learning_note_outcome` · `learning_reflect` · `learning_distill_skill` · `learning_stats` · `learning_outcomes` · `learning_consolidate` · `learning_reset` · `learning_auto_introspect_toggle` · **`mistakes_list`** · **`mistakes_record`** · **`mistakes_resolve`** · **`mistakes_reset`** | `PWN::AI::Agent::Learning` + `PWN::AI::Agent::Mistakes` → `~/.pwn/learning.jsonl` + `~/.pwn/mistakes.json` |
|
|
19
19
|
| `metrics` | `metrics_summary` · `metrics_reset` | `PWN::AI::Agent::Metrics` → `~/.pwn/metrics.json` |
|
|
20
|
-
| `extrospection` | `extro_snapshot` · `extro_drift` · `extro_observe` · `extro_observations` · `extro_intel` · **`extro_watch`** · **`extro_verify`** · `extro_correlate` · `extro_stats` · `extro_reset` · `extro_auto_toggle` | `PWN::AI::Agent::Extrospection` (+
|
|
20
|
+
| `extrospection` | `extro_snapshot` · `extro_drift` · `extro_observe` · `extro_observations` · `extro_intel` · **`extro_watch`** · **`extro_verify`** · **`extro_rf_tune`** · **`extro_osint`** · **`extro_serial`** · **`extro_telecomm`** · **`extro_packet`** · **`extro_vision`** · **`extro_voice`** · `extro_correlate` · `extro_stats` · `extro_reset` · `extro_auto_toggle` | `PWN::AI::Agent::Extrospection` (+ Serial/Packet/OCR/Voice/BareSIP/TransparentBrowser) → `~/.pwn/extrospection.json` |
|
|
21
21
|
| `cron` | `cron_list` · `cron_create` · `cron_run` · `cron_enable` · `cron_disable` · `cron_remove` | `PWN::Cron` → `~/.pwn/cron/jobs.yml` |
|
|
22
22
|
| `swarm` | `agent_list` · `agent_spawn` · `agent_ask` · `agent_debate` · `agent_broadcast` · `swarm_bus` · `swarm_list` | `PWN::AI::Agent::Swarm` → `~/.pwn/agents.yml` + `~/.pwn/swarm/` |
|
|
23
23
|
|
|
@@ -1,66 +1,320 @@
|
|
|
1
|
-
# Configuration — `~/.pwn/
|
|
1
|
+
# Configuration — `~/.pwn/pwn.yaml`
|
|
2
2
|
|
|
3
|
-
Everything configurable lives in one YAML file
|
|
4
|
-
startup and
|
|
3
|
+
Everything configurable in PWN lives in **one encrypted YAML file**, loaded by
|
|
4
|
+
`PWN::Config.refresh_env` at driver startup and exposed in-process as the
|
|
5
|
+
frozen constant **`PWN::Env`** (a redacted copy is available as
|
|
6
|
+
`PWN::EnvRedacted`).
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
The file is **AES-encrypted at rest** by `PWN::Plugins::Vault`. Its key/IV
|
|
9
|
+
live in a sibling **`~/.pwn/pwn.yaml.decryptor`** file (or in
|
|
10
|
+
`PWN_DECRYPTOR_KEY` / `PWN_DECRYPTOR_IV` env vars). Never edit `pwn.yaml`
|
|
11
|
+
by hand — use the **`pwn-vault`** REPL command, which decrypts → opens
|
|
12
|
+
`$EDITOR` → re-encrypts → reloads `PWN::Env`.
|
|
13
|
+
|
|
14
|
+
If `~/.pwn/pwn.yaml` does not exist on first run, `PWN::Config.default_env`
|
|
15
|
+
writes a fully-commented template with every key below (values set to
|
|
16
|
+
`'optional - …'` / `'required - …'` placeholder strings), encrypts it, and
|
|
17
|
+
generates the decryptor.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Full annotated example
|
|
7
22
|
|
|
8
23
|
```yaml
|
|
9
|
-
# ~/.pwn/
|
|
24
|
+
# ~/.pwn/pwn.yaml (shown DECRYPTED — file is AES-encrypted on disk)
|
|
25
|
+
|
|
10
26
|
ai:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
openai:
|
|
15
|
-
key: sk-…
|
|
27
|
+
active: grok # Which engine backs `pwn-ai`. One of: openai | anthropic | grok | gemini | ollama.
|
|
28
|
+
module_reflection: false # Master gate for LLM self-analysis (SAST triage, Burp enrichment, Learning.llm_reflect).
|
|
29
|
+
|
|
16
30
|
grok:
|
|
17
|
-
|
|
31
|
+
base_uri: https://api.x.ai/v1 # xAI API base URL. Override for a self-hosted proxy / private endpoint.
|
|
32
|
+
key: xai-… # xAI API key. If blank AND no oauth.* below, PWN prompts interactively at load.
|
|
33
|
+
model: grok-4.5 # Model id sent on every chat / tool-loop request.
|
|
34
|
+
system_role_content: 'You are an ethically hacking xAI Grok agent.' # Base system prompt (MEMORY/SKILLS/LEARNING/EXTROSPECTION blocks are appended to this).
|
|
35
|
+
temp: 1.0 # Sampling temperature passed to the chat endpoint.
|
|
36
|
+
max_prompt_length: 256000 # Soft input-context ceiling (chars) used for prompt truncation / chunking.
|
|
37
|
+
oauth: # RFC-8628 device-flow (SuperGrok subscription) — public client, no client_secret.
|
|
38
|
+
refresh_token: ~ # Durable OAuth refresh token; enables silent re-auth without an API key.
|
|
39
|
+
bearer_token: ~ # Short-lived OAuth access JWT; auto-refreshed each run when refresh_token is set.
|
|
40
|
+
client_id: b1a00492-073a-47ea-816f-4c329264a828 # xAI's PUBLIC OAuth client id for the "Grok CLI" application (not sensitive).
|
|
41
|
+
client_secret: ~ # Only for confidential-client OAuth flows; unused by the public Grok-CLI client.
|
|
42
|
+
scope: 'openid profile email offline_access grok-cli:access api:access' # OAuth scope string requested during device-flow enrollment.
|
|
43
|
+
token_uri: https://auth.x.ai/oauth2/token # OAuth token endpoint (override for enterprise IdP).
|
|
44
|
+
enroll: false # true → force RFC-8628 device-flow enrollment on load even when `key:` is set.
|
|
45
|
+
|
|
46
|
+
openai:
|
|
47
|
+
base_uri: https://api.openai.com/v1 # OpenAI API base URL. Override for Azure OpenAI / VPC gateway / local proxy.
|
|
48
|
+
key: sk-… # OpenAI API key (`sk-…`). Prompted interactively if blank.
|
|
49
|
+
model: gpt-4o # Model id sent on every chat / tool-loop request.
|
|
50
|
+
system_role_content: 'You are an ethically hacking OpenAI agent.' # Base system prompt for this engine.
|
|
51
|
+
temp: 1.0 # Sampling temperature.
|
|
52
|
+
max_prompt_length: 128000 # Soft input-context ceiling (chars) for truncation / chunking.
|
|
53
|
+
max_tokens: 16384 # Max OUTPUT tokens per response. Mapped to OpenAI wire param `max_completion_tokens`.
|
|
54
|
+
|
|
55
|
+
anthropic:
|
|
56
|
+
base_uri: https://api.anthropic.com/v1 # Anthropic API base URL. Override for Bedrock / private gateway.
|
|
57
|
+
key: sk-ant-… # Anthropic API key (`sk-ant-…`). Prompted interactively if blank.
|
|
58
|
+
model: claude-3-5-sonnet-20240620 # Model id sent on every chat / tool-loop request.
|
|
59
|
+
system_role_content: 'You are an ethically hacking Anthropic agent.' # Base system prompt for this engine.
|
|
60
|
+
temp: 1.0 # Sampling temperature.
|
|
61
|
+
max_tokens: 8192 # Max OUTPUT tokens per response. Raise if tool-call JSON truncates.
|
|
62
|
+
max_prompt_length: 200000 # Soft input-context ceiling (chars) for truncation / chunking.
|
|
63
|
+
|
|
64
|
+
gemini:
|
|
65
|
+
base_uri: https://generativelanguage.googleapis.com/v1beta # Google Generative Language API base URL.
|
|
66
|
+
key: AIza… # Google AI Studio API key (`AIza…`). Prompted interactively if blank.
|
|
67
|
+
model: gemini-2.5-pro # Model id sent on every chat / tool-loop request.
|
|
68
|
+
system_role_content: 'You are an ethically hacking Gemini agent.' # Base system prompt for this engine.
|
|
69
|
+
temp: 1.0 # Sampling temperature.
|
|
70
|
+
max_prompt_length: 1000000 # Soft input-context ceiling (chars) — Gemini supports very large contexts.
|
|
71
|
+
|
|
18
72
|
ollama:
|
|
19
|
-
|
|
20
|
-
|
|
73
|
+
base_uri: https://ollama.local # REQUIRED for ollama — Open WebUI / ollama-serve base URL (no vendor default).
|
|
74
|
+
key: eyJ… # Open WebUI JWT (Settings → Account → API Key). Prompted if blank.
|
|
75
|
+
model: llama3.1:70b # Local model tag as `ollama list` shows it.
|
|
76
|
+
system_role_content: 'You are an ethically hacking Ollama agent.' # Base system prompt for this engine.
|
|
77
|
+
temp: 1.0 # Sampling temperature.
|
|
78
|
+
max_prompt_length: 32000 # Soft input-context ceiling (chars) — tune per local model's real context window.
|
|
79
|
+
|
|
21
80
|
agent:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
81
|
+
native_tools: true # Use provider-native tool_calls / function-calling. false → legacy text-parsed tool protocol.
|
|
82
|
+
max_iters: 25 # Hard cap on tool-call rounds per user turn before a forced final answer.
|
|
83
|
+
max_depth: 3 # Recursion guard: how many levels deep agent_ask/agent_debate sub-agents may spawn sub-agents.
|
|
84
|
+
auto_introspect: true # Run Learning.auto_introspect (outcome logging + lesson mining) after every final answer.
|
|
85
|
+
auto_extrospect: false # Optional ambient baseline (host/repo/env ONLY — never launches burpsuite/zaproxy/msf/gqrx). Sense tools (intel/verify/watch/rf_tune/observe) stay on-demand.
|
|
86
|
+
toolsets: ~ # Allow-list of toolsets exposed to the agent. nil = all. Valid: cron, extrospection, learning, memory, metrics, pwn, sessions, skills, swarm, terminal.
|
|
87
|
+
extrospection:
|
|
88
|
+
web:
|
|
89
|
+
anchors: # URLs the headless browser fingerprints on extro_snapshot(sections:[:web]). Alias: web_anchors.
|
|
90
|
+
- https://nvd.nist.gov
|
|
91
|
+
- https://www.exploit-db.com
|
|
92
|
+
proxy: ~ # Upstream proxy for TransparentBrowser during probe_web/verify/watch (e.g. 'tor', http://127.0.0.1:8080).
|
|
93
|
+
max_anchors: 8 # Cap on how many anchors are rendered per snapshot (protects run time).
|
|
94
|
+
per_page_timeout: 15 # Seconds before a single page render is abandoned and recorded as unreachable.
|
|
95
|
+
screenshot: false # Persist a PNG per anchor to ~/.pwn/extrospection/web/ (disk-heavy; off by default).
|
|
96
|
+
allow_targets: false # true → also merge top-level `targets:` into anchors (opt-in — off so in-scope hosts aren't touched unprompted).
|
|
97
|
+
rf:
|
|
98
|
+
host: 127.0.0.1 # GQRX remote-control host for extro_rf_tune.
|
|
99
|
+
port: 7356 # GQRX remote-control port.
|
|
100
|
+
settle_secs: 8 # Seconds to sample RDS after tuning (max 30).
|
|
101
|
+
ttl: 300 # Observation TTL for :rf (songs change — keep short).
|
|
102
|
+
|
|
103
|
+
plugins:
|
|
104
|
+
asm:
|
|
105
|
+
arch: x86_64 # Target architecture for `pwn-asm` inline assembler/disassembler. Default: PWN::Plugins::DetectOS.arch.
|
|
106
|
+
endian: little # Endianness for `pwn-asm` (little | big). Default: PWN::Plugins::DetectOS.endian.
|
|
107
|
+
blockchain:
|
|
108
|
+
bitcoin:
|
|
109
|
+
rpc_host: localhost # bitcoind JSON-RPC host for PWN::Blockchain::BTC.
|
|
110
|
+
rpc_port: 8332 # bitcoind JSON-RPC port.
|
|
111
|
+
rpc_user: … # bitcoind RPC username (rpcauth / rpcuser in bitcoin.conf).
|
|
112
|
+
rpc_pass: … # bitcoind RPC password. Redacted in PWN::EnvRedacted.
|
|
113
|
+
hunter:
|
|
114
|
+
api_key: … # hunter.how API key — passed as api_key: to PWN::Plugins::Hunter.search.
|
|
115
|
+
jira_data_center:
|
|
116
|
+
base_uri: https://jira.company.com/rest/api/latest # Jira Data Center REST base URL.
|
|
117
|
+
token: … # Jira Personal Access Token for PWN::Plugins::JiraDataCenter. Redacted.
|
|
118
|
+
meshtastic:
|
|
119
|
+
admin_key: … # Public key authorised to send admin messages to mesh nodes via `pwn-mesh`.
|
|
120
|
+
serial:
|
|
121
|
+
port: /dev/ttyUSB0 # Serial device path for a locally-attached Meshtastic node.
|
|
122
|
+
baud: 115200 # Serial baud rate.
|
|
123
|
+
bits: 8 # Serial data bits.
|
|
124
|
+
stop: 1 # Serial stop bits.
|
|
125
|
+
parity: none # Serial parity (none | even | odd).
|
|
126
|
+
mqtt:
|
|
127
|
+
host: mqtt.meshtastic.org # MQTT broker hostname for Meshtastic-over-MQTT.
|
|
128
|
+
port: 1883 # MQTT broker port (8883 for TLS).
|
|
129
|
+
tls: false # Use TLS to the MQTT broker.
|
|
130
|
+
user: meshdev # MQTT username (public Meshtastic broker default shown).
|
|
131
|
+
pass: large4cats # MQTT password (public Meshtastic broker default shown). Redacted.
|
|
132
|
+
channel:
|
|
133
|
+
active: LongFast # Which named channel block below `pwn-mesh` uses for TX/RX.
|
|
134
|
+
LongFast: # Channel definition — name is arbitrary, referenced by `active:` above.
|
|
135
|
+
psk: 'AQ==' # Channel pre-shared key (base64). 'AQ==' = Meshtastic default public key. Redacted.
|
|
136
|
+
region: US/UT # LoRa region tag (regulatory band).
|
|
137
|
+
topic: 2/e/# # MQTT topic filter to subscribe/publish for this channel.
|
|
138
|
+
channel_num: 8 # Meshtastic channel index (slot number on the device).
|
|
139
|
+
from: '!deadbeef' # Sender node id used on outbound packets. Optional — defaults to !<mqtt client_id>.
|
|
140
|
+
PWN: # Example second (private) channel definition.
|
|
141
|
+
psk: … # Private channel pre-shared key (base64). Redacted.
|
|
142
|
+
region: US/UT # LoRa region tag for this channel.
|
|
143
|
+
topic: 2/e/PWN/# # MQTT topic filter for this channel.
|
|
144
|
+
channel_num: 99 # Meshtastic channel index for this channel.
|
|
145
|
+
shodan:
|
|
146
|
+
api_key: … # Shodan API key — passed as api_key: to PWN::Plugins::Shodan.*. Redacted.
|
|
147
|
+
|
|
148
|
+
memory:
|
|
149
|
+
enabled: true # Reserve — persistent-memory subsystem on/off (currently always active; future gate).
|
|
150
|
+
provider: file # Storage backend for PWN::Memory: file (~/.pwn/memory.json). `sqlite` reserved.
|
|
151
|
+
|
|
152
|
+
sessions:
|
|
153
|
+
enabled: true # Reserve — transcript recording on/off (currently always active; future gate).
|
|
154
|
+
provider: jsonl # Transcript format under ~/.pwn/sessions/ (one .jsonl per session).
|
|
155
|
+
|
|
156
|
+
cron:
|
|
157
|
+
enabled: true # Reserve — scheduled-job subsystem on/off (currently always active; future gate).
|
|
158
|
+
provider: yaml # Job store format for PWN::Cron (~/.pwn/cron/jobs.yml).
|
|
159
|
+
|
|
160
|
+
targets: # Optional — engagement-scope URLs/hosts. Merged into :web snapshot anchors
|
|
161
|
+
- https://target.example.com # ONLY when ai.agent.extrospection.web.allow_targets: true.
|
|
162
|
+
| `ai.agent.extrospection.rf.host` | String | `127.0.0.1` | `Extrospection.rf_tune` | GQRX remote-control host for the RF sense organ. |
|
|
163
|
+
| `ai.agent.extrospection.rf.port` | Integer | `7356` | `Extrospection.rf_tune` | GQRX remote-control port. |
|
|
164
|
+
| `ai.agent.extrospection.rf.settle_secs` | Integer | `8` | `Extrospection.rf_tune` | Seconds to sample RDS after tuning (capped at 30). |
|
|
165
|
+
| `ai.agent.extrospection.rf.ttl` | Integer | `300` | `Extrospection.rf_tune` | TTL (seconds) for `:rf` observations written by `extro_rf_tune` (ephemeral radio content). |
|
|
36
166
|
```
|
|
37
167
|
|
|
168
|
+
---
|
|
169
|
+
|
|
38
170
|
## Reading / writing at runtime
|
|
39
171
|
|
|
40
172
|
```ruby
|
|
41
|
-
PWN::Env[:ai][:
|
|
42
|
-
PWN::Env
|
|
43
|
-
PWN::
|
|
173
|
+
PWN::Env[:ai][:active] # => :grok
|
|
174
|
+
PWN::Env.dig(:ai, :agent, :max_iters) # => 25
|
|
175
|
+
PWN::EnvRedacted[:ai][:grok][:key] # => ">>> REDACTED >>> …"
|
|
176
|
+
|
|
177
|
+
# Edit + re-encrypt + reload without leaving the REPL:
|
|
178
|
+
pwn-vault
|
|
179
|
+
|
|
180
|
+
# Force a reload from disk (e.g. after pwn-vault in another shell):
|
|
181
|
+
PWN::Config.refresh_env
|
|
44
182
|
```
|
|
45
183
|
|
|
46
|
-
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Exhaustive key reference
|
|
187
|
+
|
|
188
|
+
### `ai` — AI engines & agent loop
|
|
189
|
+
|
|
190
|
+
| Key path | Type | Default | Consumed by | Purpose |
|
|
191
|
+
|---|---|---|---|---|
|
|
192
|
+
| `ai.active` | String | `grok` | `PWN::Config.refresh_env`, `PWN::AI::Agent::Loop`, `PWN::Plugins::REPL`, `PWN::Cron` | Which AI engine backs `pwn-ai`. One of `openai` · `anthropic` · `grok` · `gemini` · `ollama`. |
|
|
193
|
+
| `ai.module_reflection` | Boolean | `false` | `PWN::AI::Agent::Reflect`, `PWN::SAST::*`, `PWN::Plugins::BurpSuite` | Master gate for LLM-driven self-analysis (SAST triage, Burp finding enrichment, `Learning.llm_reflect`). |
|
|
194
|
+
| `ai.<engine>.base_uri` | String | provider default | `PWN::AI::<Engine>.rest_call` | Override the API base URL (self-hosted proxy, private endpoint, Azure/VPC gateway). **Required** for `ollama`. |
|
|
195
|
+
| `ai.<engine>.key` | String | — | `PWN::AI::<Engine>` | API key / bearer token. If blank AND no OAuth is configured, PWN prompts interactively at load. |
|
|
196
|
+
| `ai.<engine>.model` | String | provider default | `PWN::AI::<Engine>.chat` / `.chat_tool_loop` | Model id sent on every request (e.g. `grok-4.5`, `gpt-4o`, `claude-3-5-sonnet-20240620`, `gemini-2.5-pro`, `llama3.1:70b`). |
|
|
197
|
+
| `ai.<engine>.system_role_content` | String | ethical-hacker persona | `PWN::AI::Agent::PromptBuilder`, `PWN::Plugins::REPL` | Base system prompt prepended to MEMORY / SKILLS / LEARNING / EXTROSPECTION blocks. |
|
|
198
|
+
| `ai.<engine>.temp` | Float | `1.0` | `PWN::AI::<Engine>.chat` | Sampling temperature. |
|
|
199
|
+
| `ai.<engine>.max_prompt_length` | Integer | per-engine | `PWN::AI::<Engine>`, `PWN::Plugins::REPL` | Soft input-context ceiling used for prompt truncation / chunking. |
|
|
200
|
+
| `ai.anthropic.max_tokens` | Integer | `8192` | `PWN::AI::Anthropic.chat_tool_loop` | Max **output** tokens per response. Raise if tool-call JSON truncates. |
|
|
201
|
+
| `ai.openai.max_tokens` | Integer | `16384` | `PWN::AI::OpenAI.chat` | Max **output** tokens per response. Mapped to OpenAI's wire param `max_completion_tokens` (legacy env key `max_completion_tokens` still accepted). |
|
|
202
|
+
| `ai.grok.oauth.refresh_token` | String | — | `PWN::AI::Grok.resolve_auth` | Durable OAuth refresh token (from `PWN::AI::Grok.obtain_oauth_bearer_token` device flow). Enables silent re-auth without an API key. |
|
|
203
|
+
| `ai.grok.oauth.bearer_token` | String | — | `PWN::AI::Grok.resolve_auth` | Short-lived OAuth access JWT. Auto-refreshed each run when `refresh_token` is present; live-cached back into this hash. |
|
|
204
|
+
| `ai.grok.oauth.client_id` | String | Grok-CLI public id | `PWN::AI::Grok` | Override the public OAuth client id used for device-flow / refresh. |
|
|
205
|
+
| `ai.grok.oauth.client_secret` | String | — | `PWN::Config.refresh_env`, `PWN::AI::Grok` | Only for confidential-client OAuth flows. Unused by the default public Grok-CLI client. |
|
|
206
|
+
| `ai.grok.oauth.scope` | String | see example | `PWN::AI::Grok` | OAuth scope string requested during device-flow enrollment. |
|
|
207
|
+
| `ai.grok.oauth.token_uri` | String | `https://auth.x.ai/oauth2/token` | `PWN::AI::Grok` | OAuth token endpoint (override for enterprise IdP). |
|
|
208
|
+
| `ai.grok.oauth.enroll` | Boolean | `false` | `PWN::AI::Grok` | `true` → always run RFC-8628 device-flow enrollment on load, even when `ai.grok.key` is set. |
|
|
209
|
+
|
|
210
|
+
### `ai.agent` — pwn-ai autonomous loop
|
|
211
|
+
|
|
212
|
+
| Key path | Type | Default | Consumed by | Purpose |
|
|
213
|
+
|---|---|---|---|---|
|
|
214
|
+
| `ai.agent.native_tools` | Boolean | `true` | `PWN::Plugins::REPL` (`pwn-ai` cmd) | Use provider-native `tool_calls` / function-calling. `false` falls back to the legacy text-parsed tool protocol. |
|
|
215
|
+
| `ai.agent.max_iters` | Integer | `25` | `PWN::AI::Agent::Loop.run`, `PWN::AI::Agent::Swarm` | Hard cap on tool-call rounds per user turn before a forced final answer. |
|
|
216
|
+
| `ai.agent.max_depth` | Integer | `3` | `PWN::AI::Agent::Swarm` | Recursion guard for `agent_ask` / `agent_debate` sub-agents spawning sub-agents. |
|
|
217
|
+
| `ai.agent.auto_introspect` | Boolean | `true` | `PWN::AI::Agent::Learning.auto_introspect` | Run outcome logging + lesson mining after every final answer. Toggle live via `learning_auto_introspect_toggle`. |
|
|
218
|
+
| `ai.agent.auto_extrospect` | Boolean | `false` | `PWN::AI::Agent::Extrospection.auto_extrospect` | Optional ambient baseline after every final answer (`AUTO_SECTIONS` = host/repo/env only; never spawns GUI/JVM tools). Prefer on-demand sense tools (`intel`/`verify`/`watch`/`rf_tune`/`observe`). Toggle live via `extro_auto_toggle`. |
|
|
219
|
+
| `ai.agent.toolsets` | Array\<String\> \| `nil` | `nil` (all) | `bin/pwn`, `PWN::Plugins::REPL`, `PWN::AI::Agent::Registry` | Allow-list of toolsets exposed to the agent. Valid: `cron`, `extrospection`, `learning`, `memory`, `metrics`, `pwn`, `sessions`, `skills`, `swarm`, `terminal`. |
|
|
220
|
+
| `ai.agent.extrospection.web.anchors` | Array\<String\> | `DEFAULT_WEB_ANCHORS` | `PWN::AI::Agent::Extrospection.probe_web` | URLs the headless browser fingerprints on `extro_snapshot(sections:[:web])`. Alias: `web_anchors`. |
|
|
221
|
+
| `ai.agent.extrospection.web.proxy` | String | — | `Extrospection.probe_web` / `.verify` / `.watch` | Upstream proxy for `PWN::Plugins::TransparentBrowser` (e.g. `tor`, `http://127.0.0.1:8080`). |
|
|
222
|
+
| `ai.agent.extrospection.web.max_anchors` | Integer | `8` | `Extrospection.probe_web` | Cap on anchors rendered per snapshot. |
|
|
223
|
+
| `ai.agent.extrospection.web.per_page_timeout` | Integer | `15` | `Extrospection` (headless browser) | Seconds before a page render is abandoned. |
|
|
224
|
+
| `ai.agent.extrospection.web.screenshot` | Boolean | `false` | `Extrospection.probe_web` / `.watch` | Persist a PNG per anchor to `~/.pwn/extrospection/web/`. |
|
|
225
|
+
| `ai.agent.extrospection.web.allow_targets` | Boolean | `false` | `Extrospection.web_anchors` | Merge top-level `targets:` into the anchor list (opt-in — off by default to avoid touching in-scope hosts unprompted). |
|
|
226
|
+
|
|
227
|
+
### `plugins` — module credentials & wiring
|
|
228
|
+
|
|
229
|
+
| Key path | Type | Default | Consumed by | Purpose |
|
|
230
|
+
|---|---|---|---|---|
|
|
231
|
+
| `plugins.asm.arch` | String | `DetectOS.arch` | `PWN::Plugins::REPL` (`pwn-asm`) | Target architecture for the inline assembler / disassembler prompt (`x86_64`, `arm64`, …). |
|
|
232
|
+
| `plugins.asm.endian` | String | `DetectOS.endian` | `PWN::Plugins::REPL` (`pwn-asm`) | Endianness for the inline assembler (`little` / `big`). |
|
|
233
|
+
| `plugins.blockchain.bitcoin.rpc_host` | String | `localhost` | `PWN::Blockchain::BTC` | bitcoind JSON-RPC host. |
|
|
234
|
+
| `plugins.blockchain.bitcoin.rpc_port` | Integer | `8332` | `PWN::Blockchain::BTC` | bitcoind JSON-RPC port. |
|
|
235
|
+
| `plugins.blockchain.bitcoin.rpc_user` | String | — | `PWN::Blockchain::BTC` | bitcoind RPC username. |
|
|
236
|
+
| `plugins.blockchain.bitcoin.rpc_pass` | String | — | `PWN::Blockchain::BTC` | bitcoind RPC password. |
|
|
237
|
+
| `plugins.hunter.api_key` | String | — | `PWN::Plugins::Hunter` | hunter.how API key (passed as `api_key:` to `Hunter.search`). |
|
|
238
|
+
| `plugins.jira_data_center.base_uri` | String | — | `PWN::Plugins::JiraDataCenter` | Jira DC REST base (e.g. `https://jira.company.com/rest/api/latest`). |
|
|
239
|
+
| `plugins.jira_data_center.token` | String | — | `PWN::Plugins::JiraDataCenter` | Jira Personal Access Token. |
|
|
240
|
+
| `plugins.meshtastic.admin_key` | String | — | `PWN::Plugins::REPL` (`pwn-mesh`) | Public key authorised to send admin messages to mesh nodes. |
|
|
241
|
+
| `plugins.meshtastic.serial.port` | String | `/dev/ttyUSB0` | `pwn-mesh` (serial) | Serial device path for a locally-attached Meshtastic node. |
|
|
242
|
+
| `plugins.meshtastic.serial.baud` | Integer | `115200` | `pwn-mesh` (serial) | Serial baud rate. |
|
|
243
|
+
| `plugins.meshtastic.serial.bits` | Integer | `8` | `pwn-mesh` (serial) | Serial data bits. |
|
|
244
|
+
| `plugins.meshtastic.serial.stop` | Integer | `1` | `pwn-mesh` (serial) | Serial stop bits. |
|
|
245
|
+
| `plugins.meshtastic.serial.parity` | Symbol | `:none` | `pwn-mesh` (serial) | Serial parity. |
|
|
246
|
+
| `plugins.meshtastic.mqtt.host` | String | `mqtt.meshtastic.org` | `pwn-mesh` → `Meshtastic::MQTT.connect` | MQTT broker hostname. |
|
|
247
|
+
| `plugins.meshtastic.mqtt.port` | Integer | `1883` | `pwn-mesh` | MQTT broker port. |
|
|
248
|
+
| `plugins.meshtastic.mqtt.tls` | Boolean | `false` | `pwn-mesh` | Use TLS to the MQTT broker. |
|
|
249
|
+
| `plugins.meshtastic.mqtt.user` | String | `meshdev` | `pwn-mesh` | MQTT username. |
|
|
250
|
+
| `plugins.meshtastic.mqtt.pass` | String | `large4cats` | `pwn-mesh` | MQTT password. |
|
|
251
|
+
| `plugins.meshtastic.channel.active` | String | `LongFast` | `pwn-mesh` | Which named channel block below is used for TX/RX. |
|
|
252
|
+
| `plugins.meshtastic.channel.<NAME>.psk` | String (b64) | `AQ==` | `pwn-mesh` | Channel pre-shared key. |
|
|
253
|
+
| `plugins.meshtastic.channel.<NAME>.region` | String | — | `pwn-mesh` | LoRa region tag (e.g. `US/UT`). |
|
|
254
|
+
| `plugins.meshtastic.channel.<NAME>.topic` | String | — | `pwn-mesh` | MQTT topic filter to subscribe/publish (e.g. `2/e/#`). |
|
|
255
|
+
| `plugins.meshtastic.channel.<NAME>.channel_num` | Integer | — | `pwn-mesh` | Meshtastic channel index. |
|
|
256
|
+
| `plugins.meshtastic.channel.<NAME>.from` | String | `!<mqtt client_id>` | `pwn-mesh` | Sender node id used on outbound packets. |
|
|
257
|
+
| `plugins.shodan.api_key` | String | — | `PWN::Plugins::Shodan` | Shodan API key (passed as `api_key:` to `Shodan.*`). |
|
|
258
|
+
|
|
259
|
+
### `memory` / `sessions` / `cron`
|
|
260
|
+
|
|
261
|
+
| Key path | Type | Default | Consumed by | Purpose |
|
|
262
|
+
|---|---|---|---|---|
|
|
263
|
+
| `memory.enabled` | Boolean | `true` | `PWN::Memory` | Reserve — persistent memory on/off (currently always active; future gate). |
|
|
264
|
+
| `memory.provider` | String | `file` | `PWN::Memory` | Storage backend: `file` (`~/.pwn/memory.json`). `sqlite` reserved. |
|
|
265
|
+
| `sessions.enabled` | Boolean | `true` | `PWN::Sessions` | Reserve — transcript recording on/off (currently always active; future gate). |
|
|
266
|
+
| `sessions.provider` | String | `jsonl` | `PWN::Sessions` | Transcript format under `~/.pwn/sessions/`. |
|
|
267
|
+
| `cron.enabled` | Boolean | `true` | `PWN::Cron` | Reserve — scheduled-job subsystem on/off (currently always active; future gate). |
|
|
268
|
+
| `cron.provider` | String | `yaml` | `PWN::Cron` | Job store format (`~/.pwn/cron/jobs.yml`). |
|
|
269
|
+
|
|
270
|
+
### Top-level / miscellaneous
|
|
271
|
+
|
|
272
|
+
| Key path | Type | Default | Consumed by | Purpose |
|
|
273
|
+
|---|---|---|---|---|
|
|
274
|
+
| `targets` | Array\<String\> | — | `PWN::AI::Agent::Extrospection.web_anchors` | Engagement-scope URLs/hosts. Merged into `:web` snapshot anchors when `ai.agent.extrospection.web.allow_targets: true`. |
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Runtime-only keys on `PWN::Env` (NOT stored in `pwn.yaml`)
|
|
279
|
+
|
|
280
|
+
These are injected by `PWN::Config.refresh_env` / `PWN::AI::Agent::Loop` after
|
|
281
|
+
the YAML is decrypted. They will appear on `PWN::Env` in-process but are
|
|
282
|
+
**overwritten on every load**, so putting them in `pwn.yaml` has no effect.
|
|
283
|
+
|
|
284
|
+
| Key path | Set by | Purpose |
|
|
285
|
+
|---|---|---|
|
|
286
|
+
| `driver_opts.pwn_env_path` | `PWN::Config.refresh_env` / `PWN::Driver::Parser` | Resolved path to the active `pwn.yaml` (from `--pwn_env` or default). |
|
|
287
|
+
| `driver_opts.pwn_dec_path` | `PWN::Config.refresh_env` / `PWN::Driver::Parser` | Resolved path to the decryptor YAML (from `--pwn_dec` or default). |
|
|
288
|
+
| `pwn_skills_path` | `PWN::Config.refresh_env` | Absolute path to `~/.pwn/skills/`. |
|
|
289
|
+
| `pwn_memory_path` | `PWN::Config.refresh_env` | Absolute path to `~/.pwn/memory.json`. |
|
|
290
|
+
| `pwn_sessions_path` | `PWN::Config.refresh_env` | Absolute path to `~/.pwn/sessions/`. |
|
|
291
|
+
| `pwn_cron_path` | `PWN::Config.refresh_env` | Absolute path to `~/.pwn/cron/`. |
|
|
292
|
+
| `ai.<engine>.response_history` | `PWN::Config.refresh_env` | Rolling chat history for the active engine (reset on every reload). |
|
|
293
|
+
| `ai.session_id` | `PWN::AI::Agent::Loop.run` | Active `PWN::Sessions` id for the current turn (read by `sessions_current`, `mistakes_record`). |
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Redaction
|
|
298
|
+
|
|
299
|
+
`PWN::Config.redact_sensitive_artifacts` (and therefore `PWN::EnvRedacted`)
|
|
300
|
+
masks any key named: `admin_key`, `api_key`, `auth_client_secret`,
|
|
301
|
+
`bearer_token`, `client_secret`, `consumer_key`, `key`, `pass`, `password`,
|
|
302
|
+
`psk`, `refresh_token`, `secret_key`, `token`. Use those key names for any
|
|
303
|
+
custom secrets you add so they never leak into logs, transcripts, or the
|
|
304
|
+
agent system prompt.
|
|
305
|
+
|
|
306
|
+
---
|
|
47
307
|
|
|
48
|
-
|
|
49
|
-
|---|---|
|
|
50
|
-
| `ai.engine` | `PWN::AI::Agent::Loop` — which client to instantiate |
|
|
51
|
-
| `ai.<engine>.key` / `.oauth` | `PWN::AI::OpenAI` / `Anthropic` / `Grok` / `Gemini` / `Ollama` |
|
|
52
|
-
| `ai.agent.max_iters` | hard stop on tool-call rounds |
|
|
53
|
-
| `ai.agent.max_depth` | `Swarm` recursion guard |
|
|
54
|
-
| `ai.agent.auto_reflect` | toggle `Learning.auto_reflect` |
|
|
55
|
-
| `ai.agent.auto_extrospect` | toggle `Extrospection.auto_extrospect` |
|
|
56
|
-
| `burp.*` | `PWN::Plugins::BurpSuite` |
|
|
57
|
-
| `metasploit.*` | `PWN::Plugins::Metasploit` |
|
|
58
|
-
| `zap.*` | `PWN::Plugins::Zaproxy` |
|
|
59
|
-
| `shodan.key` / `hunter.key` / … | respective OSINT plugins |
|
|
60
|
-
| `aws.*` | `PWN::AWS::*` (falls back to standard AWS SDK env/instance-profile) |
|
|
308
|
+
## Related files under `~/.pwn/`
|
|
61
309
|
|
|
62
|
-
|
|
310
|
+
`pwn.yaml` is the only file you edit; everything else is machine-written
|
|
311
|
+
state. See **[Persistence](Persistence.md)** for the full map
|
|
312
|
+
(`memory.json`, `learning.jsonl`, `mistakes.json`, `metrics.json`,
|
|
313
|
+
`extrospection.json`, `sessions/`, `skills/`, `cron/`, `agents.yml`,
|
|
314
|
+
`swarm/`).
|
|
63
315
|
|
|
64
|
-
|
|
316
|
+
Multi-agent personas are **not** configured here — they live in
|
|
317
|
+
`~/.pwn/agents.yml` and are managed with `agent_spawn` / `agent_list`
|
|
318
|
+
(see **[Swarm](Swarm.md)**).
|
|
65
319
|
|
|
66
|
-
[← Home](Home.md)
|
|
320
|
+
[← Home](Home.md) · [Persistence](Persistence.md) · [pwn-ai Agent](pwn-ai-Agent.md) · [Extrospection](Extrospection.md)
|
data/documentation/Cron.md
CHANGED
|
@@ -37,9 +37,11 @@ cron_create(
|
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
At 02:00 the system cron fires `PWN::Cron.run`, which spins up a headless
|
|
40
|
-
`pwn-ai` turn.
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
`pwn-ai` turn. With `auto_introspect` on (and optional `auto_extrospect` for
|
|
41
|
+
the cheap `AUTO_SECTIONS` baseline), the run updates Learning/Metrics — and,
|
|
42
|
+
if enabled, host/repo/env posture — so tomorrow's interactive session already
|
|
43
|
+
knows what changed overnight. Sense tools (`intel`/`verify`/`watch`) stay
|
|
44
|
+
on-demand; cron is not expected to launch Burp/ZAP/msf/GQRX.
|
|
43
45
|
|
|
44
46
|
```ruby
|
|
45
47
|
cron_create(
|
data/documentation/Diagrams.md
CHANGED
|
@@ -59,7 +59,7 @@ groups) so lines never criss-cross.
|
|
|
59
59
|
[source](diagrams/dot/ai-integration-tool-calling.dot) · doc: [AI Integration](AI-Integration.md)
|
|
60
60
|

|
|
61
61
|
|
|
62
|
-
### Agent Tool Registry (10 toolsets ·
|
|
62
|
+
### Agent Tool Registry (10 toolsets · 61 tools)
|
|
63
63
|
[source](diagrams/dot/agent-tool-registry.dot) · doc: [Agent Tool Registry](Agent-Tool-Registry.md)
|
|
64
64
|

|
|
65
65
|
|