pwn 0.5.636 → 0.5.638
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/.github/workflows/install-matrix.yml +13 -1
- data/bin/pwn_ai_red_team +150 -0
- data/bin/pwn_setup +16 -2
- data/build_gem.sh +3 -0
- data/documentation/Agent-Tool-Registry.md +12 -5
- data/documentation/CLI-Drivers.md +37 -31
- data/documentation/Configuration.md +16 -3
- data/documentation/Contributing.md +9 -2
- data/documentation/Cron.md +21 -1
- data/documentation/Diagrams.md +6 -2
- data/documentation/Drivers.md +1 -1
- data/documentation/General-PWN-Usage.md +7 -1
- data/documentation/Home.md +1 -1
- data/documentation/How-PWN-Works.md +31 -17
- data/documentation/Installation.md +85 -53
- data/documentation/Persistence.md +34 -8
- data/documentation/Plugins.md +5 -5
- data/documentation/Reinforcement-Learning.md +7 -0
- data/documentation/Sessions.md +6 -2
- data/documentation/Skills-Memory-Learning.md +26 -10
- data/documentation/Troubleshooting.md +23 -0
- data/documentation/What-is-PWN.md +12 -6
- data/documentation/Why-PWN.md +3 -2
- data/documentation/diagrams/agent-tool-registry.svg +105 -102
- data/documentation/diagrams/cron-scheduling.svg +137 -78
- data/documentation/diagrams/dot/agent-tool-registry.dot +4 -4
- data/documentation/diagrams/dot/cron-scheduling.dot +25 -9
- data/documentation/diagrams/dot/history-to-drivers.dot +1 -1
- data/documentation/diagrams/dot/memory-skills-detailed.dot +10 -4
- data/documentation/diagrams/dot/overall-pwn-architecture.dot +2 -2
- data/documentation/diagrams/dot/persistence-filesystem.dot +18 -11
- data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +19 -4
- data/documentation/diagrams/dot/reinforcement-learning.dot +102 -0
- data/documentation/diagrams/history-to-drivers.svg +6 -6
- data/documentation/diagrams/memory-skills-detailed.svg +233 -198
- data/documentation/diagrams/overall-pwn-architecture.svg +168 -168
- data/documentation/diagrams/persistence-filesystem.svg +212 -136
- data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +386 -283
- data/documentation/diagrams/reinforcement-learning.svg +392 -0
- data/documentation/pwn-REPL.md +33 -4
- data/documentation/pwn-ai-Agent.md +42 -30
- data/lib/pwn/ai/agent/reflect.rb +16 -5
- data/lib/pwn/ai/red_team/excessive_agency.rb +89 -0
- data/lib/pwn/ai/red_team/insecure_output_handling.rb +90 -0
- data/lib/pwn/ai/red_team/jailbreak.rb +90 -0
- data/lib/pwn/ai/red_team/model_denial_of_service.rb +89 -0
- data/lib/pwn/ai/red_team/overreliance.rb +89 -0
- data/lib/pwn/ai/red_team/payload_splitting.rb +89 -0
- data/lib/pwn/ai/red_team/prompt_injection.rb +89 -0
- data/lib/pwn/ai/red_team/sensitive_information_disclosure.rb +89 -0
- data/lib/pwn/ai/red_team/system_prompt_extraction.rb +89 -0
- data/lib/pwn/ai/red_team/test_case_engine.rb +436 -0
- data/lib/pwn/ai/red_team/token_smuggling.rb +89 -0
- data/lib/pwn/ai/red_team.rb +45 -0
- data/lib/pwn/ai.rb +1 -0
- data/lib/pwn/config.rb +2 -0
- data/lib/pwn/plugins/repl.rb +78 -15
- data/lib/pwn/reports/ai_red_team.rb +428 -0
- data/lib/pwn/reports.rb +1 -0
- data/lib/pwn/setup.rb +193 -7
- data/lib/pwn/version.rb +1 -1
- data/packer/provisioners/pwn.sh +2 -2
- data/pwn.gemspec +20 -0
- data/spec/lib/pwn/ai/red_team/excessive_agency_spec.rb +25 -0
- data/spec/lib/pwn/ai/red_team/insecure_output_handling_spec.rb +25 -0
- data/spec/lib/pwn/ai/red_team/jailbreak_spec.rb +25 -0
- data/spec/lib/pwn/ai/red_team/model_denial_of_service_spec.rb +25 -0
- data/spec/lib/pwn/ai/red_team/overreliance_spec.rb +25 -0
- data/spec/lib/pwn/ai/red_team/payload_splitting_spec.rb +25 -0
- data/spec/lib/pwn/ai/red_team/prompt_injection_spec.rb +25 -0
- data/spec/lib/pwn/ai/red_team/sensitive_information_disclosure_spec.rb +25 -0
- data/spec/lib/pwn/ai/red_team/system_prompt_extraction_spec.rb +25 -0
- data/spec/lib/pwn/ai/red_team/test_case_engine_spec.rb +20 -0
- data/spec/lib/pwn/ai/red_team/token_smuggling_spec.rb +25 -0
- data/spec/lib/pwn/ai/red_team_spec.rb +15 -0
- data/spec/lib/pwn/reports/ai_red_team_spec.rb +15 -0
- data/third_party/pwn_rdoc.jsonl +57 -1
- data/third_party/terminator/pwn_shift_enter.py +137 -0
- metadata +34 -45
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c889fade648cffc3bfe73e8a168b4e5353f3eb1fe652fa1b1839f9733c630bc8
|
|
4
|
+
data.tar.gz: c02957f5bc40cb4d8a3dc18d5c078540f5395118ade25df55379c6399c264d03
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 97e57a81e839aaafcd83921d258ab2a95d9b7671120ef9c72a0df742c2ddfd4a84bb2d92a1b5fc426979910aea82e1b192226e1dfaddac218a057791ca892012
|
|
7
|
+
data.tar.gz: 1d89d4153ec4cd0b1604f2a8e4a735d00606d45111f9ad1db92b302968a510fbedfd6a588022ab1120fac4ed9413e7aac3e0694b6cd4200e65cfcf162ed2375e
|
|
@@ -84,7 +84,12 @@ jobs:
|
|
|
84
84
|
ruby: dnf install -y ruby ruby-devel redhat-rpm-config gcc gcc-c++ make git
|
|
85
85
|
- image: archlinux:latest
|
|
86
86
|
pm: pacman
|
|
87
|
-
ruby:
|
|
87
|
+
# ruby-stdlib/ruby-bundled-gems: Arch splits erb/etc. out of the
|
|
88
|
+
# base `ruby` package; sed: Arch's /etc/gemrc defaults to
|
|
89
|
+
# `--user-install` which puts pwn/rspec binstubs off PATH.
|
|
90
|
+
ruby: >-
|
|
91
|
+
pacman -Sy --noconfirm ruby ruby-stdlib ruby-bundled-gems rubygems base-devel git &&
|
|
92
|
+
{ sed -i '/--user-install/d' /etc/gemrc || true; }
|
|
88
93
|
env:
|
|
89
94
|
DEBIAN_FRONTEND: noninteractive
|
|
90
95
|
PWN_FRESH_INSTALL: '1'
|
|
@@ -117,6 +122,13 @@ jobs:
|
|
|
117
122
|
gem install --no-document rspec
|
|
118
123
|
ruby -r pwn -e 'puts "pwn #{PWN::VERSION} ruby #{RUBY_VERSION} #{RUBY_PLATFORM}"'
|
|
119
124
|
|
|
125
|
+
- name: expose gem binstubs on PATH
|
|
126
|
+
# Distros disagree on where `gem install` writes executables (system
|
|
127
|
+
# bindir on apt/dnf, ~/.local/share/gem/.../bin on Arch's default
|
|
128
|
+
# --user-install). Put both on PATH so `pwn` / `rspec` resolve on
|
|
129
|
+
# every leg without hard-coding per-distro paths.
|
|
130
|
+
run: ruby -e 'puts Gem.bindir; puts File.join(Gem.user_dir, "bin")' >> "$GITHUB_PATH"
|
|
131
|
+
|
|
120
132
|
- name: dry-run — every package name resolves for this distro
|
|
121
133
|
run: pwn setup --profile full --dry-run --yes
|
|
122
134
|
|
data/bin/pwn_ai_red_team
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'htmlentities'
|
|
5
|
+
require 'pwn'
|
|
6
|
+
|
|
7
|
+
opts = PWN::Env[:driver_opts]
|
|
8
|
+
PWN::Driver::Parser.new do |options|
|
|
9
|
+
options.on('-eENGINE', '--target-engine=ENGINE', '<Required - AI Engine Under Test (openai|anthropic|grok|gemini|ollama)>') do |e|
|
|
10
|
+
opts[:target_engine] = e
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
options.on('-mMODEL', '--target-model=MODEL', '<Optional - Specific Model on the Target Engine (Defaults to engine default)>') do |m|
|
|
14
|
+
opts[:target_model] = m
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
options.on('-rROLE', '--system-role=ROLE', '<Optional - System Prompt Applied to the Target for Every Payload>') do |r|
|
|
18
|
+
opts[:system_role_content] = r
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
options.on('-dDIR', '--dir-path=DIR', '<Optional - Report Output Directory (Defaults to ".")>') do |d|
|
|
22
|
+
opts[:dir_path] = d
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
options.on('-tTHREADS', '--max-threads=THREADS', '<Optional # Test Cases to Run Simultaneously (Default 5)>') do |t|
|
|
26
|
+
opts[:max_threads] = t
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
options.on('-TCASE', '--test-cases=CASE', '<Optional Comma-Delimited Test Cases to Invoke (-l for List)>') do |c|
|
|
30
|
+
opts[:chosen_test_cases] = c
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
options.on('-l', '--[no-]list-test-cases', '<Optional List Available Test Cases to Invoke and Exit>') do |l|
|
|
34
|
+
opts[:list_test_cases] = l
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
options.on('-nREPORTNAME', '--report-name=REPORTNAME', '<Optional Report Name (Defaults to, "<engine>-<model>-<timestamp>")>') do |n|
|
|
38
|
+
opts[:report_name] = n
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
options.on('-s', '--[no-]start-reporting-server', '<Optional - Start Simple HTTP Server for Reporting>') do |s|
|
|
42
|
+
opts[:start_reporting_server] = s
|
|
43
|
+
end
|
|
44
|
+
end.parse!
|
|
45
|
+
|
|
46
|
+
begin
|
|
47
|
+
timestamp = Time.now.strftime('%Y-%m-%d_%H:%M:%S%z')
|
|
48
|
+
|
|
49
|
+
pwn_env_path = opts[:pwn_env_path]
|
|
50
|
+
pwn_dec_path = opts[:pwn_dec_path]
|
|
51
|
+
|
|
52
|
+
pwn_provider = 'ruby-gem'
|
|
53
|
+
pwn_provider = ENV.fetch('PWN_PROVIDER') if ENV.keys.any? { |s| s == 'PWN_PROVIDER' }
|
|
54
|
+
|
|
55
|
+
green = "\e[32m"
|
|
56
|
+
end_of_color = "\e[0m"
|
|
57
|
+
|
|
58
|
+
dir_path = opts[:dir_path] ||= '.'
|
|
59
|
+
|
|
60
|
+
target_engine = opts[:target_engine]
|
|
61
|
+
target_model = opts[:target_model]
|
|
62
|
+
system_role_content = opts[:system_role_content]
|
|
63
|
+
|
|
64
|
+
max_threads = opts[:max_threads]
|
|
65
|
+
max_threads ||= 5
|
|
66
|
+
|
|
67
|
+
chosen_test_cases = opts[:chosen_test_cases]
|
|
68
|
+
list_test_cases = opts[:list_test_cases]
|
|
69
|
+
|
|
70
|
+
report_name = opts[:report_name]
|
|
71
|
+
report_name ||= "#{target_engine}-#{target_model || 'default'}-#{timestamp}"
|
|
72
|
+
|
|
73
|
+
start_reporting_server = opts[:start_reporting_server]
|
|
74
|
+
|
|
75
|
+
# Define Test Cases to Run & Start Thread Pool
|
|
76
|
+
if chosen_test_cases && !list_test_cases
|
|
77
|
+
test_cases = chosen_test_cases.to_s.scrub.chomp.strip.delete("\s").split(',').map(&:to_sym)
|
|
78
|
+
else
|
|
79
|
+
test_cases = %i[
|
|
80
|
+
ExcessiveAgency
|
|
81
|
+
InsecureOutputHandling
|
|
82
|
+
Jailbreak
|
|
83
|
+
ModelDenialOfService
|
|
84
|
+
Overreliance
|
|
85
|
+
PayloadSplitting
|
|
86
|
+
PromptInjection
|
|
87
|
+
SensitiveInformationDisclosure
|
|
88
|
+
SystemPromptExtraction
|
|
89
|
+
TokenSmuggling
|
|
90
|
+
].sort.uniq
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
if list_test_cases
|
|
94
|
+
test_cases.each { |tc| puts "#{green}#{tc}#{end_of_color}" }
|
|
95
|
+
exit
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
raise "ERROR: Invalid Directory #{dir_path}" unless File.directory?(dir_path)
|
|
99
|
+
|
|
100
|
+
results_hash = {
|
|
101
|
+
report_name: HTMLEntities.new.encode(
|
|
102
|
+
report_name.to_s.scrub.strip.chomp
|
|
103
|
+
),
|
|
104
|
+
data: []
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
mutex = Mutex.new
|
|
108
|
+
|
|
109
|
+
PWN::Plugins::ThreadPool.fill(
|
|
110
|
+
enumerable_array: test_cases,
|
|
111
|
+
max_threads: max_threads
|
|
112
|
+
) do |test_case|
|
|
113
|
+
rt_arr = PWN::AI::RedTeam.const_get(
|
|
114
|
+
test_case.to_s.scrub
|
|
115
|
+
).scan(
|
|
116
|
+
target_engine: target_engine,
|
|
117
|
+
target_model: target_model,
|
|
118
|
+
system_role_content: system_role_content
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
rt_arr.each { |hash_line| mutex.synchronize { results_hash[:data].push(hash_line) } }
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Generate HTML Report
|
|
125
|
+
print "#{File.basename($PROGRAM_NAME)} Generating Report..."
|
|
126
|
+
PWN::Reports::AIRedTeam.generate(
|
|
127
|
+
dir_path: dir_path,
|
|
128
|
+
results_hash: results_hash,
|
|
129
|
+
report_name: report_name
|
|
130
|
+
)
|
|
131
|
+
puts 'complete.'
|
|
132
|
+
|
|
133
|
+
# Start Simple HTTP Server (If Requested)
|
|
134
|
+
if start_reporting_server
|
|
135
|
+
listen_ip = '127.0.0.1'
|
|
136
|
+
listen_ip = '0.0.0.0' if pwn_provider == 'docker'
|
|
137
|
+
listen_port = PWN::Plugins::Sock.get_random_unused_port.to_s
|
|
138
|
+
puts "For Scan Results Navigate to: http://127.0.0.1:#{listen_port}/#{report_name}.html"
|
|
139
|
+
|
|
140
|
+
system(
|
|
141
|
+
'pwn_simple_http_server',
|
|
142
|
+
'--bind-ip',
|
|
143
|
+
listen_ip,
|
|
144
|
+
'--port',
|
|
145
|
+
listen_port
|
|
146
|
+
)
|
|
147
|
+
end
|
|
148
|
+
rescue SystemExit, Interrupt
|
|
149
|
+
puts "\nGoodbye."
|
|
150
|
+
end
|
data/bin/pwn_setup
CHANGED
|
@@ -44,6 +44,12 @@ pwn_driver = PWN::Driver::Parser.new do |options|
|
|
|
44
44
|
opts[:yes] = o
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
options.on('-t', '--terminal',
|
|
48
|
+
'<Optional - Opt-in SHIFT+ENTER multi-line support: prints ~/.tmux.conf lines and, ' \
|
|
49
|
+
'under Terminator, installs the PWNShiftEnter GTK plugin (with confirmation)>') do |o|
|
|
50
|
+
opts[:terminal] = o
|
|
51
|
+
end
|
|
52
|
+
|
|
47
53
|
options.on('-n', '--dry-run',
|
|
48
54
|
'<Optional - Print the commands that would run, do not execute>') do |o|
|
|
49
55
|
opts[:dry_run] = o
|
|
@@ -61,14 +67,22 @@ begin
|
|
|
61
67
|
dry_run: opts[:dry_run]
|
|
62
68
|
)
|
|
63
69
|
exit 1 unless r && r[:after] && r[:after][:incompatible].empty?
|
|
64
|
-
elsif opts[:
|
|
70
|
+
elsif opts[:terminal]
|
|
71
|
+
PWN::Setup.terminal(
|
|
72
|
+
yes: opts[:yes],
|
|
73
|
+
dry_run: opts[:dry_run]
|
|
74
|
+
)
|
|
75
|
+
elsif (opts[:deps] || opts[:profile]) && !opts[:check]
|
|
65
76
|
PWN::Setup.deps(
|
|
66
77
|
profile: opts[:profile],
|
|
67
78
|
yes: opts[:yes],
|
|
68
79
|
dry_run: opts[:dry_run]
|
|
69
80
|
)
|
|
70
81
|
else
|
|
71
|
-
|
|
82
|
+
# `pwn setup` → doctor gate on EVERYTHING
|
|
83
|
+
# `pwn setup --check` → same
|
|
84
|
+
# `pwn setup --check --profile net` → gate ONLY on the :net profile
|
|
85
|
+
r = PWN::Setup.check(profile: opts[:profile])
|
|
72
86
|
exit 1 unless r[:ok]
|
|
73
87
|
end
|
|
74
88
|
rescue Interrupt
|
data/build_gem.sh
CHANGED
|
@@ -35,6 +35,9 @@ if [[ $old_ruby_version == $new_ruby_version ]]; then
|
|
|
35
35
|
rvmsudo /bin/bash --login -c "cd ${pwn_root} && bundle exec rake rerdoc"
|
|
36
36
|
echo "Invoking bundle-audit Gemfile Scanner..."
|
|
37
37
|
rvmsudo /bin/bash --login -c "cd ${pwn_root} && bundle exec bundle-audit"
|
|
38
|
+
# Restore ownership of artifacts (rdoc/, pkg/, Gemfile.lock, etc.) generated
|
|
39
|
+
# under rvmsudo above so a subsequent unprivileged `rake` / `git` can operate.
|
|
40
|
+
sudo chown -R $USER:$USER "$pwn_root"
|
|
38
41
|
else
|
|
39
42
|
cd $pwn_root && ./upgrade_ruby.sh $new_ruby_version $old_ruby_version
|
|
40
43
|
fi
|
|
@@ -6,21 +6,25 @@ 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 · 71 tools)
|
|
10
10
|
|
|
11
11
|
| Toolset | Tools | Backed by |
|
|
12
12
|
|---|---|---|
|
|
13
13
|
| `terminal` | `shell` | `Open3.capture3` on the host |
|
|
14
14
|
| `pwn` | `pwn_eval` | `TOPLEVEL_BINDING.eval` in the live REPL process |
|
|
15
15
|
| `memory` | `memory_remember` · `memory_recall` · `memory_forget` · `memory_clear` | `PWN::Memory` → `~/.pwn/memory.json` |
|
|
16
|
-
| `skills` | `skill_list` · `skill_view` · `skill_create` · `skill_add_reference` · `skill_delete` · `skill_migrate_legacy` | `~/.pwn/skills/<name>/SKILL.md` (agentskills.io
|
|
16
|
+
| `skills` | `skill_list` · `skill_view` · `skill_create` · `skill_add_reference` · `skill_delete` · `skill_migrate_legacy` | `~/.pwn/skills/<name>/SKILL.md` (**[agentskills.io](https://agentskills.io) spec**; legacy flat `*.md` auto-migrated) |
|
|
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` · `learning_auto_introspect_toggle` ·
|
|
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`** · **`reward_judge`** · **`reward_prm`** · **`reward_sentinel`** · **`reward_preferences`** · **`reward_export_dpo`** · **`curriculum_practice`** · **`curriculum_train`** · **`curriculum_hindsight`** · **`learning_purge_noise`** | `PWN::AI::Agent::Learning` + `Mistakes` + `Reward` + `Curriculum` → `~/.pwn/learning.jsonl` + `~/.pwn/mistakes.json` + `~/.pwn/preferences.jsonl` + `~/.pwn/curriculum/` + `~/.pwn/finetune/` |
|
|
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_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` |
|
|
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/GQRX) → `~/.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
|
|
|
24
|
+
The `learning` toolset is deliberately fat: **Mistakes** (negative feedback),
|
|
25
|
+
**Reward** (ORM/PRM/sentinel/DPO ledger) and **Curriculum** (self-play, HER,
|
|
26
|
+
regression-gated LoRA) are all facets of the same self-improvement loop -
|
|
27
|
+
see [Reinforcement Learning](Reinforcement-Learning.md).
|
|
24
28
|
|
|
25
29
|
## Dynamic tool-set slimming (`ai.agent.tool_router`)
|
|
26
30
|
|
|
@@ -41,6 +45,8 @@ CORE_TOOLS = shell · pwn_eval · memory_remember · memory_recall
|
|
|
41
45
|
```ruby
|
|
42
46
|
PWN::AI::Agent::Registry.definitions(relevance: 'nmap sweep 10.0.0.0/8', top_k: 10)
|
|
43
47
|
PWN::AI::Agent::Registry.rank(query: 'run a shell command') # inspect ranking
|
|
48
|
+
PWN::AI::Agent::Registry.toolsets # → the 10 names above
|
|
49
|
+
PWN::AI::Agent::Registry.all.count # → 71
|
|
44
50
|
```
|
|
45
51
|
|
|
46
52
|
Frontier engines leave `tool_router` off and receive the full set.
|
|
@@ -75,6 +81,7 @@ recon:
|
|
|
75
81
|
engine: ollama
|
|
76
82
|
```
|
|
77
83
|
|
|
78
|
-
**See also:** [pwn-ai Agent](pwn-ai-Agent.md) · [Mistakes](Mistakes.md) ·
|
|
84
|
+
**See also:** [pwn-ai Agent](pwn-ai-Agent.md) · [Mistakes](Mistakes.md) ·
|
|
85
|
+
[Reinforcement Learning](Reinforcement-Learning.md) · [Swarm](Swarm.md)
|
|
79
86
|
|
|
80
87
|
[← Home](Home.md)
|
|
@@ -1,47 +1,52 @@
|
|
|
1
1
|
# CLI Drivers - `bin/pwn_*`
|
|
2
2
|
|
|
3
|
-
53 headless executables, each a thin `OptionParser`
|
|
4
|
-
(or one workflow). They exist so CI/CD can call PWN
|
|
3
|
+
53 headless executables (52 `pwn_*` + `pwn`), each a thin `OptionParser`
|
|
4
|
+
wrapper over one plugin (or one workflow). They exist so CI/CD can call PWN
|
|
5
|
+
without a REPL or an LLM.
|
|
5
6
|
|
|
6
7
|

|
|
7
8
|
|
|
8
9
|
## Full list
|
|
9
10
|
|
|
10
11
|
```text
|
|
11
|
-
pwn
|
|
12
|
-
pwn_android_war_dialer
|
|
13
|
-
pwn_autoinc_version
|
|
14
|
-
pwn_aws_describe_resources
|
|
15
|
-
pwn_bdba_groups
|
|
16
|
-
pwn_bdba_scan
|
|
17
|
-
pwn_burp_suite_pro_active_rest_api_scan
|
|
18
|
-
pwn_burp_suite_pro_active_scan
|
|
19
|
-
pwn_char_base64_encoding
|
|
20
|
-
pwn_char_dec_encoding
|
|
21
|
-
pwn_char_hex_escaped_encoding
|
|
22
|
-
pwn_char_html_entity_encoding
|
|
23
|
-
pwn_char_unicode_escaped_encoding
|
|
24
|
-
pwn_char_url_encoding
|
|
25
|
-
pwn_crt_sh
|
|
26
|
-
pwn_defectdojo_engagement_create
|
|
27
|
-
pwn_defectdojo_importscan
|
|
28
|
-
pwn_defectdojo_reimportscan
|
|
29
|
-
pwn_diff_csv_files_w_column_exclude
|
|
30
|
-
pwn_domain_reversewhois
|
|
31
|
-
pwn_fuzz_net_app_proto
|
|
32
|
-
pwn_gqrx_scanner
|
|
33
|
-
pwn_jenkins_create_job
|
|
34
|
-
pwn_jenkins_create_view
|
|
35
|
-
pwn_jenkins_install_plugin
|
|
12
|
+
pwn pwn_mail_agent
|
|
13
|
+
pwn_android_war_dialer pwn_msf_postgres_login
|
|
14
|
+
pwn_autoinc_version pwn_nessus_cloud_scan_crud
|
|
15
|
+
pwn_aws_describe_resources pwn_nessus_cloud_vulnscan
|
|
16
|
+
pwn_bdba_groups pwn_nexpose
|
|
17
|
+
pwn_bdba_scan pwn_nmap_discover_tcp_udp
|
|
18
|
+
pwn_burp_suite_pro_active_rest_api_scan pwn_openvas_vulnscan
|
|
19
|
+
pwn_burp_suite_pro_active_scan pwn_pastebin_sample_filter
|
|
20
|
+
pwn_char_base64_encoding pwn_phone
|
|
21
|
+
pwn_char_dec_encoding pwn_rdoc_to_jsonl
|
|
22
|
+
pwn_char_hex_escaped_encoding pwn_sast
|
|
23
|
+
pwn_char_html_entity_encoding pwn_serial_check_voicemail
|
|
24
|
+
pwn_char_unicode_escaped_encoding pwn_serial_msr206
|
|
25
|
+
pwn_char_url_encoding pwn_serial_qualcomm_commands
|
|
26
|
+
pwn_crt_sh pwn_serial_son_micro_sm132_rfid
|
|
27
|
+
pwn_defectdojo_engagement_create pwn_setup
|
|
28
|
+
pwn_defectdojo_importscan pwn_shodan_graphql_introspection
|
|
29
|
+
pwn_defectdojo_reimportscan pwn_shodan_search
|
|
30
|
+
pwn_diff_csv_files_w_column_exclude pwn_simple_http_server
|
|
31
|
+
pwn_domain_reversewhois pwn_web_cache_deception
|
|
32
|
+
pwn_fuzz_net_app_proto pwn_www_checkip
|
|
33
|
+
pwn_gqrx_scanner pwn_www_uri_buster
|
|
34
|
+
pwn_jenkins_create_job pwn_xss_dom_vectors
|
|
35
|
+
pwn_jenkins_create_view pwn_zaproxy_active_rest_api_scan
|
|
36
|
+
pwn_jenkins_install_plugin pwn_zaproxy_active_scan
|
|
37
|
+
pwn_jenkins_thinBackup_aws_s3
|
|
38
|
+
pwn_jenkins_update_plugins
|
|
39
|
+
pwn_jenkins_useradd
|
|
36
40
|
```
|
|
37
41
|
|
|
38
42
|
Run any with `--help` for its flags.
|
|
39
43
|
|
|
40
|
-
## `pwn_setup` - post-install doctor
|
|
44
|
+
## `pwn_setup` - post-install doctor / provisioner / state migrator
|
|
41
45
|
|
|
42
46
|
The one driver that isn't a plugin wrapper. It grows a bare `gem install pwn`
|
|
43
47
|
into a fully-armed host by installing OS headers / external tools for whatever
|
|
44
|
-
capability profile you ask for
|
|
48
|
+
capability profile you ask for, **and** verifies/repairs every persisted
|
|
49
|
+
`~/.pwn` state file after an upgrade. Also reachable as `pwn setup` and
|
|
45
50
|
`pwn --setup[=PROFILE]`.
|
|
46
51
|
|
|
47
52
|
```bash
|
|
@@ -49,10 +54,11 @@ pwn_setup # read-only doctor; exit 1 if degraded
|
|
|
49
54
|
pwn_setup --list-profiles
|
|
50
55
|
pwn_setup --profile web --yes # CI-friendly, non-interactive
|
|
51
56
|
pwn_setup --deps --dry-run # print the apt/dnf/pacman/brew/port commands only
|
|
57
|
+
pwn_setup --migrate --fix # ~/.pwn state doctor + autofix (PWN::Migrate)
|
|
52
58
|
```
|
|
53
59
|
|
|
54
|
-
See [Installation](Installation.md) for the full profile table
|
|
55
|
-
`PWN::Setup` API.
|
|
60
|
+
See [Installation](Installation.md) for the full profile table, the
|
|
61
|
+
`PWN::Setup` API and the `PWN::Migrate` state-file registry.
|
|
56
62
|
|
|
57
63
|
## Typical CI usage
|
|
58
64
|
|
|
@@ -20,6 +20,9 @@ generates the decryptor.
|
|
|
20
20
|
> [doctor](Installation.md#pwn-setup--the-post-install-doctor--provisioner)
|
|
21
21
|
> reports whether `~/.pwn/`, `pwn.yaml`, its decryptor, and an AI-engine key
|
|
22
22
|
> are present, and exits non-zero for CI if any are missing.
|
|
23
|
+
> After `gem update pwn`, run `pwn setup --migrate --fix` — `PWN::Migrate`
|
|
24
|
+
> deep-merges any keys the new `PWN::Config.env_template` added into your
|
|
25
|
+
> encrypted `pwn.yaml` **without overwriting your values**.
|
|
23
26
|
|
|
24
27
|
---
|
|
25
28
|
|
|
@@ -263,6 +266,11 @@ PWN::Config.refresh_env
|
|
|
263
266
|
| `ai.agent.plan_first` | Boolean \| `nil` | `nil` (auto: `true` when `ai.active == ollama`) | `PWN::AI::Agent::Loop.plan_first` | Plan-then-act pre-pass: the model must emit a numbered tool plan (as an assistant message) *before* it may dispatch anything. Cheap chain-of-thought scaffolding for local models. |
|
|
264
267
|
| `ai.agent.tool_router` | Boolean | `false` | `PWN::AI::Agent::Registry.definitions` | Dynamic tool-set slimming: expose only `Registry::CORE_TOOLS` + the top-K keyword-relevant schemas for *this* request. Ties break on historical `Metrics` success rate so the router itself is a learned component. |
|
|
265
268
|
| `ai.agent.escalation_persona` | String \| `nil` | `nil` | `PWN::AI::Agent::Loop.escalate` → `Swarm.ask` | Circuit-breaker: once a local model accumulates ≥ `Loop::ESCALATE_AFTER_FAILS` in-turn failures, ask this Swarm persona for a 3-line corrective hint (injected as a synthetic tool result). The local model still authors the final answer so Learning/Metrics stay attributed. |
|
|
269
|
+
| `ai.agent.critic` | Boolean | `false` | `PWN::AI::Agent::Curriculum.critic` (S3) | Tool-armed constitutional self-critic reviews (and may `shell`/`extro_verify`) every final answer before it is returned. |
|
|
270
|
+
| `ai.agent.red_team_plan` | Boolean | `false` | `PWN::AI::Agent::Curriculum.red_team_plan` (S4) | Adversarial review of the `plan_first` numbered plan, grounded in Metrics/Mistakes/`extro_drift` telemetry, before the first dispatch. |
|
|
271
|
+
| `ai.agent.counterfactual` | Boolean | `false` | `PWN::AI::Agent::Curriculum.counterfactual` (S2) | On `[REPEATING]`, fork an alt-persona branch, judge both, and record the `(loser, winner)` DPO preference pair. |
|
|
272
|
+
| `ai.agent.hindsight` | Boolean | `true` | `PWN::AI::Agent::Curriculum.hindsight` (C3) | Hindsight Experience Replay — relabel a failed trajectory as `success:true` for whatever it *did* accomplish. Free positive samples from failures. |
|
|
273
|
+
| `ai.agent.verify_as_reward` | Boolean | `false` | `PWN::AI::Agent::Reward.verify_as_reward` (E3) | Ground the LLM judge score by browser-verifying any checkable claim in the final via `extro_verify`; verdict caps/floors `Reward.judge`. |
|
|
266
274
|
| `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`. |
|
|
267
275
|
| `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`). |
|
|
268
276
|
| `ai.agent.extrospection.web.max_anchors` | Integer | `8` | `Extrospection.probe_web` | Cap on anchors rendered per snapshot. |
|
|
@@ -371,9 +379,14 @@ agent system prompt.
|
|
|
371
379
|
|
|
372
380
|
`pwn.yaml` is the only file you edit; everything else is machine-written
|
|
373
381
|
state. See **[Persistence](Persistence.md)** for the full map
|
|
374
|
-
(`memory.json`, `memory.idx`, `learning.jsonl`,
|
|
375
|
-
`
|
|
376
|
-
`
|
|
382
|
+
(`.schema`, `memory.json`, `memory.idx`, `learning.jsonl`,
|
|
383
|
+
`preferences.jsonl`, `mistakes.json`, `metrics.json`,
|
|
384
|
+
`reward_sentinel.json`, `extrospection.json`, `sessions/`,
|
|
385
|
+
`skills/<name>/SKILL.md`, `curriculum/`, `finetune/`, `cron/`,
|
|
386
|
+
`agents.yml`, `swarm/`, `backup/`, `quarantine/`).
|
|
387
|
+
|
|
388
|
+
`pwn setup --migrate` verifies (and `--fix` autorepairs) every
|
|
389
|
+
one of them against the running gem version.
|
|
377
390
|
|
|
378
391
|
Multi-agent personas are **not** configured here - they live in
|
|
379
392
|
`~/.pwn/agents.yml` and are managed with `agent_spawn` / `agent_list`
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
```text
|
|
6
6
|
lib/pwn/ # all namespaces
|
|
7
7
|
lib/pwn/setup.rb # PWN::Setup - doctor/provisioner data tables
|
|
8
|
+
lib/pwn/migrate.rb # PWN::Migrate - ~/.pwn state doctor / auto-migrator
|
|
8
9
|
lib/pwn/plugins/ # 66 plugin modules
|
|
9
10
|
lib/pwn/ai/agent/ # agent core
|
|
10
11
|
lib/pwn/ai/agent/tools/ # LLM tool registrations
|
|
11
|
-
bin/ #
|
|
12
|
+
bin/ # 52 pwn_* drivers + pwn (incl. pwn_setup)
|
|
12
13
|
spec/ # RSpec (incl. conventions_spec)
|
|
13
14
|
documentation/ # this wiki + diagrams
|
|
14
15
|
```
|
|
@@ -44,7 +45,13 @@ rake # rubocop + rspec - must be zero offenses
|
|
|
44
45
|
set, reference it from `PWN::Setup::PROFILES`. That single edit makes
|
|
45
46
|
`pwn setup` install it on every OS and every install path (gem, git,
|
|
46
47
|
Docker, Packer, Vagrant, CI). **Do not** add a new bash provisioner.
|
|
47
|
-
7.
|
|
48
|
+
7. **If it persists a new file under `~/.pwn/`**, add **one entry** to
|
|
49
|
+
`PWN::Migrate::STATE_FILES` in `lib/pwn/migrate.rb` (owner, kind,
|
|
50
|
+
`:fix` strategy, shallow verifier). If the change breaks *existing*
|
|
51
|
+
files, bump `PWN::Migrate::SCHEMA_VERSION` and append an idempotent
|
|
52
|
+
lambda to `PWN::Migrate::MIGRATIONS`. `pwn setup --migrate --fix`
|
|
53
|
+
then heals every user's `~/.pwn` on upgrade.
|
|
54
|
+
8. Update [Plugins.md](Plugins.md) and, if it changes a data flow, the
|
|
48
55
|
relevant `.dot` in `documentation/diagrams/dot/` → `./build.sh`.
|
|
49
56
|
|
|
50
57
|
## Commit / release
|
data/documentation/Cron.md
CHANGED
|
@@ -24,6 +24,26 @@ invokes `PWN::Cron.run(<id>)` on schedule.
|
|
|
24
24
|
| `cron_enable` / `cron_disable` | Toggle without deleting |
|
|
25
25
|
| `cron_remove` | Delete from `jobs.yml` (does **not** scrub crontab - `crontab -e` yourself) |
|
|
26
26
|
|
|
27
|
+
## Seeded self-improvement jobs (`PWN::Cron.install_defaults`)
|
|
28
|
+
|
|
29
|
+
`pwn setup --migrate` (schema `v1`) seeds two jobs into every fresh
|
|
30
|
+
`~/.pwn/cron/jobs.yml`:
|
|
31
|
+
|
|
32
|
+
| Name | Schedule | Ruby |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `curriculum_practice_nightly` | `0 3 * * *` | `PWN::AI::Agent::Curriculum.practice(limit: 3)` |
|
|
35
|
+
| `curriculum_train_weekly` | `0 4 * * 0` | `PWN::AI::Agent::Curriculum.train_and_gate(dry_run: true)` |
|
|
36
|
+
|
|
37
|
+
The first practises the top unresolved `Mistakes` under `Reward.judge` and
|
|
38
|
+
auto-`resolve`s any it now solves; the second exports SFT + DPO datasets to
|
|
39
|
+
`~/.pwn/finetune/`, LoRA-trains a `pwn-vN+1` local model, replays the
|
|
40
|
+
`Mistakes.top` set on both, and only promotes the new adapter when it wins.
|
|
41
|
+
Set `dry_run: false` (via `pwn-ai-cron` or `cron_create`) once a local
|
|
42
|
+
trainer is installed. See [Reinforcement Learning](Reinforcement-Learning.md).
|
|
43
|
+
|
|
44
|
+
`cron_disable(id:)` turns either off; `install_defaults` is idempotent and
|
|
45
|
+
never overwrites a job you already have with the same name.
|
|
46
|
+
|
|
27
47
|
## Example
|
|
28
48
|
|
|
29
49
|
```ruby
|
|
@@ -57,6 +77,6 @@ yyyy-mm-dd]` so the injected MEMORY block stops calcifying into
|
|
|
57
77
|
confidently-wrong priors - see [Extrospection § revalidate_memory](Extrospection.md).
|
|
58
78
|
|
|
59
79
|
**See also:** [Sessions](Sessions.md) · [Extrospection](Extrospection.md) ·
|
|
60
|
-
[CLI Drivers](CLI-Drivers.md)
|
|
80
|
+
[Reinforcement Learning](Reinforcement-Learning.md) · [CLI Drivers](CLI-Drivers.md)
|
|
61
81
|
|
|
62
82
|
[← Home](Home.md)
|
data/documentation/Diagrams.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PWN Data-Flow Diagrams
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
28 SVG diagrams, all rendered from Graphviz sources in
|
|
4
4
|
[`diagrams/dot/`](diagrams/dot/) with a single shared visual theme
|
|
5
5
|
(see [`_THEME.md`](diagrams/dot/_THEME.md)). Rebuild everything with:
|
|
6
6
|
|
|
@@ -55,11 +55,15 @@ groups) so lines never criss-cross.
|
|
|
55
55
|
[source](diagrams/dot/mistakes-negative-feedback.dot) · doc: [Mistakes](Mistakes.md)
|
|
56
56
|

|
|
57
57
|
|
|
58
|
+
### Reinforcement Learning - Reward + Curriculum
|
|
59
|
+
[source](diagrams/dot/reinforcement-learning.dot) · doc: [Reinforcement Learning](Reinforcement-Learning.md)
|
|
60
|
+

|
|
61
|
+
|
|
58
62
|
### Multi-Provider LLM Integration
|
|
59
63
|
[source](diagrams/dot/ai-integration-tool-calling.dot) · doc: [AI Integration](AI-Integration.md)
|
|
60
64
|

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

|
|
65
69
|
|
data/documentation/Drivers.md
CHANGED
|
@@ -43,7 +43,7 @@ puts result
|
|
|
43
43
|
| Artifact | Made with | Consumed by |
|
|
44
44
|
|---|---|---|
|
|
45
45
|
| `bin/pwn_<name>` | template above | shell / CI |
|
|
46
|
-
| `~/.pwn/skills/<name
|
|
46
|
+
| `~/.pwn/skills/<name>/SKILL.md` | `learning_distill_skill` | every future pwn-ai prompt |
|
|
47
47
|
| `cron` job | `cron_create(ruby: '...')` | system crontab → unattended |
|
|
48
48
|
|
|
49
49
|
**See also:** [CLI Drivers](CLI-Drivers.md) · [Cron](Cron.md) ·
|
|
@@ -14,9 +14,11 @@ $ pwn_nmap_discover_tcp_udp -t 10.0.0.0/24 -o out/ # headless driver
|
|
|
14
14
|
$ pwn setup # doctor: which PWN:: capabilities are usable here?
|
|
15
15
|
$ pwn setup --profile web # install what TransparentBrowser / Burp / ZAP need
|
|
16
16
|
$ pwn setup --list-profiles # core · ai · web · net · db · sdr · vision · voice · exploit · hardware · full
|
|
17
|
+
$ pwn setup --migrate --fix # after `gem update pwn`: verify + autofix ~/.pwn state
|
|
17
18
|
```
|
|
18
19
|
|
|
19
|
-
See [Installation](Installation.md) for every flag and the
|
|
20
|
+
See [Installation](Installation.md) for every flag and the
|
|
21
|
+
`PWN::Setup` / `PWN::Migrate` API.
|
|
20
22
|
|
|
21
23
|
## Inside the REPL
|
|
22
24
|
|
|
@@ -25,6 +27,7 @@ PWN.help # top-level help
|
|
|
25
27
|
PWN::Plugins.constants.sort # list all 66 plugins
|
|
26
28
|
PWN::Plugins::NmapIt.help # per-plugin usage
|
|
27
29
|
PWN::Setup.check # capability doctor from inside the REPL
|
|
30
|
+
PWN::Migrate.status # ~/.pwn state-file compatibility rows
|
|
28
31
|
ls PWN::Plugins::BurpSuite # Pry: list methods
|
|
29
32
|
show-source PWN::SAST::SQL.scan # Pry: read the code
|
|
30
33
|
history # what you've typed → copy into a driver
|
|
@@ -36,11 +39,14 @@ history # what you've typed → copy into a driver
|
|
|
36
39
|
|---|---|
|
|
37
40
|
| `pwn-ai` | Enter the agent TUI (SHIFT+ENTER = newline, ENTER = submit) |
|
|
38
41
|
| `pwn-asm` | Multi-line assembly ↔ opcode workbench |
|
|
42
|
+
| `pwn-mesh` | Meshtastic serial / MQTT client (Ruby ≥ 4.0) |
|
|
39
43
|
| `pwn-vault` | Decrypt → edit `~/.pwn/pwn.yaml` in `$EDITOR` → re-encrypt |
|
|
40
44
|
| `pwn-ai-memory` | Inspect / edit `~/.pwn/memory.json` |
|
|
41
45
|
| `pwn-ai-sessions` | List / view / delete transcripts |
|
|
42
46
|
| `pwn-ai-cron` | List / run scheduled jobs |
|
|
43
47
|
| `pwn-ai-delegate` | Hand a task to a Swarm persona |
|
|
48
|
+
| `toggle-pwn-ai-debug` | Show/hide raw tool_calls JSON |
|
|
49
|
+
| `toggle-pwn-ai-speaks` | TTS every final answer on/off |
|
|
44
50
|
| `welcome-banner` | Redraw a random `PWN::Banner` |
|
|
45
51
|
| `toggle-pager` | Pry pager on/off |
|
|
46
52
|
|
data/documentation/Home.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
| [Installation](Installation.md) | `gem install pwn` → `pwn setup` doctor/provisioner · capability profiles · `--migrate` state doctor |
|
|
21
21
|
| [General Usage](General-PWN-Usage.md) | Day-one cheat sheet |
|
|
22
22
|
| [Configuration](Configuration.md) | `~/.pwn/pwn.yaml` (encrypted) - engines, keys, agent options · `pwn-vault` |
|
|
23
|
-
| **[All Data-Flow Diagrams](Diagrams.md)** | **
|
|
23
|
+
| **[All Data-Flow Diagrams](Diagrams.md)** | **28 SVGs** in one scrollable page |
|
|
24
24
|
|
|
25
25
|
## 🚪 Entry Points
|
|
26
26
|
|