Module: PWN::AI::Agent::Confirmation
- Defined in:
- lib/pwn/ai/agent/confirmation.rb
Overview
Per-engagement ACK for exploit/destructive tool calls (PWN-AI-005 tiers).
Constant Summary collapse
- TIERS =
%w[read_only active_scan exploit destructive].freeze
- DEFAULTS =
{ 'read_only' => 'auto', 'active_scan' => 'auto', 'exploit' => 'prompt', 'destructive' => 'prompt' }.freeze
- AUTONOMOUS =
{ 'read_only' => 'auto', 'active_scan' => 'auto', 'exploit' => 'auto', 'destructive' => 'auto' }.freeze
Class Method Summary collapse
- .authors ⇒ Object
-
.gate(opts = {}) ⇒ Object
Return an ACK pause hash, or nil when the call may proceed.
- .help ⇒ Object
- .required_bins ⇒ Object
-
.tier(opts = {}) ⇒ Object
Classify a tool call into a PWN-AI-005 side-effect tier.
Class Method Details
.authors ⇒ Object
68 69 70 |
# File 'lib/pwn/ai/agent/confirmation.rb', line 68 public_class_method def self. "AUTHOR(S):\n 0day Inc. <[email protected]>\n" end |
.gate(opts = {}) ⇒ Object
Return an ACK pause hash, or nil when the call may proceed.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/pwn/ai/agent/confirmation.rb', line 38 public_class_method def self.gate(opts = {}) name = opts[:name].to_s args = opts[:args] args = {} unless args.is_a?(Hash) klass = tier(name: name, args: args) policy = load_policy(opts) action = (policy[klass] || DEFAULTS[klass] || 'auto').to_s return { success: false, error: 'unattended mission refuses exploit and destructive calls without scope.yaml confirmation', code: 'ACK_DENY', tier: klass } if opts[:unattended] && policy.equal?(AUTONOMOUS) && %w[exploit destructive].include?(klass) return { success: false, error: "confirmation deny for #{klass}", code: 'ACK_DENY', tier: klass } if action == 'deny' return nil unless action == 'prompt' eng = engagement_id(opts.merge(args: args)) return scoped_ack(opts.merge(name: name, args: args, engagement_id: eng, tier: klass)) if opts[:ack_scope] return nil if acked?(engagement_id: eng) if truthy?(value: opts[:operator_ack] || args[:operator_ack] || args['operator_ack']) persist_ack(engagement_id: eng) return nil end { success: false, needs_ack: true, code: 'ACK_REQUIRED', tier: klass, engagement_id: eng, diff: intended_diff(name: name, args: args, tier: klass), error: "operator ACK required for #{klass}-tier tool call" } end |
.help ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/pwn/ai/agent/confirmation.rb', line 72 public_class_method def self.help puts "USAGE: # List host binaries this module expects to be installed. #{self}.required_bins # Classify a tool call into a PWN-AI-005 side-effect tier. #{self}.tier( name: 'required - registry tool name', args: 'optional - Hash of tool arguments' ) # Return an ACK pause hash, or nil when the call may proceed. #{self}.gate( name: 'required - registry tool name', args: 'optional - Hash of tool arguments', engagement_id: 'optional - engagement id used to cache the ACK', operator_ack: 'optional - true records a one-time ACK for this engagement', scope_path: 'optional - scope.yaml path; defaults to ~/.pwn/scope.yaml', unattended: 'optional - true denies exploit and destructive when confirmation is absent', ack_scope: 'optional - true scopes the ACK to tool, host, and arguments', ack_ttl: 'optional - seconds before a scoped ACK expires' ) # Print the AUTHOR(S) string for this module. #{self}.authors " constants.sort end |
.required_bins ⇒ Object
18 19 20 |
# File 'lib/pwn/ai/agent/confirmation.rb', line 18 public_class_method def self.required_bins [] end |
.tier(opts = {}) ⇒ Object
Classify a tool call into a PWN-AI-005 side-effect tier.
23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/pwn/ai/agent/confirmation.rb', line 23 public_class_method def self.tier(opts = {}) name = opts[:name].to_s args = opts[:args] args = {} unless args.is_a?(Hash) tagged = (args[:side_effect] || args['side_effect']).to_s return tagged if TIERS.include?(tagged) return 'exploit' if name.match?(/exploit|gdb_run_to_crash|fuzz_campaign/) return 'active_scan' if name.match?(/nmap_scan|nuclei_scan|sbom_scan|http_proxy/) return payload_tier(payload: args[:command] || args['command']) if name == 'shell' return payload_tier(payload: args[:code] || args['code']) if name == 'pwn_eval' 'read_only' end |