pwn 0.5.698 → 0.5.699

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c333795b07ea88fb7ea338e6b01faf768c62bd07757328fc1698972d43a6c5e8
4
- data.tar.gz: 0cfbe454002f7ffc79571162a96367aaf3d69017d997cb024c4a475ac3bbab7b
3
+ metadata.gz: 5d7edeea1940ad56143190285565ba9bd76f4d78a47294238eafaad1d002686f
4
+ data.tar.gz: c3a594906ca8d239b8f5dfc3fe3343ec718bf1a71e3c85334b3b6db7e852b5fe
5
5
  SHA512:
6
- metadata.gz: 7a699a8308cb00f04bdf85869647ec381009daf04fe4d8c972c62d5ed57b819b4b719672fe4ad64966c316520a2496bdeb4914c002f526e886b877f7b5d11928
7
- data.tar.gz: 5b2d1fa1f979bc4852304ed09b7122817a71689114f4c4f6a1a46798b01e9d3bb186b8af28aa8d08288c470b01d323735fb252ccc9c45426835d8b717ca8e382
6
+ metadata.gz: fee1edba85d565609b592498feff5eaf38bc01a4771af2a2e22f3719d1eac7faaf54c8f8772837358cf5cbf18db59736aee90fe4a7114c1e6353be423d42e2e8
7
+ data.tar.gz: 4ad32cb15b7bd78d0fa150cf63379ecf61184b84a902426a3581a558b48b17b0a7bc23048a2d2576155b538403e9472a1ebe542a8154eece95a36e4106e352f9
@@ -1427,8 +1427,10 @@ module PWN
1427
1427
  messages = opts[:messages]
1428
1428
  return messages unless messages.is_a?(Array) && messages.length > 12
1429
1429
 
1430
- keep_pairs = (agent_flag(key: :history_keep_tool_pairs, default: 6) || 6).to_i
1431
- max_chars = (agent_flag(key: :history_tool_max_chars, default: 2_000) || 2_000).to_i
1430
+ keep_pairs = opts[:keep_pairs]
1431
+ keep_pairs = (agent_flag(key: :history_keep_tool_pairs, default: 6) || 6).to_i if keep_pairs.nil?
1432
+ max_chars = opts[:max_chars]
1433
+ max_chars = (agent_flag(key: :history_tool_max_chars, default: 2_000) || 2_000).to_i if max_chars.nil?
1432
1434
 
1433
1435
  head = []
1434
1436
  rest = messages.dup
@@ -2491,8 +2493,9 @@ module PWN
2491
2493
  i = 0
2492
2494
  loop do
2493
2495
  i += 1
2494
- # 3.1 — compact history on local so tool dumps don't fill num_ctx
2495
- compact_history!(messages: messages) if local
2496
+ # 3.1 — compact fat tool dumps so remote ReadTimeout hops do not
2497
+ # retry the same 70-message payload (R1 201215 Anthropic 180s×5).
2498
+ compact_history!(messages: messages)
2496
2499
  # English-task-as-primary: when plan_idx advanced, tell the model
2497
2500
  # which plain-English task is active before the next tool batch.
2498
2501
  inject_task_focus!(messages: messages, state: ts_state, request: request) unless skip_compass
@@ -2510,6 +2513,7 @@ module PWN
2510
2513
  final_chars = txt.length
2511
2514
  return txt
2512
2515
  end
2516
+ compact_history!(messages: messages, keep_pairs: 3, max_chars: 800)
2513
2517
  messages << {
2514
2518
  role: 'user',
2515
2519
  content: '[pwn-ai] engine hop failed (transient). Keep calling CORE_TOOLS. ' \
@@ -661,6 +661,17 @@ module PWN
661
661
  ]
662
662
  end
663
663
 
664
+ artifact = goal_text[%r{(?:/(?:tmp|var|home|opt|usr)/\S+\.(?:pdf|html|md|json|txt|csv)|~/\S+\.(?:pdf|html|md|json|txt|csv))}i]
665
+ if artifact && goal_lc.match?(/\b(analy[sz]e|test|scan|report|generat|store|write|export)\b/)
666
+ tasks << 'Carry out the requested analysis using the named skills and live evidence'
667
+ tasks << "Write the requested report to #{artifact}"
668
+ if goal_lc.match?(/\b(json|ya?ml|table|csv|tsv)\b/)
669
+ fmt = goal_lc[/\b(json|ya?ml|table|csv|tsv)\b/]
670
+ tasks << "Present the results in #{fmt} format"
671
+ end
672
+ return tasks
673
+ end
674
+
664
675
  tasks << "Understand the request: #{truncate_goal(goal: goal_text)}"
665
676
  tasks << "Carry out the core work for: #{truncate_goal(goal: goal_text)}"
666
677
 
@@ -24,6 +24,7 @@ module PWN
24
24
  # Conservative bash-only constructs. POSIX `$(())` is allowed.
25
25
  BASHISM_RX = /
26
26
  \bPIPESTATUS\b
27
+ |\$\{?RANDOM\}?\b
27
28
  |\[\[(?:\s|\z)
28
29
  |(?:^|[\s;|&])source\s+\S
29
30
  |<\([^)]
@@ -65,7 +65,7 @@ PWN::AI::Agent::Registry.register(
65
65
 
66
66
  if PWN::AI::Agent::ToolGuard.bashism?(text: cmd) && !PWN::AI::Agent::ToolGuard.shell_bash?
67
67
  return PWN::AI::Agent::ToolGuard.invalid_payload(
68
- hint: 'Command uses bash-only syntax (PIPESTATUS, [[ ]], process substitution, ' \
68
+ hint: 'Command uses bash-only syntax (PIPESTATUS, $RANDOM, [[ ]], process substitution, ' \
69
69
  'source, &>). This handler runs /bin/sh (dash) unless ' \
70
70
  'PWN::Env[:ai][:agent][:shell_bash]=true. Rewrite as POSIX or opt in to bash.'
71
71
  )
data/lib/pwn/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.5.698'
4
+ VERSION = '0.5.699'
5
5
  end
@@ -434,6 +434,33 @@ describe PWN::AI::Agent::Loop do # rubocop:disable Metrics/BlockLength
434
434
  expect(src).to match(/engine hop failed|engine_blip/)
435
435
  end
436
436
 
437
+ it 'compacts tool history for every engine, not only local' do
438
+ src = File.read(described_class.method(:run).source_location.first)
439
+ expect(src).to match(/compact_history!\(messages: messages\)/)
440
+ expect(src).not_to match(/compact_history!\(messages: messages\) if local/)
441
+ end
442
+
443
+ it 'shrinks tool bodies when history is fat' do
444
+ msgs = [
445
+ { role: 'system', content: 'sys' },
446
+ { role: 'user', content: 'goal' }
447
+ ]
448
+ 8.times do |n|
449
+ msgs << { role: 'assistant', content: '', tool_calls: [{ id: "c#{n}" }] }
450
+ msgs << { role: 'tool', tool_call_id: "c#{n}", name: 'shell', content: ('x' * 4_000) }
451
+ end
452
+ out = described_class.send(:compact_history!, messages: msgs)
453
+ tool_bodies = out.select { |m| m[:role].to_s == 'tool' }
454
+ expect(tool_bodies.length).to be <= 6
455
+ expect(tool_bodies.map { |m| m[:content].to_s.length }.max).to be <= 2_100
456
+ end
457
+
458
+ it 'compacts again after a transient engine hop before retrying' do
459
+ src = File.read(described_class.method(:run).source_location.first)
460
+ hop = src[/if engine_transient\?.*?raise/m]
461
+ expect(hop).to match(/compact_history!/)
462
+ end
463
+
437
464
  it 'records a timeout increment mistake instead of treating success:true as ok' do
438
465
  tmp = Dir.mktmpdir
439
466
  stub_const('PWN::AI::Agent::Mistakes::MISTAKES_FILE', File.join(tmp, 'mistakes.json'))
@@ -36,6 +36,14 @@ describe 'P0 signal hygiene (handler + inbox + policy-cold + calibrate)' do
36
36
  expect(r[:hint].to_s).to match(/bash-only/i)
37
37
  end
38
38
 
39
+ it 'rejects $RANDOM under /bin/sh so the model rewrites instead of getting USER=' do
40
+ expect(PWN::AI::Agent::ToolGuard.bashism?(text: 'U="p4tester$RANDOM"; echo $U')).to eq(true)
41
+ handler = PWN::AI::Agent::Registry.lookup(name: 'shell').handler
42
+ r = handler.call(command: 'U="p4tester$RANDOM"; echo $U')
43
+ expect(r[:error]).to eq('invalid_payload')
44
+ expect(r[:hint].to_s).to match(/RANDOM|bash-only|POSIX/i)
45
+ end
46
+
39
47
  it 'does not refuse pwn_eval host-discovery as unauthorized' do
40
48
  src = File.read('/opt/pwn/lib/pwn/ai/agent/tools/ruby_eval.rb')
41
49
  expect(src).not_to match(/recon_blocked/)
@@ -425,6 +425,16 @@ describe PWN::AI::Agent::TaskSummarizer do
425
425
  )
426
426
  end
427
427
 
428
+ it 'splits analyze-plus-artifact goals instead of pasting the full request twice' do
429
+ goal = 'Exhaustively analyze the running application for vulnerabilities. ' \
430
+ 'Once complete, generate a complete PDF report and store in /tmp/container_pentest-p4.pdf'
431
+ tasks = described_class.fallback_decompose(goal: goal)
432
+ expect(tasks.length).to be >= 2
433
+ expect(tasks.join("\n")).to include('/tmp/container_pentest-p4.pdf')
434
+ expect(tasks.grep(/Understand the request:/).length).to eq(0)
435
+ expect(tasks.grep(/Carry out the core work for:/).length).to eq(0)
436
+ end
437
+
428
438
  it 'accepts injected :tasks / :llm_tasks without network I/O' do
429
439
  custom = ['step alpha', 'step beta', 'verify completion']
430
440
  tasks = described_class.plan(request: 'anything at all', tasks: custom)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.698
4
+ version: 0.5.699
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.