pwn 0.5.620 → 0.5.622
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/Gemfile +1 -1
- data/README.md +1 -1
- data/documentation/Agent-Tool-Registry.md +3 -3
- data/documentation/Configuration.md +292 -47
- data/documentation/Cron.md +14 -1
- data/documentation/Diagrams.md +1 -1
- data/documentation/Extrospection.md +71 -5
- data/documentation/Home.md +2 -2
- data/documentation/How-PWN-Works.md +1 -1
- data/documentation/Mistakes.md +2 -1
- data/documentation/Persistence.md +2 -1
- data/documentation/Skills-Memory-Learning.md +3 -2
- data/documentation/Transparent-Browser.md +18 -1
- data/documentation/diagrams/agent-tool-registry.svg +55 -54
- 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 +29 -8
- data/documentation/diagrams/dot/memory-skills-detailed.dot +4 -0
- data/documentation/diagrams/dot/overall-pwn-architecture.dot +2 -2
- data/documentation/diagrams/dot/persistence-filesystem.dot +2 -1
- data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +11 -5
- data/documentation/diagrams/driver-framework.svg +13 -13
- data/documentation/diagrams/extrospection-world-awareness.svg +229 -99
- data/documentation/diagrams/fuzzing-workflow.svg +24 -24
- data/documentation/diagrams/hardware-hacking.svg +18 -18
- data/documentation/diagrams/history-to-drivers.svg +18 -18
- data/documentation/diagrams/memory-skills-detailed.svg +124 -101
- data/documentation/diagrams/mistakes-negative-feedback.svg +55 -55
- data/documentation/diagrams/network-infra-testing.svg +27 -27
- data/documentation/diagrams/overall-pwn-architecture.svg +85 -85
- data/documentation/diagrams/penetration-testing-workflow.svg +30 -30
- data/documentation/diagrams/persistence-filesystem.svg +94 -85
- data/documentation/diagrams/plugin-ecosystem.svg +35 -35
- data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +226 -180
- 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 +31 -31
- 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 +4 -4
- 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 +435 -6
- 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 +89 -4
- 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/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 +14 -33
- data/lib/pwn/sdr/decoder/apt.rb +97 -36
- data/lib/pwn/sdr/decoder/base.rb +258 -171
- data/lib/pwn/sdr/decoder/bluetooth.rb +13 -20
- data/lib/pwn/sdr/decoder/dect.rb +13 -27
- data/lib/pwn/sdr/decoder/dsp.rb +396 -0
- data/lib/pwn/sdr/decoder/flex.rb +177 -210
- data/lib/pwn/sdr/decoder/gps.rb +12 -21
- data/lib/pwn/sdr/decoder/gsm.rb +21 -73
- data/lib/pwn/sdr/decoder/iridium.rb +11 -26
- data/lib/pwn/sdr/decoder/lora.rb +16 -23
- data/lib/pwn/sdr/decoder/lte.rb +11 -32
- data/lib/pwn/sdr/decoder/morse.rb +95 -21
- data/lib/pwn/sdr/decoder/p25.rb +19 -16
- data/lib/pwn/sdr/decoder/pager.rb +22 -38
- data/lib/pwn/sdr/decoder/pocsag.rb +175 -68
- data/lib/pwn/sdr/decoder/rfid.rb +24 -33
- data/lib/pwn/sdr/decoder/rtl433.rb +21 -30
- data/lib/pwn/sdr/decoder/rtty.rb +100 -27
- data/lib/pwn/sdr/decoder/wifi.rb +21 -42
- data/lib/pwn/sdr/decoder/zigbee.rb +18 -40
- data/lib/pwn/sdr/decoder.rb +8 -0
- data/lib/pwn/sdr/gqrx.rb +1 -1
- data/lib/pwn/version.rb +1 -1
- data/spec/lib/pwn/ai/agent/{introspection_spec.rb → reflect_spec.rb} +3 -3
- data/spec/lib/pwn/sdr/decoder/dsp_spec.rb +15 -0
- data/third_party/pwn_rdoc.jsonl +75 -19
- metadata +7 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f4aeb484ae013e0feb9648009d60cfc493bbd4ec98ba42193745af669ed70bcc
|
|
4
|
+
data.tar.gz: 2dcffdf992ee24a9c8a10ae7b83c743ad5b6b1aed83e70063da56e8cf6e9ea85
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2468ec9291d44be94de1f3877441380e60cde34e24953f6ac677bd39f0679c82ab6f82f6554b7fcacf1348b0c751c63bf8d8a23a369ac665023b5a9e74cc3a01
|
|
7
|
+
data.tar.gz: 722765fd660ca9da266a170da45f65eb061886b7629557143436a0765412dc89d3de3e56ac8f5bd8e9b32e5f25831d3644ac3568d851f6ac5f7629531b9e7768
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Five layers, edges only ever go down:
|
|
|
52
52
|
|
|
53
53
|
The AI layer closes a **self-improvement loop** on every turn — Metrics +
|
|
54
54
|
Learning + **Mistakes** (introspection / negative feedback) joined with
|
|
55
|
-
Snapshot + Drift + Intel + RF (extrospection) via `extro_correlate`, so the
|
|
55
|
+
Snapshot + Drift + Intel + RF + **Web** (extrospection) — plus browser-backed **`extro_verify`** self fact-checking — via `extro_correlate`, so the
|
|
56
56
|
agent knows whether a failure was *its* fault or *the world* changed —
|
|
57
57
|
**and does not repeat the same mistake twice**:
|
|
58
58
|
|
|
@@ -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 · 54 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_correlate` · `extro_stats` · `extro_reset` · `extro_auto_toggle` | `PWN::AI::Agent::Extrospection` → `~/.pwn/extrospection.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` (+ `PWN::Plugins::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,311 @@
|
|
|
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 # Also run Extrospection.auto_extrospect (host/toolchain/net/repo drift capture) after every final answer.
|
|
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
|
+
|
|
98
|
+
plugins:
|
|
99
|
+
asm:
|
|
100
|
+
arch: x86_64 # Target architecture for `pwn-asm` inline assembler/disassembler. Default: PWN::Plugins::DetectOS.arch.
|
|
101
|
+
endian: little # Endianness for `pwn-asm` (little | big). Default: PWN::Plugins::DetectOS.endian.
|
|
102
|
+
blockchain:
|
|
103
|
+
bitcoin:
|
|
104
|
+
rpc_host: localhost # bitcoind JSON-RPC host for PWN::Blockchain::BTC.
|
|
105
|
+
rpc_port: 8332 # bitcoind JSON-RPC port.
|
|
106
|
+
rpc_user: … # bitcoind RPC username (rpcauth / rpcuser in bitcoin.conf).
|
|
107
|
+
rpc_pass: … # bitcoind RPC password. Redacted in PWN::EnvRedacted.
|
|
108
|
+
hunter:
|
|
109
|
+
api_key: … # hunter.how API key — passed as api_key: to PWN::Plugins::Hunter.search.
|
|
110
|
+
jira_data_center:
|
|
111
|
+
base_uri: https://jira.company.com/rest/api/latest # Jira Data Center REST base URL.
|
|
112
|
+
token: … # Jira Personal Access Token for PWN::Plugins::JiraDataCenter. Redacted.
|
|
113
|
+
meshtastic:
|
|
114
|
+
admin_key: … # Public key authorised to send admin messages to mesh nodes via `pwn-mesh`.
|
|
115
|
+
serial:
|
|
116
|
+
port: /dev/ttyUSB0 # Serial device path for a locally-attached Meshtastic node.
|
|
117
|
+
baud: 115200 # Serial baud rate.
|
|
118
|
+
bits: 8 # Serial data bits.
|
|
119
|
+
stop: 1 # Serial stop bits.
|
|
120
|
+
parity: none # Serial parity (none | even | odd).
|
|
121
|
+
mqtt:
|
|
122
|
+
host: mqtt.meshtastic.org # MQTT broker hostname for Meshtastic-over-MQTT.
|
|
123
|
+
port: 1883 # MQTT broker port (8883 for TLS).
|
|
124
|
+
tls: false # Use TLS to the MQTT broker.
|
|
125
|
+
user: meshdev # MQTT username (public Meshtastic broker default shown).
|
|
126
|
+
pass: large4cats # MQTT password (public Meshtastic broker default shown). Redacted.
|
|
127
|
+
channel:
|
|
128
|
+
active: LongFast # Which named channel block below `pwn-mesh` uses for TX/RX.
|
|
129
|
+
LongFast: # Channel definition — name is arbitrary, referenced by `active:` above.
|
|
130
|
+
psk: 'AQ==' # Channel pre-shared key (base64). 'AQ==' = Meshtastic default public key. Redacted.
|
|
131
|
+
region: US/UT # LoRa region tag (regulatory band).
|
|
132
|
+
topic: 2/e/# # MQTT topic filter to subscribe/publish for this channel.
|
|
133
|
+
channel_num: 8 # Meshtastic channel index (slot number on the device).
|
|
134
|
+
from: '!deadbeef' # Sender node id used on outbound packets. Optional — defaults to !<mqtt client_id>.
|
|
135
|
+
PWN: # Example second (private) channel definition.
|
|
136
|
+
psk: … # Private channel pre-shared key (base64). Redacted.
|
|
137
|
+
region: US/UT # LoRa region tag for this channel.
|
|
138
|
+
topic: 2/e/PWN/# # MQTT topic filter for this channel.
|
|
139
|
+
channel_num: 99 # Meshtastic channel index for this channel.
|
|
140
|
+
shodan:
|
|
141
|
+
api_key: … # Shodan API key — passed as api_key: to PWN::Plugins::Shodan.*. Redacted.
|
|
142
|
+
|
|
143
|
+
memory:
|
|
144
|
+
enabled: true # Reserve — persistent-memory subsystem on/off (currently always active; future gate).
|
|
145
|
+
provider: file # Storage backend for PWN::Memory: file (~/.pwn/memory.json). `sqlite` reserved.
|
|
146
|
+
|
|
147
|
+
sessions:
|
|
148
|
+
enabled: true # Reserve — transcript recording on/off (currently always active; future gate).
|
|
149
|
+
provider: jsonl # Transcript format under ~/.pwn/sessions/ (one .jsonl per session).
|
|
150
|
+
|
|
151
|
+
cron:
|
|
152
|
+
enabled: true # Reserve — scheduled-job subsystem on/off (currently always active; future gate).
|
|
153
|
+
provider: yaml # Job store format for PWN::Cron (~/.pwn/cron/jobs.yml).
|
|
154
|
+
|
|
155
|
+
targets: # Optional — engagement-scope URLs/hosts. Merged into :web snapshot anchors
|
|
156
|
+
- https://target.example.com # ONLY when ai.agent.extrospection.web.allow_targets: true.
|
|
36
157
|
```
|
|
37
158
|
|
|
159
|
+
---
|
|
160
|
+
|
|
38
161
|
## Reading / writing at runtime
|
|
39
162
|
|
|
40
163
|
```ruby
|
|
41
|
-
PWN::Env[:ai][:
|
|
42
|
-
PWN::Env
|
|
43
|
-
PWN::
|
|
164
|
+
PWN::Env[:ai][:active] # => :grok
|
|
165
|
+
PWN::Env.dig(:ai, :agent, :max_iters) # => 25
|
|
166
|
+
PWN::EnvRedacted[:ai][:grok][:key] # => ">>> REDACTED >>> …"
|
|
167
|
+
|
|
168
|
+
# Edit + re-encrypt + reload without leaving the REPL:
|
|
169
|
+
pwn-vault
|
|
170
|
+
|
|
171
|
+
# Force a reload from disk (e.g. after pwn-vault in another shell):
|
|
172
|
+
PWN::Config.refresh_env
|
|
44
173
|
```
|
|
45
174
|
|
|
46
|
-
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Exhaustive key reference
|
|
178
|
+
|
|
179
|
+
### `ai` — AI engines & agent loop
|
|
180
|
+
|
|
181
|
+
| Key path | Type | Default | Consumed by | Purpose |
|
|
182
|
+
|---|---|---|---|---|
|
|
183
|
+
| `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`. |
|
|
184
|
+
| `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`). |
|
|
185
|
+
| `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`. |
|
|
186
|
+
| `ai.<engine>.key` | String | — | `PWN::AI::<Engine>` | API key / bearer token. If blank AND no OAuth is configured, PWN prompts interactively at load. |
|
|
187
|
+
| `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`). |
|
|
188
|
+
| `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. |
|
|
189
|
+
| `ai.<engine>.temp` | Float | `1.0` | `PWN::AI::<Engine>.chat` | Sampling temperature. |
|
|
190
|
+
| `ai.<engine>.max_prompt_length` | Integer | per-engine | `PWN::AI::<Engine>`, `PWN::Plugins::REPL` | Soft input-context ceiling used for prompt truncation / chunking. |
|
|
191
|
+
| `ai.anthropic.max_tokens` | Integer | `8192` | `PWN::AI::Anthropic.chat_tool_loop` | Max **output** tokens per response. Raise if tool-call JSON truncates. |
|
|
192
|
+
| `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). |
|
|
193
|
+
| `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. |
|
|
194
|
+
| `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. |
|
|
195
|
+
| `ai.grok.oauth.client_id` | String | Grok-CLI public id | `PWN::AI::Grok` | Override the public OAuth client id used for device-flow / refresh. |
|
|
196
|
+
| `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. |
|
|
197
|
+
| `ai.grok.oauth.scope` | String | see example | `PWN::AI::Grok` | OAuth scope string requested during device-flow enrollment. |
|
|
198
|
+
| `ai.grok.oauth.token_uri` | String | `https://auth.x.ai/oauth2/token` | `PWN::AI::Grok` | OAuth token endpoint (override for enterprise IdP). |
|
|
199
|
+
| `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. |
|
|
200
|
+
|
|
201
|
+
### `ai.agent` — pwn-ai autonomous loop
|
|
202
|
+
|
|
203
|
+
| Key path | Type | Default | Consumed by | Purpose |
|
|
204
|
+
|---|---|---|---|---|
|
|
205
|
+
| `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. |
|
|
206
|
+
| `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. |
|
|
207
|
+
| `ai.agent.max_depth` | Integer | `3` | `PWN::AI::Agent::Swarm` | Recursion guard for `agent_ask` / `agent_debate` sub-agents spawning sub-agents. |
|
|
208
|
+
| `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`. |
|
|
209
|
+
| `ai.agent.auto_extrospect` | Boolean | `false` | `PWN::AI::Agent::Extrospection.auto_extrospect` | Also capture host/toolchain/net/repo drift after every final answer. Toggle live via `extro_auto_toggle`. |
|
|
210
|
+
| `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`. |
|
|
211
|
+
| `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`. |
|
|
212
|
+
| `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`). |
|
|
213
|
+
| `ai.agent.extrospection.web.max_anchors` | Integer | `8` | `Extrospection.probe_web` | Cap on anchors rendered per snapshot. |
|
|
214
|
+
| `ai.agent.extrospection.web.per_page_timeout` | Integer | `15` | `Extrospection` (headless browser) | Seconds before a page render is abandoned. |
|
|
215
|
+
| `ai.agent.extrospection.web.screenshot` | Boolean | `false` | `Extrospection.probe_web` / `.watch` | Persist a PNG per anchor to `~/.pwn/extrospection/web/`. |
|
|
216
|
+
| `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). |
|
|
217
|
+
|
|
218
|
+
### `plugins` — module credentials & wiring
|
|
219
|
+
|
|
220
|
+
| Key path | Type | Default | Consumed by | Purpose |
|
|
221
|
+
|---|---|---|---|---|
|
|
222
|
+
| `plugins.asm.arch` | String | `DetectOS.arch` | `PWN::Plugins::REPL` (`pwn-asm`) | Target architecture for the inline assembler / disassembler prompt (`x86_64`, `arm64`, …). |
|
|
223
|
+
| `plugins.asm.endian` | String | `DetectOS.endian` | `PWN::Plugins::REPL` (`pwn-asm`) | Endianness for the inline assembler (`little` / `big`). |
|
|
224
|
+
| `plugins.blockchain.bitcoin.rpc_host` | String | `localhost` | `PWN::Blockchain::BTC` | bitcoind JSON-RPC host. |
|
|
225
|
+
| `plugins.blockchain.bitcoin.rpc_port` | Integer | `8332` | `PWN::Blockchain::BTC` | bitcoind JSON-RPC port. |
|
|
226
|
+
| `plugins.blockchain.bitcoin.rpc_user` | String | — | `PWN::Blockchain::BTC` | bitcoind RPC username. |
|
|
227
|
+
| `plugins.blockchain.bitcoin.rpc_pass` | String | — | `PWN::Blockchain::BTC` | bitcoind RPC password. |
|
|
228
|
+
| `plugins.hunter.api_key` | String | — | `PWN::Plugins::Hunter` | hunter.how API key (passed as `api_key:` to `Hunter.search`). |
|
|
229
|
+
| `plugins.jira_data_center.base_uri` | String | — | `PWN::Plugins::JiraDataCenter` | Jira DC REST base (e.g. `https://jira.company.com/rest/api/latest`). |
|
|
230
|
+
| `plugins.jira_data_center.token` | String | — | `PWN::Plugins::JiraDataCenter` | Jira Personal Access Token. |
|
|
231
|
+
| `plugins.meshtastic.admin_key` | String | — | `PWN::Plugins::REPL` (`pwn-mesh`) | Public key authorised to send admin messages to mesh nodes. |
|
|
232
|
+
| `plugins.meshtastic.serial.port` | String | `/dev/ttyUSB0` | `pwn-mesh` (serial) | Serial device path for a locally-attached Meshtastic node. |
|
|
233
|
+
| `plugins.meshtastic.serial.baud` | Integer | `115200` | `pwn-mesh` (serial) | Serial baud rate. |
|
|
234
|
+
| `plugins.meshtastic.serial.bits` | Integer | `8` | `pwn-mesh` (serial) | Serial data bits. |
|
|
235
|
+
| `plugins.meshtastic.serial.stop` | Integer | `1` | `pwn-mesh` (serial) | Serial stop bits. |
|
|
236
|
+
| `plugins.meshtastic.serial.parity` | Symbol | `:none` | `pwn-mesh` (serial) | Serial parity. |
|
|
237
|
+
| `plugins.meshtastic.mqtt.host` | String | `mqtt.meshtastic.org` | `pwn-mesh` → `Meshtastic::MQTT.connect` | MQTT broker hostname. |
|
|
238
|
+
| `plugins.meshtastic.mqtt.port` | Integer | `1883` | `pwn-mesh` | MQTT broker port. |
|
|
239
|
+
| `plugins.meshtastic.mqtt.tls` | Boolean | `false` | `pwn-mesh` | Use TLS to the MQTT broker. |
|
|
240
|
+
| `plugins.meshtastic.mqtt.user` | String | `meshdev` | `pwn-mesh` | MQTT username. |
|
|
241
|
+
| `plugins.meshtastic.mqtt.pass` | String | `large4cats` | `pwn-mesh` | MQTT password. |
|
|
242
|
+
| `plugins.meshtastic.channel.active` | String | `LongFast` | `pwn-mesh` | Which named channel block below is used for TX/RX. |
|
|
243
|
+
| `plugins.meshtastic.channel.<NAME>.psk` | String (b64) | `AQ==` | `pwn-mesh` | Channel pre-shared key. |
|
|
244
|
+
| `plugins.meshtastic.channel.<NAME>.region` | String | — | `pwn-mesh` | LoRa region tag (e.g. `US/UT`). |
|
|
245
|
+
| `plugins.meshtastic.channel.<NAME>.topic` | String | — | `pwn-mesh` | MQTT topic filter to subscribe/publish (e.g. `2/e/#`). |
|
|
246
|
+
| `plugins.meshtastic.channel.<NAME>.channel_num` | Integer | — | `pwn-mesh` | Meshtastic channel index. |
|
|
247
|
+
| `plugins.meshtastic.channel.<NAME>.from` | String | `!<mqtt client_id>` | `pwn-mesh` | Sender node id used on outbound packets. |
|
|
248
|
+
| `plugins.shodan.api_key` | String | — | `PWN::Plugins::Shodan` | Shodan API key (passed as `api_key:` to `Shodan.*`). |
|
|
249
|
+
|
|
250
|
+
### `memory` / `sessions` / `cron`
|
|
251
|
+
|
|
252
|
+
| Key path | Type | Default | Consumed by | Purpose |
|
|
253
|
+
|---|---|---|---|---|
|
|
254
|
+
| `memory.enabled` | Boolean | `true` | `PWN::Memory` | Reserve — persistent memory on/off (currently always active; future gate). |
|
|
255
|
+
| `memory.provider` | String | `file` | `PWN::Memory` | Storage backend: `file` (`~/.pwn/memory.json`). `sqlite` reserved. |
|
|
256
|
+
| `sessions.enabled` | Boolean | `true` | `PWN::Sessions` | Reserve — transcript recording on/off (currently always active; future gate). |
|
|
257
|
+
| `sessions.provider` | String | `jsonl` | `PWN::Sessions` | Transcript format under `~/.pwn/sessions/`. |
|
|
258
|
+
| `cron.enabled` | Boolean | `true` | `PWN::Cron` | Reserve — scheduled-job subsystem on/off (currently always active; future gate). |
|
|
259
|
+
| `cron.provider` | String | `yaml` | `PWN::Cron` | Job store format (`~/.pwn/cron/jobs.yml`). |
|
|
260
|
+
|
|
261
|
+
### Top-level / miscellaneous
|
|
262
|
+
|
|
263
|
+
| Key path | Type | Default | Consumed by | Purpose |
|
|
264
|
+
|---|---|---|---|---|
|
|
265
|
+
| `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`. |
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Runtime-only keys on `PWN::Env` (NOT stored in `pwn.yaml`)
|
|
270
|
+
|
|
271
|
+
These are injected by `PWN::Config.refresh_env` / `PWN::AI::Agent::Loop` after
|
|
272
|
+
the YAML is decrypted. They will appear on `PWN::Env` in-process but are
|
|
273
|
+
**overwritten on every load**, so putting them in `pwn.yaml` has no effect.
|
|
274
|
+
|
|
275
|
+
| Key path | Set by | Purpose |
|
|
276
|
+
|---|---|---|
|
|
277
|
+
| `driver_opts.pwn_env_path` | `PWN::Config.refresh_env` / `PWN::Driver::Parser` | Resolved path to the active `pwn.yaml` (from `--pwn_env` or default). |
|
|
278
|
+
| `driver_opts.pwn_dec_path` | `PWN::Config.refresh_env` / `PWN::Driver::Parser` | Resolved path to the decryptor YAML (from `--pwn_dec` or default). |
|
|
279
|
+
| `pwn_skills_path` | `PWN::Config.refresh_env` | Absolute path to `~/.pwn/skills/`. |
|
|
280
|
+
| `pwn_memory_path` | `PWN::Config.refresh_env` | Absolute path to `~/.pwn/memory.json`. |
|
|
281
|
+
| `pwn_sessions_path` | `PWN::Config.refresh_env` | Absolute path to `~/.pwn/sessions/`. |
|
|
282
|
+
| `pwn_cron_path` | `PWN::Config.refresh_env` | Absolute path to `~/.pwn/cron/`. |
|
|
283
|
+
| `ai.<engine>.response_history` | `PWN::Config.refresh_env` | Rolling chat history for the active engine (reset on every reload). |
|
|
284
|
+
| `ai.session_id` | `PWN::AI::Agent::Loop.run` | Active `PWN::Sessions` id for the current turn (read by `sessions_current`, `mistakes_record`). |
|
|
285
|
+
|
|
286
|
+
---
|
|
287
|
+
|
|
288
|
+
## Redaction
|
|
289
|
+
|
|
290
|
+
`PWN::Config.redact_sensitive_artifacts` (and therefore `PWN::EnvRedacted`)
|
|
291
|
+
masks any key named: `admin_key`, `api_key`, `auth_client_secret`,
|
|
292
|
+
`bearer_token`, `client_secret`, `consumer_key`, `key`, `pass`, `password`,
|
|
293
|
+
`psk`, `refresh_token`, `secret_key`, `token`. Use those key names for any
|
|
294
|
+
custom secrets you add so they never leak into logs, transcripts, or the
|
|
295
|
+
agent system prompt.
|
|
296
|
+
|
|
297
|
+
---
|
|
47
298
|
|
|
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) |
|
|
299
|
+
## Related files under `~/.pwn/`
|
|
61
300
|
|
|
62
|
-
|
|
301
|
+
`pwn.yaml` is the only file you edit; everything else is machine-written
|
|
302
|
+
state. See **[Persistence](Persistence.md)** for the full map
|
|
303
|
+
(`memory.json`, `learning.jsonl`, `mistakes.json`, `metrics.json`,
|
|
304
|
+
`extrospection.json`, `sessions/`, `skills/`, `cron/`, `agents.yml`,
|
|
305
|
+
`swarm/`).
|
|
63
306
|
|
|
64
|
-
|
|
307
|
+
Multi-agent personas are **not** configured here — they live in
|
|
308
|
+
`~/.pwn/agents.yml` and are managed with `agent_spawn` / `agent_list`
|
|
309
|
+
(see **[Swarm](Swarm.md)**).
|
|
65
310
|
|
|
66
|
-
[← Home](Home.md)
|
|
311
|
+
[← Home](Home.md) · [Persistence](Persistence.md) · [pwn-ai Agent](pwn-ai-Agent.md) · [Extrospection](Extrospection.md)
|
data/documentation/Cron.md
CHANGED
|
@@ -37,10 +37,23 @@ 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. Because `
|
|
40
|
+
`pwn-ai` turn. Because `auto_introspect` and `auto_extrospect` are on, the run
|
|
41
41
|
also updates Learning/Metrics/Extrospection — so tomorrow's interactive
|
|
42
42
|
session already knows what changed overnight.
|
|
43
43
|
|
|
44
|
+
```ruby
|
|
45
|
+
cron_create(
|
|
46
|
+
name: 'memory_revalidate',
|
|
47
|
+
schedule: '0 4 * * 0',
|
|
48
|
+
ruby: 'PWN::AI::Agent::Extrospection.revalidate_memory'
|
|
49
|
+
)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Weekly, headless-browser fact-check of every `PWN::Memory` `:fact` containing
|
|
53
|
+
a CVE / version string / URL. Refuted entries get prefixed `[UNVERIFIED
|
|
54
|
+
yyyy-mm-dd]` so the injected MEMORY block stops calcifying into
|
|
55
|
+
confidently-wrong priors — see [Extrospection § revalidate_memory](Extrospection.md).
|
|
56
|
+
|
|
44
57
|
**See also:** [Sessions](Sessions.md) · [Extrospection](Extrospection.md) ·
|
|
45
58
|
[CLI Drivers](CLI-Drivers.md)
|
|
46
59
|
|
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 · 54 tools)
|
|
63
63
|
[source](diagrams/dot/agent-tool-registry.dot) · doc: [Agent Tool Registry](Agent-Tool-Registry.md)
|
|
64
64
|

|
|
65
65
|
|
|
@@ -17,22 +17,31 @@ like right now, and has it changed under me?"*
|
|
|
17
17
|
| `:repo` | `probe_repo` | HEAD · branch · dirty · origin |
|
|
18
18
|
| `:env` | `probe_env` | ruby / gem / bundler / PWN version |
|
|
19
19
|
| **`:rf`** | **`probe_rf`** | **RTL-SDR / HackRF presence · SoapySDR devices · GQRX socket (127.0.0.1:7356) · Flipper serial · `/dev/tty{USB,ACM}*` · band-plan count** |
|
|
20
|
+
| **`:web`** *(opt-in)* | **`probe_web`** | **Renders `web_anchors` via `PWN::Plugins::TransparentBrowser` (`:headless`) — HTTP status · final URL · `<title>` · meta[generator] · `Server` · SHA-256 of *rendered* DOM text · TLS cert fp / notAfter · optional screenshot → `~/.pwn/extrospection/web/<host>.png`** |
|
|
20
21
|
|
|
21
22
|
`RF_BINS = %w[rtl_sdr rtl_test rtl_433 hackrf_info gqrx dump1090 multimon-ng SoapySDRUtil]`
|
|
22
23
|
— these are also merged into `PROBE_BINS` so RF-toolchain drift shows up under
|
|
23
24
|
`toolchain.*` diff keys.
|
|
24
25
|
|
|
26
|
+
`DEFAULT_WEB_ANCHORS` = NVD CVE 2.0 API, Exploit-DB, upstream `pwn/version.rb`.
|
|
27
|
+
Override / extend via `PWN::Env[:ai][:agent][:extrospection][:web][:anchors]`; set
|
|
28
|
+
`allow_targets: true` to also fingerprint `PWN::Env[:targets]`. **`:web` is never
|
|
29
|
+
run by `auto_extrospect`** — a headless browser is ~1–3 s cold vs ~50 ms for
|
|
30
|
+
`probe_host`, so it's opt-in (`extro_snapshot(sections: %i[web])`).
|
|
31
|
+
|
|
25
32
|
## Verbs
|
|
26
33
|
|
|
27
34
|
| Tool | Does | Persists to |
|
|
28
35
|
|---|---|---|
|
|
29
|
-
| `extro_snapshot` | Fingerprint host/net/toolchain/repo/env/**rf
|
|
36
|
+
| `extro_snapshot` | Fingerprint host/net/toolchain/repo/env/**rf**/*web* → hash | `extrospection.json` (`snapshot` + rotates `previous`) |
|
|
30
37
|
| `extro_drift` | Diff live-vs-stored (or stored-vs-previous) | — returns `{changed, added, removed}` with dotted keys |
|
|
31
|
-
| `extro_observe` | Record a fact — `category:` one of `recon vuln intel target network env` **`rf`** `misc` | `observations[]` |
|
|
38
|
+
| `extro_observe` | Record a fact — `category:` one of `recon vuln intel target network env` **`rf` `web`** `misc` | `observations[]` |
|
|
32
39
|
| `extro_observations` | Query recorded facts by source/category/target/tag | — |
|
|
33
40
|
| `extro_intel` | Query NVD / CIRCL / Exploit-DB for keyword or CVE | optional `record: true` → `:intel` observations |
|
|
41
|
+
| **`extro_watch`** | **Render a URL headless, hash the *rendered* DOM, screenshot, diff vs prior** | `observations[]` (`category: :web`) |
|
|
42
|
+
| **`extro_verify`** | **Browser-backed self fact-check of a claim (`:cve` `:version` `:doc` `:generic`) → `:confirmed`/`:refuted`/`:unknown`** | `Mistakes.record` / `observe(:intel)` / `Learning.note_outcome` |
|
|
34
43
|
| `extro_correlate` | **Join** introspection ↔ extrospection | — actionable findings |
|
|
35
|
-
| `extro_stats` | snapshot age · observation count · drift counts · **rf_devices** | — |
|
|
44
|
+
| `extro_stats` | snapshot age · observation count · drift counts · **rf_devices** · **web_anchors** | — |
|
|
36
45
|
| `extro_reset` | Wipe snapshot + observations (new engagement) | — |
|
|
37
46
|
| `extro_auto_toggle` | Enable/disable auto-snapshot after every final answer | `PWN::Env[:ai][:agent][:auto_extrospect]` |
|
|
38
47
|
|
|
@@ -43,6 +52,9 @@ like right now, and has it changed under me?"*
|
|
|
43
52
|
(b) Learning failures on day X × host/net/repo drift on day X
|
|
44
53
|
(c) recorded :intel observations × installed component versions
|
|
45
54
|
(d) recorded :rf observations × missing SDR hardware / RF_BINS
|
|
55
|
+
(e) recorded :web DOM drift on target × Learning failures citing that host
|
|
56
|
+
(f) extro_verify :refuted claims × stale PWN::Memory :fact entries
|
|
57
|
+
(g) :intel obs whose feed anchor is × probe_web-unreachable → downgrade weight
|
|
46
58
|
```
|
|
47
59
|
|
|
48
60
|
Output tells the agent whether a failure was **its own fault** ("I called the
|
|
@@ -51,23 +63,77 @@ API wrong" → belongs in [Mistakes](Mistakes.md)) or **the world changed**
|
|
|
51
63
|
that distinction is written back into MEMORY so the next run doesn't waste
|
|
52
64
|
iterations rediscovering it.
|
|
53
65
|
|
|
66
|
+
## `extro_verify` — proactive fact-checking (the browser as a sense organ)
|
|
67
|
+
|
|
68
|
+
`probe_rf` gave Extrospection **ears**; `PWN::Plugins::TransparentBrowser` gives
|
|
69
|
+
it **eyes**. `extro_verify(claim:)` renders a canonical source *with JavaScript
|
|
70
|
+
executed* and returns a verdict:
|
|
71
|
+
|
|
72
|
+
| `kind:` | Canonical source (rendered headless) | Verdict logic |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `:cve` | `nvd.nist.gov/vuln/detail/<id>` + `cve.org/CVERecord?id=` | CVE exists? affected-product string overlaps claimed product/version? |
|
|
75
|
+
| `:version` | rubygems.org / PyPI / GitHub search | claimed "latest is X" vs scraped latest |
|
|
76
|
+
| `:doc` | the URL the model cited | 200? title/body contains ≥ 40 % of the quoted-snippet tokens (fuzzy)? |
|
|
77
|
+
| `:generic` | DuckDuckGo HTML (proxy-able, no API key) | ≥ 50 % token overlap in top result snippets |
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
┌── :refuted → Mistakes.record(tool:'assumption', …) → KNOWN MISTAKES block ∀ future runs
|
|
81
|
+
extro_verify ─────┼── :confirmed→ observe(category::intel, ttl:30d) → EXTROSPECTION block, freshness-bound
|
|
82
|
+
└── :unknown → Learning.note_outcome(tags:[needs_human])
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
This adds a **proactive** trigger to the negative-feedback loop: today
|
|
86
|
+
`Mistakes.record` fires only *reactively* (a tool blew up, or a human said
|
|
87
|
+
"that's wrong"). `extro_verify` lets the agent catch itself being wrong about
|
|
88
|
+
the world **before** a human does. `commit: false` returns the verdict without
|
|
89
|
+
side-effects.
|
|
90
|
+
|
|
91
|
+
### `revalidate_memory` — the browser as GC for `PWN::Memory`
|
|
92
|
+
|
|
93
|
+
`learning_consolidate` only dedupes/truncates; it never asks *"is this still
|
|
94
|
+
true?"*. `PWN::AI::Agent::Extrospection.revalidate_memory` walks every
|
|
95
|
+
`PWN::Memory` `:fact` containing a CVE / version string / URL, runs `verify()`
|
|
96
|
+
on it, and prefixes stale ones with `[UNVERIFIED yyyy-mm-dd]` so the injected
|
|
97
|
+
MEMORY block stops calcifying into confidently-wrong priors. Schedule it:
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
cron_create(name: 'memory_revalidate', schedule: '0 4 * * 0',
|
|
101
|
+
ruby: 'PWN::AI::Agent::Extrospection.revalidate_memory')
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Configuration
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
PWN::Env[:ai][:agent][:extrospection][:web] = {
|
|
108
|
+
anchors: ['https://target.acme/api/version', …], # else DEFAULT_WEB_ANCHORS
|
|
109
|
+
proxy: 'tor', # or 'http://127.0.0.1:8080' (Burp) — honoured by verify/watch/probe_web
|
|
110
|
+
max_anchors: 8,
|
|
111
|
+
per_page_timeout: 15,
|
|
112
|
+
screenshot: false, # → ~/.pwn/extrospection/web/<host>.png
|
|
113
|
+
allow_targets: false # OPSEC: also fingerprint PWN::Env[:targets] (active recon!)
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
|
|
54
118
|
## Typical engagement flow
|
|
55
119
|
|
|
56
120
|
```ruby
|
|
57
121
|
extro_reset(confirm: true) # clean slate for new scope
|
|
58
|
-
extro_snapshot # baseline (
|
|
122
|
+
extro_snapshot # baseline (six local sections; add sections:%i[web] for anchors)
|
|
59
123
|
# … recon …
|
|
60
124
|
extro_observe(source: 'nmap', target: '10.0.0.5',
|
|
61
125
|
category: 'recon', data: 'OpenSSH 8.2p1 Ubuntu')
|
|
62
126
|
extro_observe(source: 'gqrx', target: '433.920MHz',
|
|
63
127
|
category: 'rf', data: 'peak -34.2 dBFS bw=200k FSK — likely garage remote')
|
|
64
128
|
extro_intel(query: 'OpenSSH 8.2p1', record: true)
|
|
129
|
+
extro_watch(url: 'https://target.acme/api/version') # DOM-hash + screenshot; changed:true on next run
|
|
130
|
+
extro_verify(claim: 'CVE-2026-12345 affects OpenSSL 3.2.1') # → Mistakes/Memory/observe on verdict
|
|
65
131
|
# … days later, something breaks …
|
|
66
132
|
extro_drift # what moved?
|
|
67
133
|
extro_correlate # why did it break?
|
|
68
134
|
```
|
|
69
135
|
|
|
70
136
|
**See also:** [Skills, Memory & Learning](Skills-Memory-Learning.md) ·
|
|
71
|
-
[Mistakes](Mistakes.md) · [SDR](SDR.md) · [pwn-ai Agent](pwn-ai-Agent.md)
|
|
137
|
+
[Mistakes](Mistakes.md) · [SDR](SDR.md) · [Transparent Browser](Transparent-Browser.md) · [Cron](Cron.md) · [pwn-ai Agent](pwn-ai-Agent.md)
|
|
72
138
|
|
|
73
139
|
[← Home](Home.md)
|
data/documentation/Home.md
CHANGED
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
| | |
|
|
37
37
|
|---|---|
|
|
38
38
|
| [AI / LLM Integration](AI-Integration.md) | OpenAI · Anthropic · Grok (OAuth) · Gemini · Ollama |
|
|
39
|
-
| [Agent Tool Registry](Agent-Tool-Registry.md) | 10 toolsets ·
|
|
39
|
+
| [Agent Tool Registry](Agent-Tool-Registry.md) | 10 toolsets · 54 LLM-callable tools |
|
|
40
40
|
| [Memory · Skills · Learning](Skills-Memory-Learning.md) | Introspection — the self-improvement loop |
|
|
41
41
|
| [Mistakes](Mistakes.md) | **Negative feedback** — fingerprint failures · do-NOT-repeat · `[REPEATING]`/`[REGRESSED]` · inline self-correction |
|
|
42
|
-
| [Extrospection](Extrospection.md) | World-awareness — snapshot · drift · intel · correlate · **rf** |
|
|
42
|
+
| [Extrospection](Extrospection.md) | World-awareness — snapshot · drift · intel · **watch** · **verify** · correlate · **rf** · **web** |
|
|
43
43
|
| [Swarm (Multi-Agent)](Swarm.md) | Personas · ask · debate · broadcast · shared bus |
|
|
44
44
|
| [Sessions](Sessions.md) | Transcript persistence + reflection |
|
|
45
45
|
| [Cron](Cron.md) | Scheduled autonomous jobs |
|
|
@@ -27,7 +27,7 @@ hardware).
|
|
|
27
27
|
| Module | Role |
|
|
28
28
|
|---|---|
|
|
29
29
|
| `Loop` | plan → dispatch tool_calls → observe → repeat until final answer |
|
|
30
|
-
| `Registry` | JSON-Schema function definitions grouped into 10 **toolsets** ·
|
|
30
|
+
| `Registry` | JSON-Schema function definitions grouped into 10 **toolsets** · 54 tools |
|
|
31
31
|
| `Dispatch` / `Result` | execute a tool, capture stdout/value/error/duration |
|
|
32
32
|
| `PromptBuilder` | inject MEMORY / SKILLS / LEARNING / **KNOWN MISTAKES + FIXES** / METRICS / EXTROSPECTION blocks |
|
|
33
33
|
| `Metrics` · `Learning` | **introspection** — how well am I doing? |
|
data/documentation/Mistakes.md
CHANGED
|
@@ -42,7 +42,7 @@ PromptBuilder <-------------------- Mistakes.to_context (KNOWN MISTAKES + KN
|
|
|
42
42
|
model --(tool call)---------------> mistakes_record / mistakes_resolve
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
##
|
|
45
|
+
## Five ingest paths — nothing slips through
|
|
46
46
|
|
|
47
47
|
| Source | Trigger | What is recorded |
|
|
48
48
|
|---|---|---|
|
|
@@ -50,6 +50,7 @@ model --(tool call)---------------> mistakes_record / mistakes_resolve
|
|
|
50
50
|
| `:loop` | iteration budget exhausted with no final answer | *automatic* — `Loop.run` epilogue |
|
|
51
51
|
| `:user_correction` | next user message matches `CORRECTION_RX` (*"no that's wrong"*, *"still broken"*, *"try again"*, …) | `check_user_correction` — also flips the previous `Learning` outcome to `success:false` |
|
|
52
52
|
| `:model` | the model itself calls `mistakes_record` | wrong assumption, wrong file, hallucinated API — failures that are **not** dispatch errors |
|
|
53
|
+
| **`:model` (proactive)** | **`extro_verify(claim:)` returns `:refuted`** | **`Mistakes.record(tool:'assumption', error:'REFUTED …: <claim>')` — the browser caught the model being wrong about the world *before* a human did** |
|
|
53
54
|
|
|
54
55
|
## Tools
|
|
55
56
|
|