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
data/lib/pwn/ai/agent/gqrx.rb
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module PWN
|
|
4
4
|
module AI
|
|
5
5
|
module Agent
|
|
6
|
-
# This module is an AI agent designed to analyze signal data captured by a software-defined-radio using GQRX. It uses the PWN::AI::Agent::
|
|
6
|
+
# This module is an AI agent designed to analyze signal data captured by a software-defined-radio using GQRX. It uses the PWN::AI::Agent::Reflect.on method to analyze the signal data and provide insights based on the location where the data was captured. The agent can determine if the frequency is licensed or unlicensed based on FCC records and provide relevant information about the transmission. This module is useful for security professionals, researchers, and hobbyists interested in analyzing radio signals and understanding their context.
|
|
7
7
|
module GQRX
|
|
8
8
|
# Supported Method Parameters::
|
|
9
9
|
# ai_analysis = PWN::AI::Agent::GQRX.analyze(
|
|
@@ -20,7 +20,7 @@ module PWN
|
|
|
20
20
|
|
|
21
21
|
system_role_content = "Analyze signal data captured by a software-defined-radio using GQRX at the following location: #{location}. Respond with just FCC information about the transmission if available. If the frequency is unlicensed or not found in FCC records, state that clearly. Be clear and concise in your analysis."
|
|
22
22
|
|
|
23
|
-
PWN::AI::Agent::
|
|
23
|
+
PWN::AI::Agent::Reflect.on(
|
|
24
24
|
system_role_content: system_role_content,
|
|
25
25
|
request: request,
|
|
26
26
|
suppress_pii_warning: true
|
|
@@ -16,7 +16,7 @@ module PWN
|
|
|
16
16
|
#
|
|
17
17
|
# Data flows:
|
|
18
18
|
# Loop.run --(tool telemetry)--> Metrics.record
|
|
19
|
-
# Loop.run --(final answer)----> Learning.
|
|
19
|
+
# Loop.run --(final answer)----> Learning.auto_introspect (opt-in)
|
|
20
20
|
# model --(tool calls)------> learning_note_outcome / _distill_skill
|
|
21
21
|
# PromptBuilder <----------------- Learning.to_context + Metrics.to_context
|
|
22
22
|
#
|
|
@@ -164,9 +164,9 @@ module PWN
|
|
|
164
164
|
# dry_run: 'optional - when true, do not write to Memory/Skills (default false)'
|
|
165
165
|
# )
|
|
166
166
|
#
|
|
167
|
-
# Uses PWN::AI::Agent::
|
|
167
|
+
# Uses PWN::AI::Agent::Reflect (when available) to LLM-summarise the
|
|
168
168
|
# session into structured lessons. Falls back to a heuristic
|
|
169
|
-
# extractor when
|
|
169
|
+
# extractor when module_reflection is disabled so learning never stops.
|
|
170
170
|
|
|
171
171
|
public_class_method def self.reflect(opts = {})
|
|
172
172
|
session_id = opts[:session_id]
|
|
@@ -193,19 +193,19 @@ module PWN
|
|
|
193
193
|
end
|
|
194
194
|
|
|
195
195
|
# Supported Method Parameters::
|
|
196
|
-
# PWN::AI::Agent::Learning.
|
|
196
|
+
# PWN::AI::Agent::Learning.auto_introspect(
|
|
197
197
|
# session_id: 'required - id of the just-completed session',
|
|
198
198
|
# request: 'optional - original user request (for outcome logging)',
|
|
199
199
|
# final: 'optional - final assistant answer (for outcome logging)'
|
|
200
200
|
# )
|
|
201
201
|
#
|
|
202
|
-
# Called by Loop.run when PWN::Env[:ai][:agent][:
|
|
202
|
+
# Called by Loop.run when PWN::Env[:ai][:agent][:auto_introspect] is
|
|
203
203
|
# truthy. Never raises — learning must not break the primary loop.
|
|
204
204
|
|
|
205
|
-
public_class_method def self.
|
|
205
|
+
public_class_method def self.auto_introspect(opts = {})
|
|
206
206
|
session_id = opts[:session_id]
|
|
207
207
|
return unless session_id
|
|
208
|
-
return unless
|
|
208
|
+
return unless auto_introspect_enabled?
|
|
209
209
|
|
|
210
210
|
ok = infer_success(session_id: session_id, final: opts[:final])
|
|
211
211
|
note_outcome(
|
|
@@ -218,7 +218,7 @@ module PWN
|
|
|
218
218
|
reflect(session_id: session_id)
|
|
219
219
|
Extrospection.auto_extrospect(session_id: session_id) if defined?(Extrospection)
|
|
220
220
|
rescue StandardError => e
|
|
221
|
-
warn "[pwn-ai/learning]
|
|
221
|
+
warn "[pwn-ai/learning] auto_introspect swallowed: #{e.class}: #{e.message}"
|
|
222
222
|
nil
|
|
223
223
|
end
|
|
224
224
|
|
|
@@ -301,10 +301,10 @@ module PWN
|
|
|
301
301
|
# privates
|
|
302
302
|
# -------------------------------------------------------------
|
|
303
303
|
|
|
304
|
-
private_class_method def self.
|
|
304
|
+
private_class_method def self.auto_introspect_enabled?
|
|
305
305
|
return false unless defined?(PWN::Env) && PWN::Env.is_a?(Hash)
|
|
306
306
|
|
|
307
|
-
PWN::Env.dig(:ai, :agent, :
|
|
307
|
+
PWN::Env.dig(:ai, :agent, :auto_introspect) ? true : false
|
|
308
308
|
rescue StandardError
|
|
309
309
|
false
|
|
310
310
|
end
|
|
@@ -314,7 +314,7 @@ module PWN
|
|
|
314
314
|
# Derive a success signal stronger than "final answer non-empty":
|
|
315
315
|
# look at the tool-failure ratio inside the just-completed turn AND
|
|
316
316
|
# scan the final text for self-reported failure language. Without
|
|
317
|
-
# this,
|
|
317
|
+
# this, auto_introspect logs ~100 % success and the negative-feedback
|
|
318
318
|
# side of the learning loop never fires.
|
|
319
319
|
private_class_method def self.infer_success(opts = {})
|
|
320
320
|
final = opts[:final].to_s
|
|
@@ -353,11 +353,11 @@ module PWN
|
|
|
353
353
|
|
|
354
354
|
private_class_method def self.introspective_lessons(opts = {})
|
|
355
355
|
transcript = opts[:transcript] || []
|
|
356
|
-
return [] unless defined?(PWN::AI::Agent::
|
|
357
|
-
return [] unless defined?(PWN::Env) && PWN::Env.is_a?(Hash) && PWN::Env.dig(:ai, :
|
|
356
|
+
return [] unless defined?(PWN::AI::Agent::Reflect)
|
|
357
|
+
return [] unless defined?(PWN::Env) && PWN::Env.is_a?(Hash) && PWN::Env.dig(:ai, :module_reflection)
|
|
358
358
|
|
|
359
359
|
req = "Analyse this pwn-ai session transcript and emit up to 5 durable, generalizable lessons (one per line, no numbering, imperative voice) that would make future runs faster or more reliable. Focus on tool selection, error recovery, and target-agnostic technique. Ignore trivia.\n\nTRANSCRIPT:\n#{transcript_text(transcript: transcript)}"
|
|
360
|
-
resp = PWN::AI::Agent::
|
|
360
|
+
resp = PWN::AI::Agent::Reflect.on(request: req, suppress_pii_warning: true)
|
|
361
361
|
resp.to_s.lines.map(&:strip).reject(&:empty?).first(5)
|
|
362
362
|
rescue StandardError
|
|
363
363
|
[]
|
|
@@ -420,7 +420,7 @@ module PWN
|
|
|
420
420
|
PWN::AI::Agent::Learning.note_outcome(task: 'nmap sweep 10.0.0.0/24', success: true, details: '12 hosts up')
|
|
421
421
|
PWN::AI::Agent::Learning.outcomes(limit: 20, success: false)
|
|
422
422
|
PWN::AI::Agent::Learning.reflect(session_id: sid) # LLM or heuristic → PWN::Memory
|
|
423
|
-
PWN::AI::Agent::Learning.
|
|
423
|
+
PWN::AI::Agent::Learning.auto_introspect(session_id: sid, request: req, final: text)
|
|
424
424
|
PWN::AI::Agent::Learning.distill_skill(name: 'quick_recon', session_id: sid)
|
|
425
425
|
PWN::AI::Agent::Learning.consolidate(max_entries: 200) # dedupe + prune Memory
|
|
426
426
|
PWN::AI::Agent::Learning.to_context(limit: 5) # injected by PromptBuilder
|
|
@@ -428,7 +428,7 @@ module PWN
|
|
|
428
428
|
PWN::AI::Agent::Learning.reset
|
|
429
429
|
|
|
430
430
|
Enable end-of-run auto-learning with:
|
|
431
|
-
PWN::Env[:ai][:agent][:
|
|
431
|
+
PWN::Env[:ai][:agent][:auto_introspect] = true
|
|
432
432
|
|
|
433
433
|
#{self}.authors
|
|
434
434
|
USAGE
|
data/lib/pwn/ai/agent/loop.rb
CHANGED
|
@@ -241,7 +241,7 @@ module PWN
|
|
|
241
241
|
if calls.empty?
|
|
242
242
|
text = msg[:content].to_s
|
|
243
243
|
append_session(session_id: session_id, role: 'assistant', content: text)
|
|
244
|
-
Learning.
|
|
244
|
+
Learning.auto_introspect(session_id: session_id, request: request, final: text) if defined?(Learning)
|
|
245
245
|
return text
|
|
246
246
|
end
|
|
247
247
|
|
|
@@ -5,14 +5,14 @@ require 'json'
|
|
|
5
5
|
module PWN
|
|
6
6
|
module AI
|
|
7
7
|
module Agent
|
|
8
|
-
# PWN::AI::Agent::
|
|
8
|
+
# PWN::AI::Agent::Reflect is the inward-facing counterpart to
|
|
9
9
|
# PWN::AI::Agent::Extrospection. Where Extrospection looks OUTWARD at
|
|
10
10
|
# the world the agent operates in (host state, toolchain, network,
|
|
11
|
-
# threat-intel),
|
|
12
|
-
#
|
|
13
|
-
#
|
|
11
|
+
# threat-intel), Reflect looks INWARD - it lets pwn hand a request to
|
|
12
|
+
# the active AI engine and reflect on its own artifacts, transcripts,
|
|
13
|
+
# findings, code, or decisions.
|
|
14
14
|
#
|
|
15
|
-
# This module is gated by `PWN::Env[:ai][:
|
|
15
|
+
# This module is gated by `PWN::Env[:ai][:module_reflection]` so that
|
|
16
16
|
# potentially-sensitive local data is never shipped to a remote LLM
|
|
17
17
|
# unless the operator has explicitly opted in via pwn-vault / config.
|
|
18
18
|
#
|
|
@@ -21,16 +21,16 @@ module PWN
|
|
|
21
21
|
# through when it wants an LLM opinion on locally-produced data, and
|
|
22
22
|
# it is also what PWN::AI::Agent::Learning.reflect uses to distill
|
|
23
23
|
# session transcripts into durable PWN::Memory lessons.
|
|
24
|
-
module
|
|
24
|
+
module Reflect
|
|
25
25
|
# Supported Method Parameters::
|
|
26
|
-
# response = PWN::AI::Agent::
|
|
26
|
+
# response = PWN::AI::Agent::Reflect.on(
|
|
27
27
|
# request: 'required - String - What you want the AI to reflect on',
|
|
28
28
|
# system_role_content: 'optional - context to set up the model behavior for reflection',
|
|
29
29
|
# spinner: 'optional - Boolean - Display spinner during operation (default: false)',
|
|
30
30
|
# suppress_pii_warning: 'optional - Boolean - Suppress PII Warnings (default: false)'
|
|
31
31
|
# )
|
|
32
32
|
|
|
33
|
-
public_class_method def self.
|
|
33
|
+
public_class_method def self.on(opts = {})
|
|
34
34
|
request = opts[:request]
|
|
35
35
|
raise 'ERROR: request must be provided' if request.nil?
|
|
36
36
|
|
|
@@ -42,14 +42,14 @@ module PWN
|
|
|
42
42
|
|
|
43
43
|
response = nil
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
ai_module_reflection = PWN::Env[:ai][:module_reflection]
|
|
46
46
|
|
|
47
|
-
if
|
|
47
|
+
if ai_module_reflection && request.length.positive?
|
|
48
48
|
engine = PWN::Env[:ai][:active].to_s.downcase.to_sym
|
|
49
49
|
valid_ai_engines = PWN::AI.help.reject { |e| e.downcase == :agent }.map(&:downcase)
|
|
50
50
|
raise "ERROR: Unsupported AI engine. Supported engines are: #{valid_ai_engines}" unless valid_ai_engines.include?(engine)
|
|
51
51
|
|
|
52
|
-
warn "AI
|
|
52
|
+
warn "AI Reflection is enabled. Ensure #{engine} has been authorized for use and/or requests are sanitized properly." unless suppress_pii_warning
|
|
53
53
|
response = PWN::AI::Agent::Loop.run(
|
|
54
54
|
request: request.chomp,
|
|
55
55
|
system_role_content: system_role_content,
|
|
@@ -75,7 +75,7 @@ module PWN
|
|
|
75
75
|
|
|
76
76
|
public_class_method def self.help
|
|
77
77
|
puts "USAGE:
|
|
78
|
-
#{self}.
|
|
78
|
+
#{self}.on(
|
|
79
79
|
request: 'required - String - What you want the AI to reflect on',
|
|
80
80
|
system_role_content: 'optional - context to set up the model behavior for reflection',
|
|
81
81
|
spinner: 'optional - Boolean - Display spinner during operation (default: false)',
|
data/lib/pwn/ai/agent/sast.rb
CHANGED
|
@@ -16,7 +16,7 @@ module PWN
|
|
|
16
16
|
|
|
17
17
|
system_role_content = 'Your sole purpose is to analyze source code snippets and generate an Exploit Prediction Scoring System (EPSS) score between 0% - 100%. Just generate a score unless score is >= 75% in which a PoC and code fix should also be included.'
|
|
18
18
|
|
|
19
|
-
PWN::AI::Agent::
|
|
19
|
+
PWN::AI::Agent::Reflect.on(
|
|
20
20
|
system_role_content: system_role_content,
|
|
21
21
|
request: request,
|
|
22
22
|
suppress_pii_warning: true
|
|
@@ -29,7 +29,7 @@ PWN::AI::Agent::Registry.register(
|
|
|
29
29
|
type: 'object',
|
|
30
30
|
properties: {
|
|
31
31
|
persist: { type: 'boolean', default: true, description: 'Write to disk & rotate previous baseline.' },
|
|
32
|
-
sections: { type: 'array', items: { type: 'string', enum: %w[host net toolchain repo env rf web] }, description: 'Subset of probes
|
|
32
|
+
sections: { type: 'array', items: { type: 'string', enum: %w[host net toolchain repo env rf web osint serial telecomm packet vision voice] }, description: 'Subset of probes (default all except web). auto_extrospect uses host/repo/env only; toolchain never launches GUI bins.' }
|
|
33
33
|
},
|
|
34
34
|
required: []
|
|
35
35
|
}
|
|
@@ -86,7 +86,7 @@ PWN::AI::Agent::Registry.register(
|
|
|
86
86
|
properties: {
|
|
87
87
|
source: { type: 'string', description: 'Where it came from (nmap, shodan, burp, cve, human, ...).' },
|
|
88
88
|
data: { type: 'string', description: 'The observation itself.' },
|
|
89
|
-
category: { type: 'string', enum: %w[recon vuln intel target network env rf web misc], default: 'misc' },
|
|
89
|
+
category: { type: 'string', enum: %w[recon vuln intel target network env rf web osint serial telecomm packet vision voice misc], default: 'misc' },
|
|
90
90
|
target: { type: 'string', description: 'Host / IP / URL / asset the observation is about.' },
|
|
91
91
|
tags: { type: 'array', items: { type: 'string' } },
|
|
92
92
|
ttl: { type: 'integer', description: 'Seconds until stale (omit = forever).' }
|
|
@@ -256,12 +256,13 @@ PWN::AI::Agent::Registry.register(
|
|
|
256
256
|
toolset: 'extrospection',
|
|
257
257
|
schema: {
|
|
258
258
|
name: 'extro_auto_toggle',
|
|
259
|
-
description: 'Enable/disable
|
|
260
|
-
'(PWN::Env[:ai][:agent][:auto_extrospect]).
|
|
261
|
-
'Learning.
|
|
262
|
-
'
|
|
263
|
-
'
|
|
264
|
-
'
|
|
259
|
+
description: 'Enable/disable OPTIONAL ambient baseline after every ' \
|
|
260
|
+
'final answer (PWN::Env[:ai][:agent][:auto_extrospect]). ' \
|
|
261
|
+
'When on, Learning.auto_introspect runs Extrospection.' \
|
|
262
|
+
'auto_extrospect with AUTO_SECTIONS (host/repo/env only) — ' \
|
|
263
|
+
'never toolchain/rf/web, never launches burpsuite/zaproxy/' \
|
|
264
|
+
'msfconsole/gqrx. Primary sensing stays on-demand (intel/' \
|
|
265
|
+
'verify/watch/observe). Omit `enabled` to only query.',
|
|
265
266
|
parameters: {
|
|
266
267
|
type: 'object',
|
|
267
268
|
properties: {
|
|
@@ -363,3 +364,305 @@ PWN::AI::Agent::Registry.register(
|
|
|
363
364
|
)
|
|
364
365
|
}
|
|
365
366
|
)
|
|
367
|
+
|
|
368
|
+
PWN::AI::Agent::Registry.register(
|
|
369
|
+
name: 'extro_rf_tune',
|
|
370
|
+
toolset: 'extrospection',
|
|
371
|
+
schema: {
|
|
372
|
+
name: 'extro_rf_tune',
|
|
373
|
+
description: 'RF sense organ — the radio analogue of extro_watch / ' \
|
|
374
|
+
'extro_verify. Tunes a *running* GQRX instance (remote ' \
|
|
375
|
+
'control, never launches the GUI), demodulates, measures ' \
|
|
376
|
+
'signal strength, and samples RDS (PI / PS / RadioText) so ' \
|
|
377
|
+
'questions like "what\'s playing on 101.1 FM?" get a live ' \
|
|
378
|
+
'answer. Auto-detects band plan (fm_radio → WFM_ST + RDS). ' \
|
|
379
|
+
'Returns {ok:, freq:, hz:, strength_dbfs:, demodulator_mode:, ' \
|
|
380
|
+
'rds:{pi,ps_name,radiotext,station}, now_playing:, station:, ' \
|
|
381
|
+
'summary:}. On success also observe(category: :rf) so the ' \
|
|
382
|
+
'EXTROSPECTION prompt block and extro_correlate see it. ' \
|
|
383
|
+
'Requires GQRX remote control listening (default 7356) + ' \
|
|
384
|
+
'an SDR attached; fails fast with actionable advice otherwise.',
|
|
385
|
+
parameters: {
|
|
386
|
+
type: 'object',
|
|
387
|
+
properties: {
|
|
388
|
+
freq: {
|
|
389
|
+
type: 'string',
|
|
390
|
+
description: 'Frequency to tune. Free-form: "101.1", "101.1 FM", ' \
|
|
391
|
+
'"101.1 MHz", "101.100.000", "101100000", "433.92", …'
|
|
392
|
+
},
|
|
393
|
+
host: { type: 'string', description: 'GQRX remote-control host (default 127.0.0.1).' },
|
|
394
|
+
port: { type: 'integer', description: 'GQRX remote-control port (default 7356).' },
|
|
395
|
+
settle_secs: {
|
|
396
|
+
type: 'number',
|
|
397
|
+
description: 'Seconds to sample RDS after tuning (default 8, max 30).'
|
|
398
|
+
},
|
|
399
|
+
rds: {
|
|
400
|
+
type: 'boolean',
|
|
401
|
+
description: 'Force RDS sampling on/off. Default: auto (on for FM ' \
|
|
402
|
+
'broadcast / band-plans with decoder: :rds).'
|
|
403
|
+
},
|
|
404
|
+
demodulator_mode: {
|
|
405
|
+
type: 'string',
|
|
406
|
+
description: 'Override demod (WFM_ST, WFM, FM, AM, USB, LSB, …). ' \
|
|
407
|
+
'Default from band-plan / FM range heuristic.'
|
|
408
|
+
},
|
|
409
|
+
bandwidth: {
|
|
410
|
+
type: 'string',
|
|
411
|
+
description: 'Passband e.g. "200.000" (Hz, PWN dotted form). Default from band-plan.'
|
|
412
|
+
},
|
|
413
|
+
record: {
|
|
414
|
+
type: 'boolean',
|
|
415
|
+
default: true,
|
|
416
|
+
description: 'Also observe(category: :rf) so it hits EXTROSPECTION (default true).'
|
|
417
|
+
},
|
|
418
|
+
ttl: {
|
|
419
|
+
type: 'integer',
|
|
420
|
+
description: 'Observation TTL seconds (default 300 — radio content is ephemeral).'
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
required: %w[freq]
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
check: -> { defined?(PWN::AI::Agent::Extrospection) && PWN::AI::Agent::Extrospection.respond_to?(:rf_tune) },
|
|
427
|
+
handler: lambda { |args|
|
|
428
|
+
o = { freq: args[:freq] }
|
|
429
|
+
o[:host] = args[:host] if args[:host]
|
|
430
|
+
o[:port] = args[:port] if args[:port]
|
|
431
|
+
o[:settle_secs] = args[:settle_secs] if args[:settle_secs]
|
|
432
|
+
o[:rds] = args[:rds] if args.key?(:rds)
|
|
433
|
+
o[:demodulator_mode] = args[:demodulator_mode] if args[:demodulator_mode]
|
|
434
|
+
o[:bandwidth] = args[:bandwidth] if args[:bandwidth]
|
|
435
|
+
o[:record] = args[:record] if args.key?(:record)
|
|
436
|
+
o[:ttl] = args[:ttl] if args[:ttl]
|
|
437
|
+
PWN::AI::Agent::Extrospection.rf_tune(o)
|
|
438
|
+
}
|
|
439
|
+
)
|
|
440
|
+
|
|
441
|
+
PWN::AI::Agent::Registry.register(
|
|
442
|
+
name: 'extro_osint',
|
|
443
|
+
toolset: 'extrospection',
|
|
444
|
+
schema: {
|
|
445
|
+
name: 'extro_osint',
|
|
446
|
+
description: 'OSINT sense organ — aggregates public open APIs (also drawn ' \
|
|
447
|
+
'from public-api-lists) for reverse phone, IP/geo/ASN/BGP + ' \
|
|
448
|
+
'threat reputation (ipapi.is/iplocate/ipwho.is/AbuseIPDB/' \
|
|
449
|
+
'GreyNoise), DNS/WHOIS/RDAP, CT (crt.sh + Cert Spotter), FCC ' \
|
|
450
|
+
'ID, patent, VIN (NHTSA), MAC OUI, ham callsign (Callook), ' \
|
|
451
|
+
'person / missing-person (Wikipedia/Wikidata/OpenSanctions + ' \
|
|
452
|
+
'NamUs/FBI/Charley), username pivots (GitHub/GitLab/Reddit), ' \
|
|
453
|
+
'name demographics (Agify/Genderize/Nationalize), Shodan/' \
|
|
454
|
+
'Hunter/VirusTotal/HIBP/SecurityTrails (keyed), Wayback, ' \
|
|
455
|
+
'OTX/URLHaus/ThreatFox/urlscan, HackerTarget, openFDA, NPPES, ' \
|
|
456
|
+
'Nominatim, OpenCorporates, CourtListener, SEC EDGAR, Federal ' \
|
|
457
|
+
'Register, UK Police, EPSS + CISA KEV, Microlink unfurl, ' \
|
|
458
|
+
'universities, and vital-records plans. kind auto-detects. ' \
|
|
459
|
+
'Best-effort per-feed; unreachable → error hashes. ' \
|
|
460
|
+
'observe(category: :osint) by default.',
|
|
461
|
+
parameters: {
|
|
462
|
+
type: 'object',
|
|
463
|
+
properties: {
|
|
464
|
+
query: { type: 'string', description: 'Phone, IP, domain, email, URL, person name, company, CIK, FCC ID, patent number, username, address, …' },
|
|
465
|
+
kind: {
|
|
466
|
+
type: 'string',
|
|
467
|
+
enum: %w[auto ip geo dns whois rdap crtsh bgp shodan hunter phone fcc_id patent person username github wayback email domain url company cik openfda vital_records threat vin mac callsign npi cve],
|
|
468
|
+
description: 'Force an OSINT kind. Omit / auto to detect from query shape.'
|
|
469
|
+
},
|
|
470
|
+
feeds: {
|
|
471
|
+
type: 'array',
|
|
472
|
+
items: { type: 'string', enum: %w[ip geo dns whois rdap crtsh bgpview shodan hunter phone fcc_id patent person username github wayback otx urlhaus threatfox urlscan hackertarget openfda nominatim opencorporates courtlistener sec_edgar vital_records ipapi_is iplocate ipwhois abuseipdb virustotal greynoise certspotter epss cisa_kev nhtsa nppes federal_register uk_police callook mac_vendor universities microlink agify genderize nationalize haveibeenpwned securitytrails] }
|
|
473
|
+
},
|
|
474
|
+
limit: { type: 'integer', default: 5 },
|
|
475
|
+
record: { type: 'boolean', default: true },
|
|
476
|
+
ttl: { type: 'integer', description: 'Observation TTL seconds (default 86400).' }
|
|
477
|
+
},
|
|
478
|
+
required: %w[query]
|
|
479
|
+
}
|
|
480
|
+
},
|
|
481
|
+
check: -> { defined?(PWN::AI::Agent::Extrospection) && PWN::AI::Agent::Extrospection.respond_to?(:osint) },
|
|
482
|
+
handler: lambda { |args|
|
|
483
|
+
o = { query: args[:query] }
|
|
484
|
+
o[:kind] = args[:kind] if args[:kind]
|
|
485
|
+
o[:feeds] = args[:feeds] if args[:feeds]
|
|
486
|
+
o[:limit] = args[:limit] if args[:limit]
|
|
487
|
+
o[:record] = args[:record] if args.key?(:record)
|
|
488
|
+
o[:ttl] = args[:ttl] if args[:ttl]
|
|
489
|
+
PWN::AI::Agent::Extrospection.osint(o)
|
|
490
|
+
}
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
PWN::AI::Agent::Registry.register(
|
|
494
|
+
name: 'extro_serial',
|
|
495
|
+
toolset: 'extrospection',
|
|
496
|
+
schema: {
|
|
497
|
+
name: 'extro_serial',
|
|
498
|
+
description: 'Serial sense organ — open a USB-UART / modem / Arduino / ' \
|
|
499
|
+
'RFID reader (PWN::Plugins::Serial), optional payload write ' \
|
|
500
|
+
'(AT commands, hex bytes), drain response, disconnect. ' \
|
|
501
|
+
'Returns text + hex + line-state + modem-params + device ' \
|
|
502
|
+
'inventory. Never holds the port across calls. ' \
|
|
503
|
+
'observe(category: :serial).',
|
|
504
|
+
parameters: {
|
|
505
|
+
type: 'object',
|
|
506
|
+
properties: {
|
|
507
|
+
block_dev: { type: 'string', description: 'Device path (default first /dev/ttyUSB* or /dev/ttyACM*).' },
|
|
508
|
+
baud: { type: 'integer', description: 'Baud rate (default 9600).' },
|
|
509
|
+
payload: { type: 'string', description: 'String payload to write (e.g. "ATI\\r"). For raw bytes use pwn_eval.' },
|
|
510
|
+
settle_secs: { type: 'number', description: 'Seconds to read after write (default 1.5, max 30).' },
|
|
511
|
+
data_bits: { type: 'integer', default: 8 },
|
|
512
|
+
stop_bits: { type: 'integer', default: 1 },
|
|
513
|
+
parity: { type: 'string', enum: %w[none even odd mark space], default: 'none' },
|
|
514
|
+
record: { type: 'boolean', default: true },
|
|
515
|
+
ttl: { type: 'integer' }
|
|
516
|
+
},
|
|
517
|
+
required: []
|
|
518
|
+
}
|
|
519
|
+
},
|
|
520
|
+
check: -> { defined?(PWN::AI::Agent::Extrospection) && PWN::AI::Agent::Extrospection.respond_to?(:serial_sense) },
|
|
521
|
+
handler: lambda { |args|
|
|
522
|
+
o = {}
|
|
523
|
+
o[:block_dev] = args[:block_dev] if args[:block_dev]
|
|
524
|
+
o[:baud] = args[:baud] if args[:baud]
|
|
525
|
+
o[:payload] = args[:payload] if args[:payload]
|
|
526
|
+
o[:settle_secs] = args[:settle_secs] if args[:settle_secs]
|
|
527
|
+
o[:data_bits] = args[:data_bits] if args[:data_bits]
|
|
528
|
+
o[:stop_bits] = args[:stop_bits] if args[:stop_bits]
|
|
529
|
+
o[:parity] = args[:parity] if args[:parity]
|
|
530
|
+
o[:record] = args[:record] if args.key?(:record)
|
|
531
|
+
o[:ttl] = args[:ttl] if args[:ttl]
|
|
532
|
+
PWN::AI::Agent::Extrospection.serial_sense(o)
|
|
533
|
+
}
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
PWN::AI::Agent::Registry.register(
|
|
537
|
+
name: 'extro_telecomm',
|
|
538
|
+
toolset: 'extrospection',
|
|
539
|
+
schema: {
|
|
540
|
+
name: 'extro_telecomm',
|
|
541
|
+
description: 'Telecomm sense organ (SIP / VoIP / PSTN) — senses a running ' \
|
|
542
|
+
'BareSIP instance over HTTP control (never launches it). ' \
|
|
543
|
+
'Actions: :inventory / :status / :dial / :hangup. Dial is ' \
|
|
544
|
+
'OPSEC-sensitive (real call). observe(category: :telecomm).',
|
|
545
|
+
parameters: {
|
|
546
|
+
type: 'object',
|
|
547
|
+
properties: {
|
|
548
|
+
action: { type: 'string', enum: %w[inventory status dial hangup], default: 'inventory' },
|
|
549
|
+
target: { type: 'string', description: 'SIP URI or E.164 number for action:dial (e.g. sip:alice@example.com or +13125551212).' },
|
|
550
|
+
host: { type: 'string', description: 'BareSIP HTTP host (default 127.0.0.1).' },
|
|
551
|
+
port: { type: 'integer', description: 'BareSIP HTTP port (default 8000).' },
|
|
552
|
+
record: { type: 'boolean', default: true },
|
|
553
|
+
ttl: { type: 'integer' }
|
|
554
|
+
},
|
|
555
|
+
required: []
|
|
556
|
+
}
|
|
557
|
+
},
|
|
558
|
+
check: -> { defined?(PWN::AI::Agent::Extrospection) && PWN::AI::Agent::Extrospection.respond_to?(:telecomm) },
|
|
559
|
+
handler: lambda { |args|
|
|
560
|
+
o = {}
|
|
561
|
+
o[:action] = args[:action] if args[:action]
|
|
562
|
+
o[:target] = args[:target] if args[:target]
|
|
563
|
+
o[:host] = args[:host] if args[:host]
|
|
564
|
+
o[:port] = args[:port] if args[:port]
|
|
565
|
+
o[:record] = args[:record] if args.key?(:record)
|
|
566
|
+
o[:ttl] = args[:ttl] if args[:ttl]
|
|
567
|
+
PWN::AI::Agent::Extrospection.telecomm(o)
|
|
568
|
+
}
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
PWN::AI::Agent::Registry.register(
|
|
572
|
+
name: 'extro_packet',
|
|
573
|
+
toolset: 'extrospection',
|
|
574
|
+
schema: {
|
|
575
|
+
name: 'extro_packet',
|
|
576
|
+
description: 'Packet sense organ — L2/L3 capture & pcap summarisation via ' \
|
|
577
|
+
'tshark/tcpdump + PWN::Plugins::Packet. Actions: :inventory, ' \
|
|
578
|
+
':capture (bounded count/timeout → ~/.pwn/extrospection/packet/*.pcap), ' \
|
|
579
|
+
':summarize_pcap. observe(category: :packet).',
|
|
580
|
+
parameters: {
|
|
581
|
+
type: 'object',
|
|
582
|
+
properties: {
|
|
583
|
+
action: { type: 'string', enum: %w[inventory capture summarize_pcap], default: 'inventory' },
|
|
584
|
+
iface: { type: 'string', description: 'Capture interface (default first non-lo or any).' },
|
|
585
|
+
filter: { type: 'string', description: 'BPF filter e.g. "tcp port 443".' },
|
|
586
|
+
count: { type: 'integer', description: 'Packets to capture (default 20, max 200).' },
|
|
587
|
+
timeout: { type: 'integer', description: 'Capture seconds (default 5, max 60).' },
|
|
588
|
+
path: { type: 'string', description: 'Existing pcap path for action:summarize_pcap.' },
|
|
589
|
+
record: { type: 'boolean', default: true },
|
|
590
|
+
ttl: { type: 'integer' }
|
|
591
|
+
},
|
|
592
|
+
required: []
|
|
593
|
+
}
|
|
594
|
+
},
|
|
595
|
+
check: -> { defined?(PWN::AI::Agent::Extrospection) && PWN::AI::Agent::Extrospection.respond_to?(:packet_sense) },
|
|
596
|
+
handler: lambda { |args|
|
|
597
|
+
o = {}
|
|
598
|
+
%i[action iface filter count timeout path ttl].each { |k| o[k] = args[k] if args[k] }
|
|
599
|
+
o[:record] = args[:record] if args.key?(:record)
|
|
600
|
+
PWN::AI::Agent::Extrospection.packet_sense(o)
|
|
601
|
+
}
|
|
602
|
+
)
|
|
603
|
+
|
|
604
|
+
PWN::AI::Agent::Registry.register(
|
|
605
|
+
name: 'extro_vision',
|
|
606
|
+
toolset: 'extrospection',
|
|
607
|
+
schema: {
|
|
608
|
+
name: 'extro_vision',
|
|
609
|
+
description: 'Vision / OCR sense organ — OCR an image via PWN::Plugins::OCR ' \
|
|
610
|
+
'(tesseract / RTesseract) or decode barcodes/QR via zbarimg. ' \
|
|
611
|
+
'Actions: :ocr, :barcode, :inventory. observe(category: :vision).',
|
|
612
|
+
parameters: {
|
|
613
|
+
type: 'object',
|
|
614
|
+
properties: {
|
|
615
|
+
file: { type: 'string', description: 'Path to image (png/jpg/tiff/webp) for :ocr / :barcode.' },
|
|
616
|
+
action: { type: 'string', enum: %w[ocr barcode inventory], description: 'Default :ocr when file given, else :inventory.' },
|
|
617
|
+
lang: { type: 'string', description: 'Tesseract language (default eng).' },
|
|
618
|
+
record: { type: 'boolean', default: true },
|
|
619
|
+
ttl: { type: 'integer' }
|
|
620
|
+
},
|
|
621
|
+
required: []
|
|
622
|
+
}
|
|
623
|
+
},
|
|
624
|
+
check: -> { defined?(PWN::AI::Agent::Extrospection) && PWN::AI::Agent::Extrospection.respond_to?(:vision) },
|
|
625
|
+
handler: lambda { |args|
|
|
626
|
+
o = {}
|
|
627
|
+
o[:file] = args[:file] if args[:file]
|
|
628
|
+
o[:action] = args[:action] if args[:action]
|
|
629
|
+
o[:lang] = args[:lang] if args[:lang]
|
|
630
|
+
o[:record] = args[:record] if args.key?(:record)
|
|
631
|
+
o[:ttl] = args[:ttl] if args[:ttl]
|
|
632
|
+
PWN::AI::Agent::Extrospection.vision(o)
|
|
633
|
+
}
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
PWN::AI::Agent::Registry.register(
|
|
637
|
+
name: 'extro_voice',
|
|
638
|
+
toolset: 'extrospection',
|
|
639
|
+
schema: {
|
|
640
|
+
name: 'extro_voice',
|
|
641
|
+
description: 'Voice sense organ — text-to-speech (espeak-ng / festival / ' \
|
|
642
|
+
'spd-say via PWN::Plugins::Voice) and speech-to-text (whisper). ' \
|
|
643
|
+
'Actions: :inventory, :tts, :stt. Artefacts under ' \
|
|
644
|
+
'~/.pwn/extrospection/voice/. observe(category: :voice).',
|
|
645
|
+
parameters: {
|
|
646
|
+
type: 'object',
|
|
647
|
+
properties: {
|
|
648
|
+
action: { type: 'string', enum: %w[inventory tts stt], default: 'inventory' },
|
|
649
|
+
text: { type: 'string', description: 'Text to speak for action:tts.' },
|
|
650
|
+
text_path: { type: 'string', description: 'Path to text file for action:tts.' },
|
|
651
|
+
audio: { type: 'string', description: 'Path to audio file for action:stt.' },
|
|
652
|
+
out: { type: 'string', description: 'Output wav path for action:tts.' },
|
|
653
|
+
engine: { type: 'string', enum: %w[espeak festival spd_say whisper], description: 'Force engine (auto by default).' },
|
|
654
|
+
model: { type: 'string', description: 'Whisper model for STT (default tiny).' },
|
|
655
|
+
record: { type: 'boolean', default: true },
|
|
656
|
+
ttl: { type: 'integer' }
|
|
657
|
+
},
|
|
658
|
+
required: []
|
|
659
|
+
}
|
|
660
|
+
},
|
|
661
|
+
check: -> { defined?(PWN::AI::Agent::Extrospection) && PWN::AI::Agent::Extrospection.respond_to?(:voice_sense) },
|
|
662
|
+
handler: lambda { |args|
|
|
663
|
+
o = {}
|
|
664
|
+
%i[action text text_path audio out engine model ttl].each { |k| o[k] = args[k] if args[k] }
|
|
665
|
+
o[:record] = args[:record] if args.key?(:record)
|
|
666
|
+
PWN::AI::Agent::Extrospection.voice_sense(o)
|
|
667
|
+
}
|
|
668
|
+
)
|
|
@@ -190,13 +190,13 @@ PWN::AI::Agent::Registry.register(
|
|
|
190
190
|
)
|
|
191
191
|
|
|
192
192
|
PWN::AI::Agent::Registry.register(
|
|
193
|
-
name: '
|
|
193
|
+
name: 'learning_auto_introspect_toggle',
|
|
194
194
|
toolset: 'learning',
|
|
195
195
|
schema: {
|
|
196
|
-
name: '
|
|
196
|
+
name: 'learning_auto_introspect_toggle',
|
|
197
197
|
description: 'Enable/disable end-of-run auto-reflection ' \
|
|
198
|
-
'(PWN::Env[:ai][:agent][:
|
|
199
|
-
'Loop.run calls Learning.
|
|
198
|
+
'(PWN::Env[:ai][:agent][:auto_introspect]). When enabled, ' \
|
|
199
|
+
'Loop.run calls Learning.auto_introspect on the session after ' \
|
|
200
200
|
'every final answer. Disable during noisy fuzzing loops; ' \
|
|
201
201
|
're-enable for the summary turn. Omit `enabled` to just ' \
|
|
202
202
|
'read the current state.',
|
|
@@ -214,8 +214,8 @@ PWN::AI::Agent::Registry.register(
|
|
|
214
214
|
raise 'PWN::Env[:ai] is unavailable or immutable' unless ai.is_a?(Hash) && !ai.frozen?
|
|
215
215
|
|
|
216
216
|
ai[:agent] = (ai[:agent] || {}).dup if ai[:agent].nil? || ai[:agent].frozen?
|
|
217
|
-
prev = ai[:agent][:
|
|
218
|
-
ai[:agent][:
|
|
219
|
-
{ previous: prev, current: ai[:agent][:
|
|
217
|
+
prev = ai[:agent][:auto_introspect] ? true : false
|
|
218
|
+
ai[:agent][:auto_introspect] = (args[:enabled] ? true : false) if args.key?(:enabled)
|
|
219
|
+
{ previous: prev, current: ai[:agent][:auto_introspect] ? true : false }
|
|
220
220
|
}
|
|
221
221
|
)
|
|
@@ -20,7 +20,7 @@ module PWN
|
|
|
20
20
|
|
|
21
21
|
system_role_content = "Being an expert penetration tester skilled in code analysis, debugging, and exploitation while stepping through JavaScript in a Chrome DevTools debugging session: 1. Your sole purpose is to analyze each JavaScript step and generate an Exploit Prediction Scoring System (EPSS) score between 0% - 100%. The step currently resides in this block of JavaScript:\n```\n#{source_to_review}\n```\n2. If the score is >= 75%, generate a JavaScript proof-of-concept that would allow a threat actor to directly exploit or target a user for exploitation (i.e. no self-exploit). 3. If the EPSS score is >= 75% also provide a code fix. *** If the EPSS score is < 75%, no explanations or summaries - just the EPSS score."
|
|
22
22
|
|
|
23
|
-
PWN::AI::Agent::
|
|
23
|
+
PWN::AI::Agent::Reflect.on(
|
|
24
24
|
system_role_content: system_role_content,
|
|
25
25
|
request: request,
|
|
26
26
|
suppress_pii_warning: true
|
|
@@ -12,7 +12,7 @@ module PWN
|
|
|
12
12
|
# 4. CVSS score, vector string, and first.org calculator URI
|
|
13
13
|
# 5. CWE category, brief description, and CWE URI
|
|
14
14
|
# 6. Relevant NIST 800-53 control
|
|
15
|
-
# It leverages the PWN::AI::Agent::
|
|
15
|
+
# It leverages the PWN::AI::Agent::Reflect.on method. Defaults to Jira for existing workflow compatibility.
|
|
16
16
|
module VulnGen
|
|
17
17
|
# Supported Method Parameters::
|
|
18
18
|
# ai_analysis = PWN::AI::Agent::VulnGen.analyze(
|
|
@@ -60,7 +60,7 @@ module PWN
|
|
|
60
60
|
6. NIST 800-53 Security Control that is impacted by this vulnerability.
|
|
61
61
|
"
|
|
62
62
|
|
|
63
|
-
analysis = PWN::AI::Agent::
|
|
63
|
+
analysis = PWN::AI::Agent::Reflect.on(
|
|
64
64
|
system_role_content: system_role_content,
|
|
65
65
|
request: request,
|
|
66
66
|
suppress_pii_warning: true
|
data/lib/pwn/ai/agent.rb
CHANGED
|
@@ -27,7 +27,7 @@ module PWN
|
|
|
27
27
|
autoload :Learning, 'pwn/ai/agent/learning'
|
|
28
28
|
autoload :Mistakes, 'pwn/ai/agent/mistakes'
|
|
29
29
|
autoload :Extrospection, 'pwn/ai/agent/extrospection'
|
|
30
|
-
autoload :
|
|
30
|
+
autoload :Reflect, 'pwn/ai/agent/reflect'
|
|
31
31
|
autoload :Swarm, 'pwn/ai/agent/swarm'
|
|
32
32
|
|
|
33
33
|
# Display a List of Every PWN::AI Module
|