pwn 0.5.708 → 0.5.709

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.
Files changed (434) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/Installation.md +1 -0
  3. data/etc/default_skills/pwn/ai/agent/extrospection/osint/bridges/SKILL.md +30 -8
  4. data/etc/default_skills/pwn/ai/agent/extrospection/osint/social/SKILL.md +30 -8
  5. data/etc/default_skills/pwn/ai/agent/extrospection/osint/social/references/urls.md +1 -1
  6. data/etc/default_skills/pwn/ai/agent/extrospection/references/urls.md +0 -1
  7. data/etc/default_skills/pwn/memory_index/SKILL.md +0 -4
  8. data/etc/default_skills/pwn/plugins/aflplusplus/SKILL.md +48 -0
  9. data/etc/default_skills/pwn/plugins/android/SKILL.md +1 -0
  10. data/etc/default_skills/pwn/plugins/artifact_registry/SKILL.md +49 -0
  11. data/etc/default_skills/pwn/plugins/binary_parser/SKILL.md +54 -0
  12. data/etc/default_skills/pwn/plugins/credential_attack/SKILL.md +51 -0
  13. data/etc/default_skills/pwn/plugins/doctor/SKILL.md +57 -0
  14. data/etc/default_skills/pwn/plugins/exploit_dev/SKILL.md +61 -0
  15. data/etc/default_skills/pwn/plugins/frida/SKILL.md +49 -0
  16. data/etc/default_skills/pwn/plugins/gdb/SKILL.md +52 -0
  17. data/etc/default_skills/pwn/plugins/jobs/SKILL.md +51 -0
  18. data/etc/default_skills/pwn/plugins/nuclei/SKILL.md +48 -0
  19. data/etc/default_skills/pwn/plugins/process_tube/SKILL.md +52 -0
  20. data/etc/default_skills/pwn/plugins/radare2/SKILL.md +59 -0
  21. data/etc/default_skills/pwn/plugins/recon/SKILL.md +55 -0
  22. data/etc/default_skills/pwn/plugins/recon/references/urls.md +5 -0
  23. data/etc/default_skills/pwn/plugins/sqlmap/SKILL.md +48 -0
  24. data/etc/default_skills/pwn/plugins/transparent_browser/SKILL.md +0 -4
  25. data/etc/default_skills/pwn/plugins/volatility/SKILL.md +48 -0
  26. data/lib/pwn/ai/agent/assembly.rb +4 -1
  27. data/lib/pwn/ai/agent/btc.rb +4 -1
  28. data/lib/pwn/ai/agent/burp_suite.rb +5 -2
  29. data/lib/pwn/ai/agent/curriculum.rb +89 -30
  30. data/lib/pwn/ai/agent/dispatch.rb +27 -16
  31. data/lib/pwn/ai/agent/extrospection/osint/bridges.rb +9 -18
  32. data/lib/pwn/ai/agent/extrospection/osint/social.rb +9 -18
  33. data/lib/pwn/ai/agent/extrospection.rb +185 -60
  34. data/lib/pwn/ai/agent/gqrx.rb +4 -1
  35. data/lib/pwn/ai/agent/hacker_one.rb +5 -2
  36. data/lib/pwn/ai/agent/learning.rb +142 -25
  37. data/lib/pwn/ai/agent/loop.rb +53 -46
  38. data/lib/pwn/ai/agent/metrics.rb +133 -23
  39. data/lib/pwn/ai/agent/mistakes.rb +126 -17
  40. data/lib/pwn/ai/agent/open_goal.rb +25 -9
  41. data/lib/pwn/ai/agent/policy.rb +158 -18
  42. data/lib/pwn/ai/agent/prompt_builder.rb +21 -11
  43. data/lib/pwn/ai/agent/prompt_cache.rb +44 -13
  44. data/lib/pwn/ai/agent/reflect.rb +9 -5
  45. data/lib/pwn/ai/agent/registry.rb +65 -12
  46. data/lib/pwn/ai/agent/result.rb +19 -10
  47. data/lib/pwn/ai/agent/reward.rb +150 -32
  48. data/lib/pwn/ai/agent/sast.rb +4 -1
  49. data/lib/pwn/ai/agent/swarm.rb +72 -36
  50. data/lib/pwn/ai/agent/task_summarizer.rb +165 -36
  51. data/lib/pwn/ai/agent/tool_guard.rb +105 -6
  52. data/lib/pwn/ai/agent/transparent_browser.rb +4 -1
  53. data/lib/pwn/ai/agent/turn_finalizer.rb +41 -21
  54. data/lib/pwn/ai/agent/vuln_gen.rb +6 -3
  55. data/lib/pwn/ai/agent.rb +4 -0
  56. data/lib/pwn/ai/anthropic.rb +41 -7
  57. data/lib/pwn/ai/gemini.rb +21 -11
  58. data/lib/pwn/ai/grok.rb +44 -6
  59. data/lib/pwn/ai/http_retry.rb +40 -12
  60. data/lib/pwn/ai/ollama.rb +19 -10
  61. data/lib/pwn/ai/open_ai.rb +81 -30
  62. data/lib/pwn/ai/open_web_ui.rb +20 -14
  63. data/lib/pwn/ai/red_team/agent_protocol_abuse.rb +7 -1
  64. data/lib/pwn/ai/red_team/data_and_model_poisoning.rb +7 -1
  65. data/lib/pwn/ai/red_team/excessive_agency.rb +7 -1
  66. data/lib/pwn/ai/red_team/hidden_context_exposure.rb +7 -1
  67. data/lib/pwn/ai/red_team/insecure_output_handling.rb +7 -1
  68. data/lib/pwn/ai/red_team/jailbreak.rb +7 -1
  69. data/lib/pwn/ai/red_team/memory_poisoning.rb +7 -1
  70. data/lib/pwn/ai/red_team/multimodal_injection.rb +7 -1
  71. data/lib/pwn/ai/red_team/overreliance.rb +7 -1
  72. data/lib/pwn/ai/red_team/payload_splitting.rb +7 -1
  73. data/lib/pwn/ai/red_team/prompt_injection.rb +7 -1
  74. data/lib/pwn/ai/red_team/rag_poisoning.rb +7 -1
  75. data/lib/pwn/ai/red_team/sensitive_information_disclosure.rb +7 -1
  76. data/lib/pwn/ai/red_team/supply_chain.rb +7 -1
  77. data/lib/pwn/ai/red_team/system_prompt_extraction.rb +7 -1
  78. data/lib/pwn/ai/red_team/test_case_engine.rb +12 -9
  79. data/lib/pwn/ai/red_team/token_smuggling.rb +7 -1
  80. data/lib/pwn/ai/red_team/unbounded_consumption.rb +7 -1
  81. data/lib/pwn/ai/red_team/vector_and_embedding_weaknesses.rb +7 -1
  82. data/lib/pwn/ai/red_team.rb +4 -0
  83. data/lib/pwn/ai.rb +4 -0
  84. data/lib/pwn/aws/acm.rb +5 -2
  85. data/lib/pwn/aws/api_gateway.rb +10 -7
  86. data/lib/pwn/aws/app_stream.rb +5 -2
  87. data/lib/pwn/aws/application_auto_scaling.rb +5 -2
  88. data/lib/pwn/aws/application_discovery_service.rb +5 -2
  89. data/lib/pwn/aws/auto_scaling.rb +5 -2
  90. data/lib/pwn/aws/batch.rb +5 -2
  91. data/lib/pwn/aws/budgets.rb +5 -2
  92. data/lib/pwn/aws/cloud_formation.rb +5 -2
  93. data/lib/pwn/aws/cloud_front.rb +7 -4
  94. data/lib/pwn/aws/cloud_hsm.rb +5 -2
  95. data/lib/pwn/aws/cloud_search.rb +5 -2
  96. data/lib/pwn/aws/cloud_search_domain.rb +5 -2
  97. data/lib/pwn/aws/cloud_trail.rb +5 -2
  98. data/lib/pwn/aws/cloud_watch.rb +5 -2
  99. data/lib/pwn/aws/cloud_watch_events.rb +5 -2
  100. data/lib/pwn/aws/cloud_watch_logs.rb +5 -2
  101. data/lib/pwn/aws/code_build.rb +5 -2
  102. data/lib/pwn/aws/code_commit.rb +5 -2
  103. data/lib/pwn/aws/code_deploy.rb +5 -2
  104. data/lib/pwn/aws/code_pipeline.rb +5 -2
  105. data/lib/pwn/aws/cognito_identity.rb +5 -2
  106. data/lib/pwn/aws/cognito_identity_provider.rb +5 -2
  107. data/lib/pwn/aws/cognito_sync.rb +5 -2
  108. data/lib/pwn/aws/config_service.rb +5 -2
  109. data/lib/pwn/aws/data_pipleline.rb +5 -2
  110. data/lib/pwn/aws/database_migration_service.rb +5 -2
  111. data/lib/pwn/aws/device_farm.rb +5 -2
  112. data/lib/pwn/aws/direct_connect.rb +5 -2
  113. data/lib/pwn/aws/directory_service.rb +5 -2
  114. data/lib/pwn/aws/dynamo_db.rb +5 -2
  115. data/lib/pwn/aws/dynamo_db_streams.rb +5 -2
  116. data/lib/pwn/aws/ec2.rb +5 -2
  117. data/lib/pwn/aws/ecr.rb +5 -2
  118. data/lib/pwn/aws/ecs.rb +5 -2
  119. data/lib/pwn/aws/efs.rb +5 -2
  120. data/lib/pwn/aws/elasti_cache.rb +5 -2
  121. data/lib/pwn/aws/elastic_beanstalk.rb +8 -5
  122. data/lib/pwn/aws/elastic_load_balancing.rb +5 -2
  123. data/lib/pwn/aws/elastic_load_balancing_v2.rb +6 -3
  124. data/lib/pwn/aws/elastic_transcoder.rb +5 -2
  125. data/lib/pwn/aws/elasticsearch_service.rb +5 -2
  126. data/lib/pwn/aws/emr.rb +5 -2
  127. data/lib/pwn/aws/firehose.rb +5 -2
  128. data/lib/pwn/aws/game_lift.rb +5 -2
  129. data/lib/pwn/aws/glacier.rb +6 -3
  130. data/lib/pwn/aws/health.rb +5 -2
  131. data/lib/pwn/aws/iam.rb +10 -4
  132. data/lib/pwn/aws/import_export.rb +5 -2
  133. data/lib/pwn/aws/inspector.rb +5 -2
  134. data/lib/pwn/aws/iot.rb +5 -2
  135. data/lib/pwn/aws/iot_data_plane.rb +5 -2
  136. data/lib/pwn/aws/kinesis.rb +5 -2
  137. data/lib/pwn/aws/kinesis_analytics.rb +5 -2
  138. data/lib/pwn/aws/kms.rb +5 -2
  139. data/lib/pwn/aws/lambda.rb +5 -2
  140. data/lib/pwn/aws/lambda_preview.rb +5 -2
  141. data/lib/pwn/aws/lex.rb +5 -2
  142. data/lib/pwn/aws/lightsail.rb +5 -2
  143. data/lib/pwn/aws/machine_learning.rb +5 -2
  144. data/lib/pwn/aws/marketplace_commerce_analytics.rb +5 -2
  145. data/lib/pwn/aws/marketplace_metering.rb +5 -2
  146. data/lib/pwn/aws/ops_works.rb +5 -2
  147. data/lib/pwn/aws/ops_works_cm.rb +5 -2
  148. data/lib/pwn/aws/pinpoint.rb +5 -2
  149. data/lib/pwn/aws/polly.rb +5 -2
  150. data/lib/pwn/aws/rds.rb +5 -2
  151. data/lib/pwn/aws/redshift.rb +5 -2
  152. data/lib/pwn/aws/rekognition.rb +5 -2
  153. data/lib/pwn/aws/route53.rb +5 -2
  154. data/lib/pwn/aws/route53_domains.rb +5 -2
  155. data/lib/pwn/aws/s3.rb +5 -2
  156. data/lib/pwn/aws/service_catalog.rb +5 -2
  157. data/lib/pwn/aws/ses.rb +5 -2
  158. data/lib/pwn/aws/shield.rb +5 -2
  159. data/lib/pwn/aws/simple_db.rb +5 -2
  160. data/lib/pwn/aws/sms.rb +5 -2
  161. data/lib/pwn/aws/snowball.rb +5 -2
  162. data/lib/pwn/aws/sns.rb +5 -2
  163. data/lib/pwn/aws/sqs.rb +5 -2
  164. data/lib/pwn/aws/ssm.rb +5 -2
  165. data/lib/pwn/aws/states.rb +5 -2
  166. data/lib/pwn/aws/storage_gateway.rb +5 -2
  167. data/lib/pwn/aws/sts.rb +4 -1
  168. data/lib/pwn/aws/support.rb +5 -2
  169. data/lib/pwn/aws/swf.rb +5 -2
  170. data/lib/pwn/aws/waf.rb +5 -2
  171. data/lib/pwn/aws/waf_regional.rb +5 -2
  172. data/lib/pwn/aws/workspaces.rb +5 -2
  173. data/lib/pwn/aws/x_ray.rb +5 -2
  174. data/lib/pwn/aws.rb +4 -0
  175. data/lib/pwn/banner/anon.rb +3 -0
  176. data/lib/pwn/banner/bubble.rb +3 -0
  177. data/lib/pwn/banner/cheshire.rb +3 -0
  178. data/lib/pwn/banner/code_cave.rb +3 -0
  179. data/lib/pwn/banner/dont_panic.rb +3 -0
  180. data/lib/pwn/banner/f_society.rb +3 -0
  181. data/lib/pwn/banner/fork_bomb.rb +3 -0
  182. data/lib/pwn/banner/jmp_esp.rb +3 -0
  183. data/lib/pwn/banner/matrix.rb +5 -1
  184. data/lib/pwn/banner/ninja.rb +3 -0
  185. data/lib/pwn/banner/off_the_air.rb +3 -0
  186. data/lib/pwn/banner/pirate.rb +3 -0
  187. data/lib/pwn/banner/radare2.rb +3 -0
  188. data/lib/pwn/banner/radare2_ai.rb +3 -0
  189. data/lib/pwn/banner/white_rabbit.rb +3 -0
  190. data/lib/pwn/banner.rb +6 -2
  191. data/lib/pwn/blockchain/btc.rb +8 -3
  192. data/lib/pwn/blockchain/eth.rb +10 -3
  193. data/lib/pwn/blockchain.rb +4 -0
  194. data/lib/pwn/bounty/lifecycle_authz_replay.rb +46 -27
  195. data/lib/pwn/bounty.rb +4 -0
  196. data/lib/pwn/config.rb +79 -13
  197. data/lib/pwn/cron.rb +297 -20
  198. data/lib/pwn/driver.rb +2 -18
  199. data/lib/pwn/ffi/adalm_pluto.rb +65 -11
  200. data/lib/pwn/ffi/fftw.rb +31 -6
  201. data/lib/pwn/ffi/hack_rf.rb +59 -8
  202. data/lib/pwn/ffi/liquid.rb +63 -10
  203. data/lib/pwn/ffi/rtl_sdr.rb +35 -5
  204. data/lib/pwn/ffi/soapy_sdr.rb +60 -10
  205. data/lib/pwn/ffi/stdio.rb +5 -8
  206. data/lib/pwn/ffi/volk.rb +36 -7
  207. data/lib/pwn/ffi.rb +12 -0
  208. data/lib/pwn/memory.rb +136 -16
  209. data/lib/pwn/memory_index.rb +34 -19
  210. data/lib/pwn/migrate.rb +34 -24
  211. data/lib/pwn/module_skills.rb +39 -8
  212. data/lib/pwn/plugins/aflplusplus.rb +52 -0
  213. data/lib/pwn/plugins/android.rb +65 -245
  214. data/lib/pwn/plugins/artifact_registry.rb +71 -0
  215. data/lib/pwn/plugins/assembly.rb +9 -4
  216. data/lib/pwn/plugins/authentication_helper.rb +8 -5
  217. data/lib/pwn/plugins/baresip.rb +59 -12
  218. data/lib/pwn/plugins/basic_auth.rb +9 -3
  219. data/lib/pwn/plugins/beef.rb +28 -18
  220. data/lib/pwn/plugins/binary_parser.rb +133 -0
  221. data/lib/pwn/plugins/black_duck_binary_analysis.rb +63 -39
  222. data/lib/pwn/plugins/burp_suite.rb +98 -68
  223. data/lib/pwn/plugins/bus_pirate.rb +15 -8
  224. data/lib/pwn/plugins/char.rb +33 -3
  225. data/lib/pwn/plugins/credential_attack.rb +99 -0
  226. data/lib/pwn/plugins/credit_card.rb +6 -1
  227. data/lib/pwn/plugins/dao_ldap.rb +19 -13
  228. data/lib/pwn/plugins/dao_mongo.rb +11 -5
  229. data/lib/pwn/plugins/dao_postgres.rb +28 -19
  230. data/lib/pwn/plugins/dao_sqlite3.rb +15 -6
  231. data/lib/pwn/plugins/defect_dojo.rb +38 -22
  232. data/lib/pwn/plugins/detect_os.rb +5 -0
  233. data/lib/pwn/plugins/doctor.rb +149 -0
  234. data/lib/pwn/plugins/ein.rb +3 -0
  235. data/lib/pwn/plugins/exploit_dev.rb +264 -0
  236. data/lib/pwn/plugins/file_fu.rb +11 -8
  237. data/lib/pwn/plugins/frida.rb +61 -0
  238. data/lib/pwn/plugins/fuzz.rb +9 -6
  239. data/lib/pwn/plugins/gdb.rb +95 -0
  240. data/lib/pwn/plugins/git.rb +19 -14
  241. data/lib/pwn/plugins/github.rb +38 -15
  242. data/lib/pwn/plugins/google_workspace.rb +188 -45
  243. data/lib/pwn/plugins/hacker_one.rb +159 -35
  244. data/lib/pwn/plugins/hunter.rb +6 -3
  245. data/lib/pwn/plugins/ip_info.rb +9 -4
  246. data/lib/pwn/plugins/irc.rb +28 -15
  247. data/lib/pwn/plugins/jenkins.rb +65 -57
  248. data/lib/pwn/plugins/jira_data_center.rb +30 -22
  249. data/lib/pwn/plugins/jobs.rb +109 -0
  250. data/lib/pwn/plugins/json_pathify.rb +9 -5
  251. data/lib/pwn/plugins/log.rb +113 -13
  252. data/lib/pwn/plugins/mail_agent.rb +87 -79
  253. data/lib/pwn/plugins/metasploit.rb +11 -6
  254. data/lib/pwn/plugins/monkey_patch.rb +3 -0
  255. data/lib/pwn/plugins/msr206.rb +42 -28
  256. data/lib/pwn/plugins/nessus_cloud.rb +44 -4
  257. data/lib/pwn/plugins/nexpose_vuln_scan.rb +40 -24
  258. data/lib/pwn/plugins/nmap_it.rb +14 -34
  259. data/lib/pwn/plugins/nuclei.rb +57 -0
  260. data/lib/pwn/plugins/oauth2.rb +11 -5
  261. data/lib/pwn/plugins/ocr.rb +3 -0
  262. data/lib/pwn/plugins/open_api.rb +5 -2
  263. data/lib/pwn/plugins/openvas.rb +33 -25
  264. data/lib/pwn/plugins/packet.rb +152 -31
  265. data/lib/pwn/plugins/pdf_parse.rb +5 -2
  266. data/lib/pwn/plugins/pony.rb +86 -1
  267. data/lib/pwn/plugins/process_tube.rb +120 -0
  268. data/lib/pwn/plugins/ps.rb +7 -1
  269. data/lib/pwn/plugins/pwn_logger.rb +6 -2
  270. data/lib/pwn/plugins/rabbit_mq.rb +12 -7
  271. data/lib/pwn/plugins/radare2.rb +253 -0
  272. data/lib/pwn/plugins/recon.rb +161 -0
  273. data/lib/pwn/plugins/repl.rb +122 -1
  274. data/lib/pwn/plugins/scannable_codes.rb +5 -1
  275. data/lib/pwn/plugins/serial.rb +24 -14
  276. data/lib/pwn/plugins/shodan.rb +54 -35
  277. data/lib/pwn/plugins/slack_client.rb +11 -6
  278. data/lib/pwn/plugins/sock.rb +16 -8
  279. data/lib/pwn/plugins/spider.rb +5 -2
  280. data/lib/pwn/plugins/sqlmap.rb +49 -0
  281. data/lib/pwn/plugins/ssn.rb +3 -0
  282. data/lib/pwn/plugins/thread_pool.rb +6 -9
  283. data/lib/pwn/plugins/tor.rb +9 -4
  284. data/lib/pwn/plugins/transparent_browser.rb +62 -107
  285. data/lib/pwn/plugins/tty_spinner.rb +16 -2
  286. data/lib/pwn/plugins/twitter_api.rb +6 -2
  287. data/lib/pwn/plugins/uri_scheme.rb +4 -1
  288. data/lib/pwn/plugins/vault.rb +12 -3
  289. data/lib/pwn/plugins/vin.rb +24 -12
  290. data/lib/pwn/plugins/voice.rb +7 -2
  291. data/lib/pwn/plugins/volatility.rb +48 -0
  292. data/lib/pwn/plugins/vsphere.rb +9 -5
  293. data/lib/pwn/plugins/xxd.rb +12 -43
  294. data/lib/pwn/plugins/zaproxy.rb +30 -16
  295. data/lib/pwn/plugins.rb +19 -0
  296. data/lib/pwn/reports/ai_red_team.rb +6 -2
  297. data/lib/pwn/reports/csv.rb +8 -1
  298. data/lib/pwn/reports/fuzz.rb +5 -2
  299. data/lib/pwn/reports/html.rb +8 -1
  300. data/lib/pwn/reports/html_footer.rb +4 -3
  301. data/lib/pwn/reports/html_header.rb +6 -2
  302. data/lib/pwn/reports/json.rb +8 -1
  303. data/lib/pwn/reports/markdown.rb +8 -1
  304. data/lib/pwn/reports/pdf.rb +8 -1
  305. data/lib/pwn/reports/phone.rb +5 -2
  306. data/lib/pwn/reports/sast.rb +6 -2
  307. data/lib/pwn/reports/uri_buster.rb +5 -2
  308. data/lib/pwn/reports/xml.rb +8 -1
  309. data/lib/pwn/reports.rb +19 -0
  310. data/lib/pwn/sast/amqp_connect_as_guest.rb +9 -3
  311. data/lib/pwn/sast/apache_file_system_util_api.rb +9 -3
  312. data/lib/pwn/sast/aws.rb +9 -3
  313. data/lib/pwn/sast/banned_function_calls_c.rb +9 -3
  314. data/lib/pwn/sast/base64.rb +9 -3
  315. data/lib/pwn/sast/beef_hook.rb +9 -3
  316. data/lib/pwn/sast/cmd_execution_go_lang.rb +9 -3
  317. data/lib/pwn/sast/cmd_execution_java.rb +9 -3
  318. data/lib/pwn/sast/cmd_execution_python.rb +9 -3
  319. data/lib/pwn/sast/cmd_execution_ruby.rb +9 -3
  320. data/lib/pwn/sast/cmd_execution_scala.rb +9 -3
  321. data/lib/pwn/sast/csrf.rb +9 -3
  322. data/lib/pwn/sast/deserial_java.rb +9 -3
  323. data/lib/pwn/sast/emoticon.rb +9 -3
  324. data/lib/pwn/sast/eval.rb +9 -3
  325. data/lib/pwn/sast/factory.rb +9 -3
  326. data/lib/pwn/sast/http_authorization_header.rb +9 -3
  327. data/lib/pwn/sast/inner_html.rb +9 -3
  328. data/lib/pwn/sast/keystore.rb +9 -3
  329. data/lib/pwn/sast/local_storage.rb +9 -3
  330. data/lib/pwn/sast/location_hash.rb +9 -3
  331. data/lib/pwn/sast/log4j.rb +9 -3
  332. data/lib/pwn/sast/logger.rb +9 -3
  333. data/lib/pwn/sast/md5.rb +9 -3
  334. data/lib/pwn/sast/outer_html.rb +9 -3
  335. data/lib/pwn/sast/padding_oracle.rb +9 -3
  336. data/lib/pwn/sast/password.rb +9 -3
  337. data/lib/pwn/sast/php_input_mechanisms.rb +9 -3
  338. data/lib/pwn/sast/php_type_juggling.rb +9 -3
  339. data/lib/pwn/sast/pom_version.rb +9 -3
  340. data/lib/pwn/sast/port.rb +9 -3
  341. data/lib/pwn/sast/post_message.rb +9 -3
  342. data/lib/pwn/sast/private_key.rb +9 -3
  343. data/lib/pwn/sast/redirect.rb +9 -3
  344. data/lib/pwn/sast/redos.rb +9 -3
  345. data/lib/pwn/sast/shell.rb +9 -3
  346. data/lib/pwn/sast/signature.rb +9 -3
  347. data/lib/pwn/sast/sql.rb +9 -3
  348. data/lib/pwn/sast/ssl.rb +9 -3
  349. data/lib/pwn/sast/sudo.rb +9 -3
  350. data/lib/pwn/sast/task_tag.rb +9 -3
  351. data/lib/pwn/sast/test_case_engine.rb +11 -7
  352. data/lib/pwn/sast/throw_errors.rb +9 -3
  353. data/lib/pwn/sast/token.rb +9 -3
  354. data/lib/pwn/sast/type_script_type_juggling.rb +9 -3
  355. data/lib/pwn/sast/use_after_free.rb +9 -3
  356. data/lib/pwn/sast/version.rb +9 -3
  357. data/lib/pwn/sast/window_location_hash.rb +9 -3
  358. data/lib/pwn/sast.rb +4 -0
  359. data/lib/pwn/sdr/decoder/adsb.rb +36 -5
  360. data/lib/pwn/sdr/decoder/apt.rb +9 -6
  361. data/lib/pwn/sdr/decoder/base.rb +74 -22
  362. data/lib/pwn/sdr/decoder/bluetooth.rb +17 -5
  363. data/lib/pwn/sdr/decoder/dect.rb +12 -3
  364. data/lib/pwn/sdr/decoder/dsp.rb +229 -39
  365. data/lib/pwn/sdr/decoder/flex.rb +59 -11
  366. data/lib/pwn/sdr/decoder/gps.rb +12 -3
  367. data/lib/pwn/sdr/decoder/gsm.rb +24 -4
  368. data/lib/pwn/sdr/decoder/iridium.rb +12 -3
  369. data/lib/pwn/sdr/decoder/lora.rb +13 -4
  370. data/lib/pwn/sdr/decoder/lte.rb +27 -3
  371. data/lib/pwn/sdr/decoder/morse.rb +12 -3
  372. data/lib/pwn/sdr/decoder/p25.rb +12 -3
  373. data/lib/pwn/sdr/decoder/pager.rb +8 -5
  374. data/lib/pwn/sdr/decoder/pocsag.rb +29 -9
  375. data/lib/pwn/sdr/decoder/rds.rb +14 -8
  376. data/lib/pwn/sdr/decoder/rfid.rb +12 -3
  377. data/lib/pwn/sdr/decoder/rtl433.rb +12 -3
  378. data/lib/pwn/sdr/decoder/rtty.rb +8 -5
  379. data/lib/pwn/sdr/decoder/wifi.rb +12 -3
  380. data/lib/pwn/sdr/decoder/zigbee.rb +12 -3
  381. data/lib/pwn/sdr/decoder.rb +9 -0
  382. data/lib/pwn/sdr/flipper_zero.rb +17 -10
  383. data/lib/pwn/sdr/frequency_allocation.rb +4 -1
  384. data/lib/pwn/sdr/gqrx.rb +178 -119
  385. data/lib/pwn/sdr/rfidler.rb +4 -1
  386. data/lib/pwn/sdr/son_micro_rfid.rb +37 -24
  387. data/lib/pwn/sdr.rb +14 -0
  388. data/lib/pwn/sessions.rb +86 -16
  389. data/lib/pwn/setup.rb +94 -37
  390. data/lib/pwn/version.rb +1 -1
  391. data/lib/pwn/www/app_cobalt_io.rb +11 -5
  392. data/lib/pwn/www/bing.rb +10 -5
  393. data/lib/pwn/www/bug_crowd.rb +11 -5
  394. data/lib/pwn/www/checkip.rb +8 -4
  395. data/lib/pwn/www/coinbase_pro.rb +11 -5
  396. data/lib/pwn/www/duckduckgo.rb +12 -6
  397. data/lib/pwn/www/facebook.rb +11 -5
  398. data/lib/pwn/www/github.rb +11 -5
  399. data/lib/pwn/www/google.rb +11 -5
  400. data/lib/pwn/www/hacker_one.rb +20 -9
  401. data/lib/pwn/www/linkedin.rb +11 -5
  402. data/lib/pwn/www/pandora.rb +11 -5
  403. data/lib/pwn/www/pastebin.rb +9 -4
  404. data/lib/pwn/www/paypal.rb +19 -11
  405. data/lib/pwn/www/synack.rb +11 -5
  406. data/lib/pwn/www/torch.rb +13 -8
  407. data/lib/pwn/www/trading_view.rb +11 -5
  408. data/lib/pwn/www/twitter.rb +11 -5
  409. data/lib/pwn/www/uber.rb +11 -5
  410. data/lib/pwn/www/upwork.rb +11 -5
  411. data/lib/pwn/www/wayback_machine.rb +12 -6
  412. data/lib/pwn/www/youtube.rb +10 -5
  413. data/lib/pwn/www.rb +4 -0
  414. data/spec/conventions_spec.rb +118 -2
  415. data/spec/lib/pwn/ai/agent/reward_spec.rb +9 -0
  416. data/spec/lib/pwn/plugins/aflplusplus_spec.rb +13 -0
  417. data/spec/lib/pwn/plugins/artifact_registry_spec.rb +13 -0
  418. data/spec/lib/pwn/plugins/binary_parser_spec.rb +21 -0
  419. data/spec/lib/pwn/plugins/credential_attack_spec.rb +13 -0
  420. data/spec/lib/pwn/plugins/doctor_spec.rb +23 -0
  421. data/spec/lib/pwn/plugins/exploit_dev_spec.rb +23 -0
  422. data/spec/lib/pwn/plugins/frida_spec.rb +13 -0
  423. data/spec/lib/pwn/plugins/gdb_spec.rb +13 -0
  424. data/spec/lib/pwn/plugins/jobs_spec.rb +13 -0
  425. data/spec/lib/pwn/plugins/nuclei_spec.rb +13 -0
  426. data/spec/lib/pwn/plugins/process_tube_spec.rb +13 -0
  427. data/spec/lib/pwn/plugins/radare2_spec.rb +13 -0
  428. data/spec/lib/pwn/plugins/recon_spec.rb +26 -0
  429. data/spec/lib/pwn/plugins/sqlmap_spec.rb +13 -0
  430. data/spec/lib/pwn/plugins/volatility_spec.rb +13 -0
  431. data/third_party/pwn_rdoc.jsonl +126 -5
  432. metadata +47 -3
  433. data/etc/default_skills/pwn/memory_index/references/urls.md +0 -4
  434. data/etc/default_skills/pwn/plugins/transparent_browser/references/urls.md +0 -3
@@ -97,27 +97,33 @@ module PWN
97
97
 
98
98
  public_class_method def self.help
99
99
  puts "USAGE:
100
- browser_obj = #{self}.open(
100
+ # Open a session or connection and return a handle.
101
+ #{self}.open(
101
102
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
102
103
  proxy: 'optional - scheme://proxy_host:port || tor'
103
104
  )
104
105
 
105
- browser_obj = #{self}.login(
106
+ # Run login and return its result
107
+ #{self}.login(
106
108
  browser_obj: 'required - browser_obj returned from #open method',
107
- username: 'required - username',
108
- password: 'optional - passwd (will prompt if blank),
109
+ username: 'required - username value consumed by #login',
110
+ password: 'optional - passwd (will prompt if blank)'
109
111
  )
110
112
 
111
- browser_obj = #{self}.logout(
113
+ # Run logout and return its result
114
+ #{self}.logout(
112
115
  browser_obj: 'required - browser_obj returned from #open method'
113
116
  )
114
117
 
118
+ # Close a session previously returned by #open.
115
119
  #{self}.close(
116
120
  browser_obj: 'required - browser_obj returned from #open method'
117
121
  )
118
122
 
123
+ # Print the AUTHOR(S) string for this module.
119
124
  #{self}.authors
120
125
  "
126
+ constants.sort
121
127
  end
122
128
  end
123
129
  end
@@ -63,21 +63,26 @@ module PWN
63
63
 
64
64
  public_class_method def self.help
65
65
  puts "USAGE:
66
- browser_obj = #{self}.open(
67
- browser_type: 'optional :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
66
+ # Open a session or connection and return a handle.
67
+ #{self}.open(
68
+ browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
68
69
  proxy: 'optional - scheme://proxy_host:port || tor'
69
70
  )
70
71
 
71
- browser_obj = #{self}.onion(
72
+ # Run onion and return its result
73
+ #{self}.onion(
72
74
  browser_obj: 'required - browser_obj returned from #open method'
73
75
  )
74
76
 
75
- browser_obj = #{self}.close(
77
+ # Close a session previously returned by #open.
78
+ #{self}.close(
76
79
  browser_obj: 'required - browser_obj returned from #open method'
77
80
  )
78
81
 
82
+ # Print the AUTHOR(S) string for this module.
79
83
  #{self}.authors
80
84
  "
85
+ constants.sort
81
86
  end
82
87
  end
83
88
  end
@@ -167,41 +167,49 @@ module PWN
167
167
 
168
168
  public_class_method def self.help
169
169
  puts "USAGE:
170
- browser_obj = #{self}.open(
170
+ # Open a session or connection and return a handle.
171
+ #{self}.open(
171
172
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
172
173
  proxy: 'optional - scheme://proxy_host:port || tor'
173
174
  )
174
175
 
175
- browser_obj = #{self}.signup(
176
+ # Run signup and return its result
177
+ #{self}.signup(
176
178
  browser_obj: 'required - browser_obj returned from #open method',
177
- first_name: 'required - first name',
178
- last_name: 'required - last name',
179
- address: 'required - address',
180
- city: 'required - city',
179
+ first_name: 'required - first name value consumed by #signup',
180
+ last_name: 'required - last name value consumed by #signup',
181
+ address: 'required - address value consumed by #signup',
182
+ city: 'required - city value consumed by #signup',
181
183
  state: 'required - state abbreviation',
182
- zip_code: 'required - zip code',
183
- mobile_phone: 'required - mobile phone',
184
+ zip_code: 'required - zip code value consumed by #signup',
185
+ mobile_phone: 'required - mobile phone value consumed by #signup',
184
186
  username: 'required - username (email address)',
185
187
  password: 'optional - passwd (will prompt if blank)',
188
+ mfa: 'optional - mfa value consumed by #signup'
186
189
  )
187
190
 
188
- browser_obj = #{self}.login(
191
+ # Run login and return its result
192
+ #{self}.login(
189
193
  browser_obj: 'required - browser_obj returned from #open method',
190
194
  username: 'required - username (email address)',
191
- password: 'optional - passwd (will prompt if blank),
195
+ password: 'optional - passwd (will prompt if blank)',
192
196
  mfa: 'optional - if true prompt for mfa token (defaults to false)'
193
197
  )
194
198
 
195
- browser_obj = #{self}.logout(
199
+ # Run logout and return its result
200
+ #{self}.logout(
196
201
  browser_obj: 'required - browser_obj returned from #open method'
197
202
  )
198
203
 
204
+ # Close a session previously returned by #open.
199
205
  #{self}.close(
200
206
  browser_obj: 'required - browser_obj returned from #open method'
201
207
  )
202
208
 
209
+ # Print the AUTHOR(S) string for this module.
203
210
  #{self}.authors
204
211
  "
212
+ constants.sort
205
213
  end
206
214
  end
207
215
  end
@@ -108,28 +108,34 @@ module PWN
108
108
 
109
109
  public_class_method def self.help
110
110
  puts "USAGE:
111
- browser_obj = #{self}.open(
111
+ # Open a session or connection and return a handle.
112
+ #{self}.open(
112
113
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
113
114
  proxy: 'optional - scheme://proxy_host:port || tor'
114
115
  )
115
116
 
116
- browser_obj = #{self}.login(
117
+ # Run login and return its result
118
+ #{self}.login(
117
119
  browser_obj: 'required - browser_obj returned from #open method',
118
- username: 'required - username',
119
- password: 'optional - passwd (will prompt if blank),
120
+ username: 'required - username value consumed by #login',
121
+ password: 'optional - passwd (will prompt if blank)',
120
122
  mfa: 'optional - if true prompt for mfa token (defaults to false)'
121
123
  )
122
124
 
123
- browser_obj = #{self}.logout(
125
+ # Run logout and return its result
126
+ #{self}.logout(
124
127
  browser_obj: 'required - browser_obj returned from #open method'
125
128
  )
126
129
 
130
+ # Close a session previously returned by #open.
127
131
  #{self}.close(
128
132
  browser_obj: 'required - browser_obj returned from #open method'
129
133
  )
130
134
 
135
+ # Print the AUTHOR(S) string for this module.
131
136
  #{self}.authors
132
137
  "
138
+ constants.sort
133
139
  end
134
140
  end
135
141
  end
data/lib/pwn/www/torch.rb CHANGED
@@ -82,25 +82,30 @@ module PWN
82
82
 
83
83
  public_class_method def self.help
84
84
  puts "USAGE:
85
- browser_obj = #{self}.open(
86
- browser_type: 'optional :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
85
+ # Open a session or connection and return a handle.
86
+ #{self}.open(
87
+ browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
87
88
  proxy: 'optional - scheme://proxy_host:port || tor'
88
89
  )
89
90
 
90
- browser_obj = #{self}.open(
91
- q: 'required search string'
91
+ # Run a search using the open session.
92
+ #{self}.search(
93
+ browser_obj: 'required - browser_obj returned from #open method',
94
+ q: 'required - required search string'
92
95
  )
93
96
 
94
- browser_obj = #{self}.onion(
95
- browser_obj: 'required - browser_obj returned from #open method'
96
- )
97
+ # Run onion and return its result
98
+ #{self}.onion
97
99
 
98
- browser_obj = #{self}.close(
100
+ # Close a session previously returned by #open.
101
+ #{self}.close(
99
102
  browser_obj: 'required - browser_obj returned from #open method'
100
103
  )
101
104
 
105
+ # Print the AUTHOR(S) string for this module.
102
106
  #{self}.authors
103
107
  "
108
+ constants.sort
104
109
  end
105
110
  end
106
111
  end
@@ -100,27 +100,33 @@ module PWN
100
100
 
101
101
  public_class_method def self.help
102
102
  puts "USAGE:
103
- browser_obj = #{self}.open(
103
+ # Open a session or connection and return a handle.
104
+ #{self}.open(
104
105
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
105
106
  proxy: 'optional - scheme://proxy_host:port || tor'
106
107
  )
107
108
 
108
- browser_obj = #{self}.login(
109
+ # Run login and return its result
110
+ #{self}.login(
109
111
  browser_obj: 'required - browser_obj returned from #open method',
110
- username: 'required - username',
111
- password: 'optional - passwd (will prompt if blank),
112
+ username: 'required - username value consumed by #login',
113
+ password: 'optional - passwd (will prompt if blank)'
112
114
  )
113
115
 
114
- browser_obj = #{self}.logout(
116
+ # Run logout and return its result
117
+ #{self}.logout(
115
118
  browser_obj: 'required - browser_obj returned from #open method'
116
119
  )
117
120
 
121
+ # Close a session previously returned by #open.
118
122
  #{self}.close(
119
123
  browser_obj: 'required - browser_obj returned from #open method'
120
124
  )
121
125
 
126
+ # Print the AUTHOR(S) string for this module.
122
127
  #{self}.authors
123
128
  "
129
+ constants.sort
124
130
  end
125
131
  end
126
132
  end
@@ -110,28 +110,34 @@ module PWN
110
110
 
111
111
  public_class_method def self.help
112
112
  puts "USAGE:
113
- browser_obj = #{self}.open(
113
+ # Open a session or connection and return a handle.
114
+ #{self}.open(
114
115
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
115
116
  proxy: 'optional - scheme://proxy_host:port || tor'
116
117
  )
117
118
 
118
- browser_obj = #{self}.login(
119
+ # Run login and return its result
120
+ #{self}.login(
119
121
  browser_obj: 'required - browser_obj returned from #open method',
120
- username: 'required - username',
121
- password: 'optional - passwd (will prompt if blank),
122
+ username: 'required - username value consumed by #login',
123
+ password: 'optional - passwd (will prompt if blank)',
122
124
  mfa: 'optional - if true prompt for mfa token (defaults to false)'
123
125
  )
124
126
 
125
- browser_obj = #{self}.logout(
127
+ # Run logout and return its result
128
+ #{self}.logout(
126
129
  browser_obj: 'required - browser_obj returned from #open method'
127
130
  )
128
131
 
132
+ # Close a session previously returned by #open.
129
133
  #{self}.close(
130
134
  browser_obj: 'required - browser_obj returned from #open method'
131
135
  )
132
136
 
137
+ # Print the AUTHOR(S) string for this module.
133
138
  #{self}.authors
134
139
  "
140
+ constants.sort
135
141
  end
136
142
  end
137
143
  end
data/lib/pwn/www/uber.rb CHANGED
@@ -97,27 +97,33 @@ module PWN
97
97
 
98
98
  public_class_method def self.help
99
99
  puts "USAGE:
100
- browser_obj = #{self}.open(
100
+ # Open a session or connection and return a handle.
101
+ #{self}.open(
101
102
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
102
103
  proxy: 'optional - scheme://proxy_host:port || tor'
103
104
  )
104
105
 
105
- browser_obj = #{self}.login(
106
+ # Run login and return its result
107
+ #{self}.login(
106
108
  browser_obj: 'required - browser_obj returned from #open method',
107
- username: 'required - username',
108
- password: 'optional - passwd (will prompt if blank),
109
+ username: 'required - username value consumed by #login',
110
+ password: 'optional - passwd (will prompt if blank)'
109
111
  )
110
112
 
111
- browser_obj = #{self}.logout(
113
+ # Run logout and return its result
114
+ #{self}.logout(
112
115
  browser_obj: 'required - browser_obj returned from #open method'
113
116
  )
114
117
 
118
+ # Close a session previously returned by #open.
115
119
  #{self}.close(
116
120
  browser_obj: 'required - browser_obj returned from #open method'
117
121
  )
118
122
 
123
+ # Print the AUTHOR(S) string for this module.
119
124
  #{self}.authors
120
125
  "
126
+ constants.sort
121
127
  end
122
128
  end
123
129
  end
@@ -97,27 +97,33 @@ module PWN
97
97
 
98
98
  public_class_method def self.help
99
99
  puts "USAGE:
100
- browser_obj = #{self}.open(
100
+ # Open a session or connection and return a handle.
101
+ #{self}.open(
101
102
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
102
103
  proxy: 'optional - scheme://proxy_host:port || tor'
103
104
  )
104
105
 
105
- browser_obj = #{self}.login(
106
+ # Run login and return its result
107
+ #{self}.login(
106
108
  browser_obj: 'required - browser_obj returned from #open method',
107
- username: 'required - username',
108
- password: 'optional - passwd (will prompt if blank),
109
+ username: 'required - username value consumed by #login',
110
+ password: 'optional - passwd (will prompt if blank)'
109
111
  )
110
112
 
111
- browser_obj = #{self}.logout(
113
+ # Run logout and return its result
114
+ #{self}.logout(
112
115
  browser_obj: 'required - browser_obj returned from #open method'
113
116
  )
114
117
 
118
+ # Close a session previously returned by #open.
115
119
  #{self}.close(
116
120
  browser_obj: 'required - browser_obj returned from #open method'
117
121
  )
118
122
 
123
+ # Print the AUTHOR(S) string for this module.
119
124
  #{self}.authors
120
125
  "
126
+ constants.sort
121
127
  end
122
128
  end
123
129
  end
@@ -85,28 +85,34 @@ module PWN
85
85
 
86
86
  public_class_method def self.help
87
87
  puts "USAGE:
88
- browser_obj = #{self}.open(
88
+ # Open a session or connection and return a handle.
89
+ #{self}.open(
89
90
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
90
91
  proxy: 'optional - scheme://proxy_host:port || tor'
91
92
  )
92
93
 
93
- browser_obj = #{self}.search(
94
+ # Run a search using the open session.
95
+ #{self}.search(
94
96
  browser_obj: 'required - browser_obj returned from #open method',
95
- q: 'required search string'
97
+ q: 'required - search string'
96
98
  )
97
99
 
98
- browser_obj = #{self}.timetravel(
100
+ # Run timetravel and return its result
101
+ #{self}.timetravel(
99
102
  browser_obj: 'required - browser_obj returned from #open method',
100
103
  uri: 'required - URI (e.g. https://example.com)',
101
104
  date: 'optional - date in YYYYMMDD format (Defaults to today)'
102
105
  )
103
106
 
104
- browser_obj = #{self}.close(
105
- browser_obj: 'required - browser_obj returned from #open method',
107
+ # Close a session previously returned by #open.
108
+ #{self}.close(
109
+ browser_obj: 'required - browser_obj returned from #open method'
106
110
  )
107
111
 
112
+ # Print the AUTHOR(S) string for this module.
108
113
  #{self}.authors
109
114
  "
115
+ constants.sort
110
116
  end
111
117
  end
112
118
  end
@@ -66,22 +66,27 @@ module PWN
66
66
 
67
67
  public_class_method def self.help
68
68
  puts "USAGE:
69
- browser_obj = #{self}.open(
69
+ # Open a session or connection and return a handle.
70
+ #{self}.open(
70
71
  browser_type: 'optional - :firefox|:chrome|:ie|:headless (Defaults to :firefox)',
71
72
  proxy: 'optional - scheme://proxy_host:port || tor'
72
73
  )
73
74
 
74
- browser_obj = #{self}.search(
75
+ # Run a search using the open session.
76
+ #{self}.search(
75
77
  browser_obj: 'required - browser_obj returned from #open method',
76
- q: 'required search string'
78
+ q: 'required - search string'
77
79
  )
78
80
 
79
- browser_obj = #{self}.close(
80
- browser_obj: 'required - browser_obj returned from #open method',
81
+ # Close a session previously returned by #open.
82
+ #{self}.close(
83
+ browser_obj: 'required - browser_obj returned from #open method'
81
84
  )
82
85
 
86
+ # Print the AUTHOR(S) string for this module.
83
87
  #{self}.authors
84
88
  "
89
+ constants.sort
85
90
  end
86
91
  end
87
92
  end
data/lib/pwn/www.rb CHANGED
@@ -37,6 +37,10 @@ module PWN
37
37
  end
38
38
 
39
39
  public_class_method def self.help
40
+ puts "USAGE:
41
+ # Display a List of Every PWN::WWW Module
42
+ #{self}.authors
43
+ "
40
44
  constants.sort
41
45
  end
42
46
  end
@@ -43,6 +43,14 @@ require 'spec_helper'
43
43
  #
44
44
  # 5. Every leaf module file MUST define `def self.authors`.
45
45
  #
46
+ # 6. Every public class method except `help` MUST appear in that
47
+ # module's `help` method — including `authors`. Directly above each
48
+ # method, `help` MUST print a brief purpose line (what the method
49
+ # does). Methods that take `(opts = {})` MUST document each
50
+ # `opts[:key]` they read as `required` or `optional` plus an
51
+ # operator-usable description (what to pass, not just the key name)
52
+ # — same shape as PWN::WWW::Google.help.
53
+ #
46
54
  # A "leaf module file" is any file under lib/pwn/**/*.rb that opens at
47
55
  # least one `module` block. Pure namespace/index files (autoload-only,
48
56
  # no method bodies) are exempt from 4/5 via NAMESPACE_INDEX_FILES.
@@ -126,13 +134,26 @@ module PWNConventions
126
134
  line: idx + 1,
127
135
  decorator: m[2]&.strip,
128
136
  name: m[3],
129
- arglist: m[4], # nil = zero-arg endless or paren-less; '' = ()
130
- body_excerpt: lines[(idx + 1)..(idx + 60)]&.join.to_s
137
+ arglist: m[4],
138
+ body_excerpt: lines[(idx + 1)..(idx + 60)]&.join.to_s,
139
+ method_body: method_body_excerpt(lines, idx)
131
140
  }
132
141
  end
133
142
  out
134
143
  end
135
144
 
145
+ def method_body_excerpt(lines, idx)
146
+ indent = lines[idx][/^[ \t]*/]
147
+ buf = []
148
+ ((idx + 1)...lines.length).each do |i|
149
+ break if lines[i].match?(/^#{Regexp.escape(indent)}end\b/)
150
+
151
+ buf << lines[i]
152
+ break if buf.length >= 120
153
+ end
154
+ buf.join
155
+ end
156
+
136
157
  # Module-level bare `def name` only. Nested class instance methods and
137
158
  # class_eval / module_eval reopenings are legitimate and not part of the
138
159
  # PWN module API contract. Track open containers by indent so a plain
@@ -197,6 +218,63 @@ module PWNConventions
197
218
  ALL_BARE_DEFS = MODULE_FILES.flat_map { |f| scan_bare_defs(f) }.freeze
198
219
  ALL_MODULE_FUNCTIONS = MODULE_FILES.flat_map { |f| scan_module_function(f) }.freeze
199
220
 
221
+ HELP_SKIP = %w[help].freeze
222
+
223
+ def help_text(path)
224
+ lines = File.readlines(path)
225
+ idx = lines.find_index { |l| l.match?(/def self\.help\b/) }
226
+ return '' unless idx
227
+
228
+ indent = lines[idx][/^[ \t]*/]
229
+ buf = []
230
+ ((idx + 1)...lines.length).each do |i|
231
+ break if lines[i].match?(/^#{Regexp.escape(indent)}end\b/)
232
+
233
+ buf << lines[i]
234
+ end
235
+ buf.join
236
+ end
237
+
238
+ def opts_keys(body)
239
+ body.to_s.scan(/opts\[\s*:([A-Za-z_]\w*)\s*\]/).flatten.uniq
240
+ end
241
+
242
+ def thin_option_desc?(key, desc)
243
+ rest = desc.to_s.strip.sub(/\A(?:required|optional)\s*-\s*/i, '')
244
+ return true if rest.empty?
245
+
246
+ norm = rest.downcase.gsub(/[^a-z0-9]+/, ' ').strip
247
+ key_norm = key.to_s.downcase.tr('_', ' ')
248
+ return true if norm == key_norm
249
+
250
+ words = rest.split
251
+ words.length < 2 && rest.length < 18
252
+ end
253
+
254
+ def purpose_above?(help, name)
255
+ lines = help.to_s.lines
256
+ idx = lines.find_index { |l| l.match?(/\#\{self\}\.#{Regexp.escape(name)}(?!\w)/) }
257
+ return false unless idx
258
+
259
+ prev = nil
260
+ (idx - 1).downto(0) do |i|
261
+ next if lines[i].strip.empty?
262
+
263
+ prev = lines[i]
264
+ break
265
+ end
266
+ return false unless prev
267
+
268
+ text = prev.strip.sub(/\A#\s*/, '')
269
+ return false if text.match?(/\AUSAGE:/i)
270
+ return false if text.match?(/\.\w+\s*\(/) || text.match?(/\#\{self\}/)
271
+ return false if text.match?(/\A\w+\s*=\s*PWN::/)
272
+ return false if text.downcase.gsub(/[^a-z0-9]+/, ' ').strip == name.downcase.tr('_', ' ')
273
+
274
+ words = text.split
275
+ words.length >= 3 || text.length >= 20
276
+ end
277
+
200
278
  def rel(path)
201
279
  path.sub("#{ROOT}/", '')
202
280
  end
@@ -266,4 +344,42 @@ describe 'PWN module conventions' do
266
344
  msg = missing.map { |f| " #{c.rel(f)}" }.join("\n")
267
345
  expect(missing).to be_empty, "modules missing `def self.authors`:\n#{msg}"
268
346
  end
347
+
348
+ # ---------------------------------------------------------------- 6 --
349
+ it '6) every public class method is documented in help with required/optional options (Google.help shape)' do
350
+ misses = []
351
+ c::MODULE_FILES.each do |path|
352
+ next if c::NAMESPACE_INDEX_FILES.include?(c.rel(path))
353
+
354
+ help = c.help_text(path)
355
+ misses << "#{c.rel(path)} missing method authors in help" unless help.match?(/\.authors(?!\w)/)
356
+ pubs = c::ALL_METHODS.select do |m|
357
+ m[:file] == path &&
358
+ m[:decorator] == 'public_class_method' &&
359
+ !c::HELP_SKIP.include?(m[:name])
360
+ end
361
+ pubs.each do |meth|
362
+ name = meth[:name]
363
+ unless help.match?(/\.#{Regexp.escape(name)}(?!\w)/)
364
+ misses << "#{c.rel(path)} missing method #{name} in help"
365
+ next
366
+ end
367
+ misses << "#{c.rel(path)} #{name}: missing purpose line above the method in help" unless c.purpose_above?(help, name)
368
+ next unless meth[:arglist]&.strip == 'opts = {}'
369
+
370
+ c.opts_keys(meth[:method_body]).each do |key|
371
+ descs = help.scan(/#{Regexp.escape(key)}:\s*['"]((?:required|optional)\s*-\s*[^'"]+)/i).flatten
372
+ if descs.empty?
373
+ misses << "#{c.rel(path)} #{name} option #{key}: missing required/optional description"
374
+ next
375
+ end
376
+ next unless descs.any? { |d| c.thin_option_desc?(key, d) }
377
+
378
+ misses << "#{c.rel(path)} #{name} option #{key}: description too thin (say what to pass, not just the key name)"
379
+ end
380
+ end
381
+ end
382
+ extra = misses.length > 80 ? "\n... #{misses.length} total" : ''
383
+ expect(misses).to be_empty, "#{misses.first(80).join("\n")}#{extra}"
384
+ end
269
385
  end
@@ -399,4 +399,13 @@ describe 'PWN::AI::Agent::Reward vs TUI plan' do
399
399
  expect(a[:score]).to be >= 0.6
400
400
  expect(a[:verdict].to_s).to eq('solved')
401
401
  end
402
+
403
+ it 'does not drag a long analytical PASS to partial on zero token overlap' do
404
+ klass = PWN::AI::Agent::Reward
405
+ allow(klass).to receive(:llm_judge).and_return(nil)
406
+ req = 'Analyze the harness in which you currently reside and provide a summary of strengths / weaknesses.'
407
+ final = ('The control loop architecture is strong. Q-learning, calibration, anti-stall gates. ' * 20)
408
+ v = klass.judge(request: req, final: final, trace: ['{"success":true,"result":{"exit":0}}'], commit: false)
409
+ expect(v[:score]).to be > 0.35
410
+ end
402
411
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe PWN::Plugins::AFLplusplus do
6
+ it 'should display information for authors' do
7
+ expect(described_class).to respond_to :authors
8
+ end
9
+
10
+ it 'should display information for existing help method' do
11
+ expect(described_class).to respond_to :help
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe PWN::Plugins::ArtifactRegistry do
6
+ it 'should display information for authors' do
7
+ expect(described_class).to respond_to :authors
8
+ end
9
+
10
+ it 'should display information for existing help method' do
11
+ expect(described_class).to respond_to :help
12
+ end
13
+ end