pwn 0.5.387 → 0.5.390

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: 6276f7133a84a10851a85b44e5b21543de34abaec589011698c04667ede52f35
4
- data.tar.gz: b632de2f5bf6957b5ab1ce5f4408403a935a4fce1709bbcaa223d56962cef613
3
+ metadata.gz: 29455d0f44118f016d59ba4370e80b883a189d960697d2ad98f1c6d36b6b953d
4
+ data.tar.gz: bda5ff363c12e7b054daf8f71936d8d83ccf973c7e927333331e6107ddb9e4df
5
5
  SHA512:
6
- metadata.gz: bdc09c6f2b768550ab1c288bccab9e02c8008eb09769313f350719c19b8a4d87b6121116f481f013ee2ba2b978b79ccf5a81ec7a177f0f966103b810887e367b
7
- data.tar.gz: f6911fdab5cffa4038412815b4b8a1f5ccba48d6bd0b645900aa65b79138322c00945b6740c0f5f165bcb3169b2c54582ad0c5735b19d07ac68081e60eff2f23
6
+ metadata.gz: 885789f3328900c0e0cfee3c69a868a54851b9b156c61399a32f789daa767e1f33d5a1f4846d197832f76f8916da525cd40e564666691ed2489b495e0e47cc06
7
+ data.tar.gz: b25394c00e67546058cc7cc0b8da9cdf2b93a1165f4305ed056c5959907273f4b884607be987550095fd9fcae14bdacfd81a58a7e08c6381742cca2be6c947ee
data/.rubocop.yml CHANGED
@@ -2,7 +2,7 @@ AllCops:
2
2
  UseCache: false
3
3
  NewCops: enable
4
4
  Layout/LineLength:
5
- Max: 874
5
+ Max: 1620
6
6
  Lint/UselessRescue:
7
7
  Enabled: false
8
8
  Metrics/AbcSize:
@@ -16,7 +16,7 @@ Metrics/ClassLength:
16
16
  Metrics/CyclomaticComplexity:
17
17
  Max: 157
18
18
  Metrics/MethodLength:
19
- Max: 663
19
+ Max: 564
20
20
  Metrics/ModuleLength:
21
21
  Max: 1000
22
22
  Metrics/PerceivedComplexity:
data/Gemfile CHANGED
@@ -82,7 +82,7 @@ gem 'rmagick', '6.1.4'
82
82
  gem 'rqrcode', '3.1.0'
83
83
  gem 'rspec', '3.13.1'
84
84
  gem 'rtesseract', '3.1.4'
85
- gem 'rubocop', '1.80.0'
85
+ gem 'rubocop', '1.80.1'
86
86
  gem 'rubocop-rake', '0.7.1'
87
87
  gem 'rubocop-rspec', '3.6.0'
88
88
  gem 'ruby-audio', '1.6.1'
data/README.md CHANGED
@@ -37,7 +37,7 @@ $ cd /opt/pwn
37
37
  $ ./install.sh
38
38
  $ ./install.sh ruby-gem
39
39
  $ pwn
40
- pwn[v0.5.387]:001 >>> PWN.help
40
+ pwn[v0.5.390]:001 >>> PWN.help
41
41
  ```
42
42
 
43
43
  [![Installing the pwn Security Automation Framework](https://raw.githubusercontent.com/0dayInc/pwn/master/documentation/pwn_install.png)](https://youtu.be/G7iLUY4FzsI)
@@ -52,7 +52,7 @@ $ rvm use ruby-3.4.4@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.5.387]:001 >>> PWN.help
55
+ pwn[v0.5.390]:001 >>> PWN.help
56
56
  ```
57
57
 
58
58
  If you're using a multi-user install of RVM do:
@@ -62,7 +62,7 @@ $ rvm use ruby-3.4.4@pwn
62
62
  $ rvmsudo gem uninstall --all --executables pwn
63
63
  $ rvmsudo gem install --verbose pwn
64
64
  $ pwn
65
- pwn[v0.5.387]:001 >>> PWN.help
65
+ pwn[v0.5.390]:001 >>> PWN.help
66
66
  ```
67
67
 
68
68
  PWN periodically upgrades to the latest version of Ruby which is reflected in `/opt/pwn/.ruby-version`. The easiest way to upgrade to the latest version of Ruby from a previous PWN installation is to run the following script:
@@ -56,11 +56,7 @@ module PWN
56
56
  target_file = opts[:target_file].to_s
57
57
  target_file.gsub!(%r{^#{repo_root}/}, '')
58
58
 
59
- if File.directory?(repo_root) && File.file?("#{repo_root}/#{target_file}")
60
- `git --git-dir="#{Shellwords.escape(repo_root)}/.git" log -L #{from_line},#{to_line}:"#{Shellwords.escape(target_file)}" 2> /dev/null | grep Author | head -n 1`.to_s.scrub
61
- else
62
- -1
63
- end
59
+ `git --git-dir="#{Shellwords.escape(repo_root)}/.git" log -L #{from_line},#{to_line}:"#{Shellwords.escape(target_file)}" 2> /dev/null | grep Author | head -n 1`.to_s.scrub if File.directory?(repo_root) && File.file?("#{repo_root}/#{target_file}")
64
60
  rescue StandardError => e
65
61
  raise e
66
62
  end
@@ -120,7 +116,7 @@ module PWN
120
116
  )
121
117
  end
122
118
 
123
- author
119
+ author ||= 'N/A'
124
120
  rescue StandardError => e
125
121
  raise e
126
122
  end
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'barby'
4
- require 'rqrcode'
4
+ require 'base64'
5
+ require 'fileutils'
5
6
  require 'chunky_png'
7
+ require 'rqrcode'
6
8
 
7
9
  module PWN
8
10
  module Plugins
@@ -12,7 +14,9 @@ module PWN
12
14
  # response = PWN::Plugins::ScannableCodes.generate(
13
15
  # data: 'required - data to encode',
14
16
  # type: 'optional - :barcode || :qrcode (defaults to :qrcode)',
17
+ # size: 'optional - size of the image when type is :qrcode (defaults to 200)',
15
18
  # path: 'optional - path to save image (defaults to "./#{data}.png")'
19
+ # return_type: 'optional - :base64 || :file (defaults to :file)'
16
20
  # )
17
21
 
18
22
  public_class_method def self.generate(opts = {})
@@ -22,22 +26,34 @@ module PWN
22
26
  type = opts[:type]
23
27
  type ||= :qrcode
24
28
 
29
+ size = opts[:size]
30
+ raise 'ERROR: size is only applicable when type is :qrcode.' if size && type != :qrcode
31
+
25
32
  path = opts[:path]
26
33
  path ||= "./#{data}.png"
27
34
 
35
+ return_type = opts[:return_type] ||= :file
36
+
28
37
  case type
29
38
  when :barcode
30
39
  barcode = Barby::Code128B.new(data)
31
40
  barcode.to_png.save(path)
32
41
  when :qrcode
42
+ size ||= 200
33
43
  qrcode = RQRCode::QRCode.new(data)
34
44
  png = qrcode.as_png
35
- png.resize(200, 200).save(path)
45
+ png.resize(size, size).save(path)
36
46
  else
37
47
  raise 'ERROR: type must be :barcode or :qrcode.'
38
48
  end
39
49
 
40
- puts "Saved #{type} to #{path}"
50
+ data = "Saved #{type} to #{path}"
51
+ if return_type == :base64
52
+ data = Base64.strict_encode64(File.binread(path))
53
+ FileUtils.rm_f(path)
54
+ end
55
+
56
+ data
41
57
  rescue Interrupt
42
58
  puts "\nGoodbye."
43
59
  rescue StandardError => e
@@ -59,6 +75,7 @@ module PWN
59
75
  #{self}.generate(
60
76
  data: 'required - data to encode',
61
77
  type: 'optional - :barcode || :qrcode (defaults to :qrcode)',
78
+ size: 'optional - size of the image when type is :qrcode (defaults to 200)',
62
79
  path: 'optional - path to save image (defaults to \"./\#{data}.png\")'
63
80
  )
64
81
 
@@ -0,0 +1,255 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cgi'
4
+ require 'json'
5
+ require 'tty-spinner'
6
+
7
+ module PWN
8
+ module Reports
9
+ # This plugin generates the HTML header and includes external JS/CSS libraries for PWN reports.
10
+ module HTMLHeader
11
+ # Supported Method Parameters::
12
+ # PWN::Reports::HTMLHeader.generate(
13
+ # column_names: 'required - array of column names to use in the report table',
14
+ # driver_src_uri: 'required - pwn driver source code uri',
15
+ # )
16
+
17
+ public_class_method def self.generate(opts = {})
18
+ column_names = opts[:column_names] || []
19
+ driver_src_uri = opts[:driver_src_uri]
20
+ raise 'ERROR: :driver_src_uri must be provided' if driver_src_uri.nil? || driver_src_uri.strip == ''
21
+
22
+ driver_src_name = "~ #{driver_src_uri.to_s.split('/').last.gsub('_', ' ')}"
23
+
24
+ external_css_libraries = [
25
+ {
26
+ src: 'https://cdn.datatables.net/plug-ins/2.3.3/features/searchHighlight/dataTables.searchHighlight.css',
27
+ integrity: 'sha384-3FGcHDS9wKlVV/Pu4y1kojpLsNxlE3jQjdm1N0p7RC9f6xPdRAj78js3ELGiGP/j'
28
+ },
29
+ {
30
+ src: 'https://cdn.datatables.net/v/dt/jszip-3.10.1/dt-2.3.3/b-3.2.4/b-colvis-3.2.4/b-html5-3.2.4/b-print-3.2.4/fc-5.0.4/fh-4.0.3/kt-2.12.1/r-3.0.6/rg-1.5.2/rr-1.5.0/sc-2.4.3/sb-1.8.3/sp-2.3.5/sl-3.1.0/datatables.min.css',
31
+ integrity: 'sha384-51NLFpi/9qR2x0LAjQHiFAjV765f0g9+05EmKQ/QWINR/y3qonty8mPy68vEbo0z'
32
+ }
33
+ ]
34
+
35
+ external_js_libraries = [
36
+ {
37
+ src: 'https://code.jquery.com/jquery-3.7.1.min.js',
38
+ integrity: 'sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo='
39
+ },
40
+ {
41
+ src: 'https://cdn.jsdelivr.net/npm/datatables.mark.js@2.1.0/dist/datatables.mark.min.js',
42
+ integrity: 'sha384-1NNYvadWgPeE3tcSCdnI+3HB9iVqXwDBQsQUCUJTygTR3Whmz3HFkMn1kdevXe/F'
43
+ },
44
+ {
45
+ src: 'https://bartaz.github.io/sandbox.js/jquery.highlight.js',
46
+ integrity: 'sha384-COfjQfuLZw+Zvx+XMsYIVqsBHXPaUJnu/nwutbZvnI3zys8lUt3N3SUDsR6yu7ud'
47
+ },
48
+ {
49
+ src: 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js',
50
+ integrity: 'sha384-VFQrHzqBh5qiJIU0uGU5CIW3+OWpdGGJM9LBnGbuIH2mkICcFZ7lPd/AAtI7SNf7'
51
+ },
52
+ {
53
+ src: 'https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js',
54
+ integrity: 'sha384-/RlQG9uf0M2vcTw3CX7fbqgbj/h8wKxw7C3zu9/GxcBPRKOEcESxaxufwRXqzq6n'
55
+ },
56
+ {
57
+ src: 'https://cdn.datatables.net/v/dt/jszip-3.10.1/dt-2.3.3/b-3.2.4/b-colvis-3.2.4/b-html5-3.2.4/b-print-3.2.4/fc-5.0.4/fh-4.0.3/kt-2.12.1/r-3.0.6/rg-1.5.2/rr-1.5.0/sc-2.4.3/sb-1.8.3/sp-2.3.5/sl-3.1.0/datatables.min.js',
58
+ integrity: 'sha384-jvnxkXTB++rTO/pbg6w5nj0jm5HiSGtTcBW5vnoLGRfmSxw3eyqNA0bJ+m6Skjw/'
59
+ },
60
+ {
61
+ src: 'https://cdn.datatables.net/plug-ins/2.3.3/features/searchHighlight/dataTables.searchHighlight.min.js',
62
+ integrity: 'sha384-XDdmvsWg5e1/POTILjMFvB3KtrBqRk5W1CG9aoi1+K6bBMPHQAvlKEiekndU6CTp'
63
+ },
64
+ {
65
+ src: 'https://unpkg.com/exceljs@4.4.0/dist/exceljs.min.js',
66
+ integrity: 'sha384-Pqp51FUN2/qzfxZxBCtF0stpc9ONI6MYZpVqmo8m20SoaQCzf+arZvACkLkirlPz'
67
+ }
68
+ ]
69
+
70
+ markup = %(<!DOCTYPE HTML>
71
+ <html>
72
+ <head>
73
+ <!-- favicon.ico from https://0dayinc.com -->
74
+ <link rel="icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABIXAAASFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkAAACJAgAAiSYAAIlbAACJcAAAiX0AAIlmAACJLQAAiQQAAIkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkAAACJAAAAiS0AAIluAACJdwAAiXgAAIl+AACJeAAAiXQAAIk5AACJAQAAiQAAAAAAAAAAAAAAAAAAAAAAAACJAAAAiRgAAIlvAACJbQAAiXcAAIl7AACJcwAAiXEAAIl1AACJZwAAiR4AAIkAAACJAAAAAAAAAAAAAACJAAAAiQAAAIlEAACJfAAAiXIAAIlyAACJewAAiX4AAIl5AACJdQAAiXcAAIlIAACJAAAAiQAAAAAAAAAAAAAAiQAAAIkJAACJWQAAiXUAAIl9AACJdAAAiYYAAImLAACJdAAAiXkAAImNAACJfQAAiQwAAIkAAAAAAAAAAAAAAIkAAACJFQAAiWsAAIl2AACJfAAAiYIAAImCAACJfwAAiXYAAIl5AACJiQAAiYYAAIkWAACJAAAAAAAAAAAAAACJAAAAiSAAAIl2AACJeQAAiXkAAIl1AACJfwAAiYEAAIl8AACJbwAAiXoAAImBAACJFgAAiQAAAAAAAAAAAAAAiQAAAIkpAACJeAAAiXMAAIl3AACJeQAAiXUAAImAAACJfwAAiWYAAIl4AACJfwAAiR4AAIkAAAAAAAAAAAAAAIkAAACJKAAAiXkAAIlyAACJdQAAiXQAAIluAACJfAAAiXwAAIl3AACJewAAiXwAAIkvAACJAAAAAAAAAAAAAACJAAAAiSMAAIl4AACJdgAAiXsAAIl1AACJcQAAiXcAAIl6AACJeQAAiXoAAIl0AACJKQAAiQAAAAAAAAAAAAAAiQAAAIkXAACJaAAAiXgAAIl3AACJfAAAiXkAAIl3AACJZwAAiXcAAIl0AACJagAAiSgAAIkAAAAAAAAAAAAAAIkAAACJDgAAiV4AAIl5AACJbwAAiW4AAIl9AACJewAAiXcAAIl6AACJfQAAiW8AAIkWAACJAAAAAAAAAAAAAACJAAAAiQ0AAIllAACJewAAiXYAAIl4AACJdQAAiXUAAIl4AACJbQAAiXkAAIlNAACJAwAAiQAAAAAAAAAAAAAAiQAAAIkCAACJPQAAiXMAAIl2AACJeAAAiWgAAIlsAACJfQAAiXsAAIlwAACJGQAAiQAAAIkAAAAAAAAAAAAAAAAAAACJAAAAiQcAAIk4AACJXAAAiXoAAIl7AACJfAAAiYAAAIlsAACJJwAAiQMAAIkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkAAACJAQAAiSsAAIluAACJewAAiXwAAIluAACJKgAAiQAAAIkAAAAAAAAAAAAAAAAA8A8AAPAHAADgBwAA4AcAAMADAADAAwAAwAMAAMADAADAAwAAwAMAAMADAADAAwAAwAMAAMAHAADgBwAA8B8AAA==" type="image/x-icon" />
75
+ <style>
76
+ body {
77
+ font-family: Verdana, Geneva, sans-serif;
78
+ font-size: 11px;
79
+ background-color: #FFFFFF;
80
+ color: #084B8A !important;
81
+ }
82
+
83
+ a:link {
84
+ color: #0174DF;
85
+ text-decoration: none;
86
+ }
87
+
88
+ a:visited {
89
+ color: #B40404;
90
+ text-decoration: none;
91
+ }
92
+
93
+ a:hover {
94
+ color: #01A9DB;
95
+ text-decoration: underline;
96
+ }
97
+
98
+ a:active {
99
+ color: #610B5E;
100
+ text-decoration: underline;
101
+ }
102
+
103
+ div.toggle_col_and_button_group {
104
+ display: flex; /* Makes the container a flex container */
105
+ justify-content: none; /* Aligns items along the main axis */
106
+ align-items: flex-start; /* Aligns items to the start of the cross-axis */
107
+ width: 1275px !important;
108
+ }}
109
+
110
+ div.cols_to_toggle {
111
+ width: 300px !important;
112
+ text-align: left !important;
113
+ vertical-align: middle !important;
114
+ }
115
+
116
+ div.dt-buttons {
117
+ width: 420px !important;
118
+ text-align: right !important;
119
+ }
120
+
121
+ div.dt-container {
122
+ width: 1275px !important;
123
+ }
124
+
125
+ div.dt-scroll-body {
126
+ width: 1275px !important;
127
+ }
128
+
129
+ span.highlight {
130
+ background-color: cyan !important;
131
+ }
132
+ table {
133
+ width: 100%;
134
+ border-spacing:0px;
135
+ }
136
+
137
+ table.squish {
138
+ table-layout: fixed;
139
+ }
140
+
141
+ td {
142
+ vertical-align: top;
143
+ word-wrap: break-word !important;
144
+ border: none !important;
145
+ }
146
+
147
+ table.multi_line_select tr.odd {
148
+ background-color: #dedede !important; /* Gray for odd rows */
149
+ }
150
+
151
+ table.multi_line_select tr.even {
152
+ background-color: #ffffff !important; /* White for even rows */
153
+ }
154
+
155
+ tr.highlighted td {
156
+ background-color: #FFF396 !important;
157
+ }
158
+ </style>
159
+ )
160
+
161
+ external_css_libraries.each do |css_lib_hash|
162
+ css_lib = css_lib_hash[:src]
163
+ css_integrity = css_lib_hash[:integrity]
164
+ markup += %(
165
+ <link href="#{css_lib}" rel="stylesheet" integrity="#{css_integrity}" crossorigin="anonymous">
166
+ )
167
+ end
168
+
169
+ external_js_libraries.each do |js_lib|
170
+ js_src = js_lib[:src]
171
+ js_integrity = js_lib[:integrity]
172
+ markup += %(
173
+ <script type="text/javascript" src="#{js_src}" integrity="#{js_integrity}" crossorigin="anonymous"></script>
174
+ )
175
+ end
176
+
177
+ markup += %(
178
+ </head>
179
+ <body id="pwn_body">
180
+
181
+ <h1 style="display:inline">
182
+ <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIEAAACCCAQAAADLPWN1AAAAAXNSR0IB2cksfwAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAJiS0dEAIKpO8E+AAAACXBIWXMAAAsTAAALEwEAmpwYAAADTElEQVR42u2dyY7jMBBDqxrz/7+sOTRycCKJpOwBBsjzrWO3F4Ks3XKPUV++/dTXb3+qqjr8p1/i9HLPa2uxZ0z+6s011HXPngMWAAEQvGzBXK+fW6b+uUJ7ebTWuL7+yXPAAiB4E8IdurV5XObs1rLQEZ37HLAACKZCcLcrIe8QXFF7wAKEAAT/sS2oSWbnuqUOz55dFxYAwQNCyKi1iwdbuEudOq0j0A6jUlgABLYQ+saJVP1vHB1X0XFnzwELgAAIXrbgLMLS3YS2LMdZoWO2b8AChPB0mjRLQ9okX9tSWcuiTUepos2dbGmoIYSLEDRxXYur+0Pne3bRYZv3OXtCWAAEQFBGyUSVPa52ZCydZ5lO1tXz7nwl7xYWAMGbD/ocumvTEenUpc0oci2sLM4zHndyNCwAgjchtJlyKOK6SUt8s5GkdAxLmoQQgOCeU8wyOzevHNFv6fkomSAEu2Qyo4xKk3QXOROWS/fZddOBf1gABDI67JC4KkrLxmt3tQv3v1qKAxYAARBcbUE6OZzZhzKjtCzeO7MSRXSIEM7SJOWiRljOUCR1644loz7teBECQrikSSUJqbtESg6usLKY0+9E9fIasAAIgKA2M8juaNXM3eiO8RN5IywAgn8aHaoE5XTZjJNoUzvo7FqUTBCCIYQsQXKjSHdk485c+lnNkjQJIQDBzha4M4ZnTjGr+9fyumddbjrLCGGTJqWlEHeecOaclHx091rf3/o3OssIwagXeHTzaazjzKySoGoSPZUPLAACIHiiZDJu6F5Flm6mmHavVXZLdIgQ7OjQXZVGL+2kSe+ObHREc7ejDQuA4G0VCzcNcY+bRXPKgj9RhchqErAACICgNivjP1fDc2dJynSe2vWt+xyz54AFQBAu7ZS2vLJFNmbnc1t86RvRsAAITI+gBXG2LLyb6gzhiTqscTQsQAhAIG3BmcPyoj3nfCOKIl3b4rp1WAAEt76Vso4En3gXWb39nA7yUzJBCKEQUnvuRXO741Qi41r8sxEQWAAEQHDPFqy/cjduaPzsrbX1ne3WY4QFQLARwtMvQWWLx6VncqPX9W+wAAge/FbK2p5nn6PU4x6uRNzCOiwAAiCozdwhLAACIPiq7S/uVkwm4fz8nQAAAABJRU5ErkJggg==" type="image/png" style="iheight:70px;width:70px;"/>
183
+ <a href="#{driver_src_uri}" target="_blank">#{driver_src_name}</a>
184
+ </h1>
185
+ <h2 id="report_name"></h2><br />
186
+
187
+ <div id="toggle_col_and_button_group" class="toggle_col_and_button_group">
188
+ <div class="cols_to_toggle">
189
+ <b>Toggle Column(s) Visibility:</b>&nbsp;
190
+ )
191
+
192
+ last_column_idx = column_names.length - 1
193
+ column_names.each_with_index do |col, idx|
194
+ dat_col = idx + 1
195
+ encoded_col = CGI.escape_html(col)
196
+ if idx < last_column_idx
197
+ markup += %(
198
+ <a class="toggle-vis" data-column="#{dat_col}" href="#">#{encoded_col}</a>&nbsp;|&nbsp;
199
+ )
200
+ else
201
+ markup += %(
202
+ <a class="toggle-vis" data-column="#{dat_col}" href="#">#{encoded_col}</a>
203
+ )
204
+ end
205
+ end
206
+
207
+ markup += %(
208
+ </div>
209
+ </div>
210
+ <div class="dt-container">
211
+ <table id="pwn_results" class="display" cellspacing="0">
212
+ <thead>
213
+ <tr>
214
+ <th>#</th>
215
+ )
216
+
217
+ column_names.each do |col|
218
+ markup += %(
219
+ <th>#{col}</th>
220
+ )
221
+ end
222
+
223
+ markup += %(
224
+ </tr>
225
+ </thead>
226
+ <!-- DataTables <tbody> -->
227
+ </table>
228
+ </div>
229
+ )
230
+ rescue StandardError => e
231
+ raise e
232
+ end
233
+
234
+ # Author(s):: 0day Inc. <support@0dayinc.com>
235
+
236
+ public_class_method def self.authors
237
+ "AUTHOR(S):
238
+ 0day Inc. <support@0dayinc.com>
239
+ "
240
+ end
241
+
242
+ # Display Usage for this Module
243
+
244
+ public_class_method def self.help
245
+ puts "USAGE:
246
+ #{self}.generate(
247
+ column_names: 'Array of Column Names to use in the report table',
248
+ driver_src_uri: 're
249
+
250
+ #{self}.authors
251
+ "
252
+ end
253
+ end
254
+ end
255
+ end
@@ -127,140 +127,18 @@ module PWN
127
127
  JSON.pretty_generate(results_hash)
128
128
  )
129
129
 
130
- html_report = %{<!DOCTYPE HTML>
131
- <html>
132
- <head>
133
- <!-- favicon.ico from https://0dayinc.com -->
134
- <link rel="icon" href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABIXAAASFwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkAAACJAgAAiSYAAIlbAACJcAAAiX0AAIlmAACJLQAAiQQAAIkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkAAACJAAAAiS0AAIluAACJdwAAiXgAAIl+AACJeAAAiXQAAIk5AACJAQAAiQAAAAAAAAAAAAAAAAAAAAAAAACJAAAAiRgAAIlvAACJbQAAiXcAAIl7AACJcwAAiXEAAIl1AACJZwAAiR4AAIkAAACJAAAAAAAAAAAAAACJAAAAiQAAAIlEAACJfAAAiXIAAIlyAACJewAAiX4AAIl5AACJdQAAiXcAAIlIAACJAAAAiQAAAAAAAAAAAAAAiQAAAIkJAACJWQAAiXUAAIl9AACJdAAAiYYAAImLAACJdAAAiXkAAImNAACJfQAAiQwAAIkAAAAAAAAAAAAAAIkAAACJFQAAiWsAAIl2AACJfAAAiYIAAImCAACJfwAAiXYAAIl5AACJiQAAiYYAAIkWAACJAAAAAAAAAAAAAACJAAAAiSAAAIl2AACJeQAAiXkAAIl1AACJfwAAiYEAAIl8AACJbwAAiXoAAImBAACJFgAAiQAAAAAAAAAAAAAAiQAAAIkpAACJeAAAiXMAAIl3AACJeQAAiXUAAImAAACJfwAAiWYAAIl4AACJfwAAiR4AAIkAAAAAAAAAAAAAAIkAAACJKAAAiXkAAIlyAACJdQAAiXQAAIluAACJfAAAiXwAAIl3AACJewAAiXwAAIkvAACJAAAAAAAAAAAAAACJAAAAiSMAAIl4AACJdgAAiXsAAIl1AACJcQAAiXcAAIl6AACJeQAAiXoAAIl0AACJKQAAiQAAAAAAAAAAAAAAiQAAAIkXAACJaAAAiXgAAIl3AACJfAAAiXkAAIl3AACJZwAAiXcAAIl0AACJagAAiSgAAIkAAAAAAAAAAAAAAIkAAACJDgAAiV4AAIl5AACJbwAAiW4AAIl9AACJewAAiXcAAIl6AACJfQAAiW8AAIkWAACJAAAAAAAAAAAAAACJAAAAiQ0AAIllAACJewAAiXYAAIl4AACJdQAAiXUAAIl4AACJbQAAiXkAAIlNAACJAwAAiQAAAAAAAAAAAAAAiQAAAIkCAACJPQAAiXMAAIl2AACJeAAAiWgAAIlsAACJfQAAiXsAAIlwAACJGQAAiQAAAIkAAAAAAAAAAAAAAAAAAACJAAAAiQcAAIk4AACJXAAAiXoAAIl7AACJfAAAiYAAAIlsAACJJwAAiQMAAIkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIkAAACJAQAAiSsAAIluAACJewAAiXwAAIluAACJKgAAiQAAAIkAAAAAAAAAAAAAAAAA8A8AAPAHAADgBwAA4AcAAMADAADAAwAAwAMAAMADAADAAwAAwAMAAMADAADAAwAAwAMAAMAHAADgBwAA8B8AAA==" type="image/x-icon" />
135
- <style>
136
- body {
137
- font-family: Verdana, Geneva, sans-serif;
138
- font-size: 11px;
139
- background-color: #FFFFFF;
140
- color: #084B8A !important;
141
- }
142
-
143
- a:link {
144
- color: #0174DF;
145
- text-decoration: none;
146
- }
147
-
148
- a:visited {
149
- color: #B40404;
150
- text-decoration: none;
151
- }
152
-
153
- a:hover {
154
- color: #01A9DB;
155
- text-decoration: underline;
156
- }
157
-
158
- a:active {
159
- color: #610B5E;
160
- text-decoration: underline;
161
- }
162
-
163
- div.dt-container {
164
- width: 1275px !important;
165
- }
166
-
167
- div.dt-scroll-body {
168
- width: 1275px !important;
169
- }
170
-
171
- table {
172
- width: 100%;
173
- border-spacing:0px;
174
- }
175
-
176
- table.squish {
177
- table-layout: fixed;
178
- }
179
-
180
- td {
181
- vertical-align: top;
182
- word-wrap: break-word !important;
183
- border: none !important;
184
- }
185
-
186
- table.multi_line_select tr.odd {
187
- background-color: #dedede !important; /* Gray for odd rows */
188
- }
189
-
190
- table.multi_line_select tr.even {
191
- background-color: #ffffff !important; /* White for even rows */
192
- }
193
-
194
- tr.highlighted td {
195
- background-color: #FFF396 !important;
196
- }
197
- </style>
198
-
199
- <!-- jQuery & DataTables -->
200
- <script type="text/javascript" src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
201
-
202
- <link href="https://cdn.datatables.net/v/dt/jszip-3.10.1/dt-2.3.3/b-3.2.4/b-colvis-3.2.4/b-html5-3.2.4/b-print-3.2.4/fc-5.0.4/fh-4.0.3/kt-2.12.1/r-3.0.6/rg-1.5.2/rr-1.5.0/sc-2.4.3/sb-1.8.3/sp-2.3.5/sl-3.1.0/datatables.min.css" rel="stylesheet" integrity="sha384-51NLFpi/9qR2x0LAjQHiFAjV765f0g9+05EmKQ/QWINR/y3qonty8mPy68vEbo0z" crossorigin="anonymous">
203
-
204
- <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js" integrity="sha384-VFQrHzqBh5qiJIU0uGU5CIW3+OWpdGGJM9LBnGbuIH2mkICcFZ7lPd/AAtI7SNf7" crossorigin="anonymous"></script>
205
-
206
- <script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js" integrity="sha384-/RlQG9uf0M2vcTw3CX7fbqgbj/h8wKxw7C3zu9/GxcBPRKOEcESxaxufwRXqzq6n" crossorigin="anonymous"></script>
207
-
208
- <script src="https://cdn.datatables.net/v/dt/jszip-3.10.1/dt-2.3.3/b-3.2.4/b-colvis-3.2.4/b-html5-3.2.4/b-print-3.2.4/fc-5.0.4/fh-4.0.3/kt-2.12.1/r-3.0.6/rg-1.5.2/rr-1.5.0/sc-2.4.3/sb-1.8.3/sp-2.3.5/sl-3.1.0/datatables.min.js" integrity="sha384-jvnxkXTB++rTO/pbg6w5nj0jm5HiSGtTcBW5vnoLGRfmSxw3eyqNA0bJ+m6Skjw/" crossorigin="anonymous"></script>
209
-
210
- <script src="https://cdn.sheetjs.com/xlsx-0.20.2/package/dist/xlsx.full.min.js"></script>
211
-
212
- <!--
213
- <script type="text/javascript" src="//code.jquery.com/jquery-3.6.0.min.js"></script>
214
-
215
- <link rel="stylesheet" type="text/css" href="//cdn.datatables.net/v/dt/dt-1.11.4/b-2.2.2/b-colvis-2.2.2/b-html5-2.2.2/b-print-2.2.2/cr-1.5.5/fc-4.0.1/fh-3.2.1/kt-2.6.4/r-2.2.9/rg-1.1.4/rr-1.2.8/sc-2.0.5/sp-1.4.0/sl-1.3.4/datatables.min.css"/>
216
-
217
- <script type="text/javascript" src="//cdn.datatables.net/v/dt/dt-1.11.4/b-2.2.2/b-colvis-2.2.2/b-html5-2.2.2/b-print-2.2.2/cr-1.5.5/fc-4.0.1/fh-3.2.1/kt-2.6.4/r-2.2.9/rg-1.1.4/rr-1.2.8/sc-2.0.5/sp-1.4.0/sl-1.3.4/datatables.min.js"></script>
218
- -->
219
- </head>
220
-
221
- <body id="pwn_body">
222
-
223
- <h1 style="display:inline">
224
- <a href="https://github.com/0dayinc/pwn/tree/master">~ pwn sast</a>
225
- </h1><br /><br />
226
- <h2 id="report_name"></h2><br />
227
-
228
- <div class="dt-buttons" id="button_group">
229
- <!--<button type="button" id="debug_rows_selected">Rows Selected</button>-->
230
- </div>
231
-
232
- <div>
233
- <b>Toggle Column(s) Visibility:</b>&nbsp;
234
- <a class="toggle-vis" data-column="1" href="#">Timestamp</a>&nbsp;|&nbsp;
235
- <a class="toggle-vis" data-column="2" href="#">Test Case / Security References</a>&nbsp;|&nbsp;
236
- <a class="toggle-vis" data-column="3" href="#">Path</a>&nbsp;|&nbsp;
237
- <a class="toggle-vis" data-column="4" href="#">Line#, Formatted Content, AI Analysis, &amp; Last Committed By</a>&nbsp;|&nbsp;
238
- <a class="toggle-vis" data-column="5" href="#">Raw Content</a>&nbsp;|&nbsp;
239
- <a class="toggle-vis" data-column="6" href="#">Test Case (Anti-Pattern) Filter</a>
240
- </div>
241
- <br /><br />
242
-
243
- <div>
244
- Search tips: Use space-separated keywords for AND search, prefix with - to exclude (e.g., "security -password"), or enclose in / / for regex (e.g., "/^important.*$/i").
245
- </div><br />
246
-
247
- <div>
248
- <table id="pwn_scan_git_source_results" class="display" cellspacing="0">
249
- <thead>
250
- <tr>
251
- <th>#</th>
252
- <th>Timestamp</th>
253
- <th>Test Case / Security References</th>
254
- <th>Path</th>
255
- <th>Line#, Formatted Content, AI Analysis, &amp; Last Committed By</th>
256
- <th>Raw Content</th>
257
- <th>Test Case (Anti-Pattern) Filter</th>
258
- </tr>
259
- </thead>
260
- <!-- DataTables <tbody> -->
261
- </table>
262
- </div>
263
-
130
+ column_names = [
131
+ 'Timestamp',
132
+ 'Test Case / Security References',
133
+ 'Path',
134
+ 'Line# | Source | AI Analysis | Author',
135
+ 'Raw Content',
136
+ 'Test Case'
137
+ ]
138
+
139
+ driver_src_uri = 'https://github.com/0dayinc/pwn/blob/master/bin/pwn_sast'
140
+
141
+ html_report = %(#{PWN::Reports::HTMLHeader.generate(column_names: column_names, driver_src_uri: driver_src_uri)}
264
142
  <script>
265
143
  var htmlEntityEncode = $.fn.dataTable.render.text().display;
266
144
 
@@ -273,10 +151,11 @@ module PWN
273
151
  var offset = 400;
274
152
  var min_scroll_height = 100;
275
153
  var scrollYHeight = Math.max(min_scroll_height, windowHeight - offset); // Ensure minimum of 600px
276
- var table = $('#pwn_scan_git_source_results').DataTable( {
154
+ var table = $('#pwn_results').DataTable( {
277
155
  "order": [[2, 'asc']],
278
156
  "scrollY": scrollYHeight + "px",
279
157
  "scrollCollapse": true,
158
+ "searchHighlight": true,
280
159
  "paging": true,
281
160
  "lengthMenu": [25, 50, 100, 250, 500, 1000, 2500, 5000],
282
161
  "drawCallback": function () {
@@ -449,61 +328,52 @@ module PWN
449
328
  ]
450
329
  });
451
330
 
452
- table.buttons().container().insertAfter('#button_group');
331
+ table.buttons().container().appendTo('#toggle_col_and_button_group');
453
332
  }
454
333
  });
455
334
 
456
- $('#pwn_scan_git_source_results tbody').on('click', '.multi_line_select tr', function () {
335
+ $('#pwn_results tbody').on('click', '.multi_line_select tr', function () {
457
336
  $(this).toggleClass('highlighted');
458
337
  });
459
338
 
339
+ // Dynamically create the smart toggle label and input
340
+ var smartLabel = $('<label for="smart-toggle">Smart Search (e.g., "security !password")</label>');
341
+ var smartInput = $('<input type="radio" id="smart-toggle" name="searchMode" value="" checked>');
342
+ smartLabel.prepend(smartInput); // Prepend input inside label for proper association
343
+
344
+ // Dynamically create the regex toggle label and input
345
+ var regexLabel = $('<label for="regex-toggle">Regex Search (e.g., "^important.*$")</label>');
346
+ var regexInput = $('<input type="radio" id="regex-toggle" name="searchMode" value="">');
347
+ regexLabel.prepend(regexInput); // Prepend input inside label
348
+
349
+ // Now relocate them as before (insert before the search input)
350
+ smartLabel.insertBefore('#dt-search-0');
351
+ regexLabel.insertBefore('#dt-search-0');
352
+
353
+ // Style for inline display and spacing
354
+ smartLabel.css({ display: 'inline-block', marginRight: '10px' });
355
+ regexLabel.css({ display: 'inline-block', marginRight: '10px' });
356
+
357
+ // Optional: Hide the default "Search:" label if not needed
358
+ $('.dt-search label:first-of-type').hide();
359
+
460
360
  // Custom advanced search handling
461
- $('.dataTables_filter input').unbind();
462
- $('.dataTables_filter input').on('keyup', function() {
463
- var search = $(this).val();
464
-
465
- var filterFunc;
466
- if (search.match(/^\\/.*\\/$/)) {
467
- try {
468
- var regex = new RegExp(search.slice(1, -1), 'i');
469
- filterFunc = function(settings, data, dataIndex) {
470
- var rowData = data.join(' ');
471
- return regex.test(rowData);
472
- };
473
- } catch (e) {
474
- filterFunc = function(settings, data, dataIndex) {
475
- return true;
476
- };
477
- }
478
- } else {
479
- var positives = [];
480
- var negatives = [];
481
- var terms = search.split(/\\s+/).filter(function(t) { return t.length > 0; });
482
- for (var i = 0; i < terms.length; i++) {
483
- var term = terms[i];
484
- if (term.startsWith('-')) {
485
- var cleanTerm = term.substring(1).toLowerCase();
486
- if (cleanTerm) negatives.push(cleanTerm);
487
- } else {
488
- positives.push(term.toLowerCase());
489
- }
490
- }
491
- filterFunc = function(settings, data, dataIndex) {
492
- var rowData = data.join(' ').toLowerCase();
493
- for (var j = 0; j < positives.length; j++) {
494
- if (!rowData.includes(positives[j])) return false;
495
- }
496
- for (var k = 0; k < negatives.length; k++) {
497
- if (rowData.includes(negatives[k])) return false;
498
- }
499
- return true;
500
- };
501
- }
361
+ $('#dt-search-0').unbind();
362
+ $('#dt-search-0').on('input', function() {
363
+ var table = $('#pwn_results').DataTable();
364
+ var searchTerm = this.value;
365
+ var isRegex = $('#regex-toggle').prop('checked');
366
+ var isSmart = $('#smart-toggle').prop('checked');
367
+ table.search(searchTerm, isRegex, isSmart).draw();
368
+ });
502
369
 
503
- $.fn.dataTable.ext.search.pop();
504
- $.fn.dataTable.ext.search.push(filterFunc);
505
- table.search('');
506
- table.draw();
370
+ // Additionally, reapply search on toggle changes (assuming radios exist in HTML)
371
+ $('#regex-toggle, #smart-toggle').on('input', function() {
372
+ var table = $('#pwn_results').DataTable();
373
+ var searchTerm = this.value;
374
+ var isRegex = $('#regex-toggle').prop('checked');
375
+ var isSmart = $('#smart-toggle').prop('checked');
376
+ table.search(searchTerm, isRegex, isSmart).draw();
507
377
  });
508
378
 
509
379
  // Toggle Columns
@@ -523,10 +393,12 @@ module PWN
523
393
 
524
394
  // Select All and Deselect All
525
395
  function select_deselect_all() {
526
- if ($('.multi_line_select tr.highlighted').length === $('.multi_line_select tr').length) {
527
- $('.multi_line_select tr.highlighted').removeClass('highlighted');
396
+ var visible_multi_line_trs = $('#pwn_results tbody tr:visible .multi_line_select tr');
397
+ var highlighted_in_visible = visible_multi_line_trs.filter('.highlighted');
398
+ if (highlighted_in_visible.length === visible_multi_line_trs.length) {
399
+ highlighted_in_visible.removeClass('highlighted');
528
400
  } else {
529
- $('.multi_line_select tr:not(.highlighted)').addClass('highlighted');
401
+ visible_multi_line_trs.filter(':not(.highlighted)').addClass('highlighted');
530
402
  }
531
403
  }
532
404
 
@@ -614,6 +486,8 @@ module PWN
614
486
  test_case: row.security_references.sast_module.split('::')[2],
615
487
  nist_800_53_security_control: row.security_references.nist_800_53_uri,
616
488
  cwe: row.security_references.cwe_uri,
489
+ nist_section: row.security_references.section,
490
+ cwe_id: row.security_references.cwe_id,
617
491
  path: row.filename.entry,
618
492
  line_no: line.line_no,
619
493
  contents: line.contents,
@@ -627,63 +501,70 @@ module PWN
627
501
  var title = '~ pwn sast >>> ' + report_name + ' (Exported on ' + exportDate + ')';
628
502
 
629
503
  if (type === 'xlsx') {
630
- // Add title row
631
- var titleRow = [{ v: title, t: 's', s: { font: { sz: 14, bold: true }, alignment: { horizontal: 'center' } } }];
632
- var ws = XLSX.utils.json_to_sheet(flatData, {skipHeader: true});
633
- XLSX.utils.sheet_add_aoa(ws, [titleRow], {origin: 'A1'});
634
- XLSX.utils.sheet_add_json(ws, flatData, {origin: 'A2', skipHeader: false});
635
-
636
- // Merge title cell across columns
637
- if (!ws['!merges']) ws['!merges'] = [];
638
- ws['!merges'].push({s: {r:0, c:0}, e: {r:0, c:8}}); // A1 to I1
639
-
640
- // Set column widths by dividing desired column inches by 0.135
641
- // column inches observed with Exce
642
- // e.g 2.83 inches / 0.0135 ~ 209px
643
- ws['!cols'] = [
644
- {wpx: 209},
645
- {wpx: 130},
646
- {wpx: 580},
647
- {wpx: 256},
648
- {wpx: 110},
649
- {wpx: 40},
650
- {wpx: 370},
651
- {wpx: 370},
652
- {wpx: 185}
653
- ];
654
-
655
- // Style header row (row 2, since title at 1, header at 2, data from 3)
656
- var headerStyle = {
657
- font: { bold: true, color: { rgb: "000000" } },
658
- fill: { fgColor: { rgb: "999999" } },
659
- alignment: { horizontal: 'center', wrapText: true }
660
- };
661
- for (var col = 0; col < 9; col++) {
662
- var cellRef = XLSX.utils.encode_cell({r:1, c:col}); // Row 2 (0-based)
663
- if (ws[cellRef]) ws[cellRef].s = headerStyle;
664
- }
504
+ const workbook = new ExcelJS.Workbook();
505
+ const worksheet = workbook.addWorksheet('PWN SAST Results');
506
+
507
+ // Add title row and merge
508
+ worksheet.mergeCells('A1:I1');
509
+ const titleCell = worksheet.getCell('A1');
510
+ titleCell.value = title;
511
+ titleCell.font = { size: 14, bold: true };
512
+ titleCell.alignment = { horizontal: 'center' };
513
+
514
+ // Add header row
515
+ worksheet.addRow(['Timestamp', 'Test Case', 'NIST 800-53', 'CWE', 'Path', 'Line#', 'Content', 'AI Analysis', 'Author']);
516
+ const headerRow = worksheet.getRow(2);
517
+ headerRow.eachCell((cell) => {
518
+ cell.font = { bold: true, color: { argb: 'FF000000' } };
519
+ cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF999999' } };
520
+ cell.alignment = { horizontal: 'center', wrapText: true };
521
+ });
665
522
 
666
- // Alternate row colors for data rows (starting from row 3)
667
- var grayFill = { fgColor: { rgb: "DEDEDE" } };
668
- var whiteFill = { fgColor: { rgb: "FFFFFF" } };
669
- for (var rowNum = 3; rowNum < flatData.length + 2; rowNum++) { // Data rows 2-based from 3
670
- var fill = (rowNum % 2 === 0) ? whiteFill : grayFill;
671
- for (var col = 0; col < 9; col++) {
672
- var cellRef = XLSX.utils.encode_cell({r: rowNum, c: col});
673
- if (ws[cellRef]) {
674
- if (!ws[cellRef].s) ws[cellRef].s = {};
675
- ws[cellRef].s.fill = fill;
676
- ws[cellRef].s.alignment = { wrapText: true, vertical: 'top' };
677
- }
678
- }
679
- }
523
+ // Add data rows with alternating fills and hyperlinks
524
+ flatData.forEach((item, index) => {
525
+ const row = worksheet.addRow([
526
+ item.timestamp,
527
+ item.test_case,
528
+ { text: item.nist_section, hyperlink: item.nist_800_53_security_control },
529
+ { text: item.cwe_id, hyperlink: item.cwe },
530
+ item.path,
531
+ item.line_no,
532
+ item.contents,
533
+ item.ai_analysis,
534
+ item.author
535
+ ]);
536
+
537
+ const fill = (index % 2 === 0)
538
+ ? { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFDEDEDE' } }
539
+ : { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFFFFFFF' } };
540
+
541
+ row.eachCell((cell) => {
542
+ cell.fill = fill;
543
+ cell.alignment = { wrapText: true, vertical: 'top', horizontal: 'left' };
544
+ });
545
+ });
680
546
 
681
- // Freeze header
682
- ws['!freeze'] = { xSplit: 0, ySplit: 2 };
547
+ // Set column widths (converted from pixels to character units approx.)
548
+ const pixelWidthsInches = [1.0, 2.0, 4.5, 0.5, 2.5, 0.75, 3.5, 3.5, 2];
549
+ worksheet.columns = pixelWidthsInches.map(inches => {
550
+ let width;
551
+ width = inches / 0.077
552
+ return { width: width };
553
+ });
683
554
 
684
- var wb = XLSX.utils.book_new();
685
- XLSX.utils.book_append_sheet(wb, ws, 'PWN SAST Results');
686
- XLSX.writeFile(wb, report_name + '.xlsx');
555
+ // Freeze header
556
+ worksheet.views = [{ state: 'frozen', ySplit: 2 }];
557
+
558
+ // Generate and download the file
559
+ workbook.xlsx.writeBuffer().then(buffer => {
560
+ const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
561
+ const url = URL.createObjectURL(blob);
562
+ const a = document.createElement('a');
563
+ a.href = url;
564
+ a.download = report_name + '.xlsx';
565
+ a.click();
566
+ URL.revokeObjectURL(url);
567
+ });
687
568
  } else if (type === 'pdf') {
688
569
  var docDefinition = {
689
570
  pageOrientation: 'landscape',
@@ -716,8 +597,8 @@ module PWN
716
597
  ...flatData.map(r => [
717
598
  r.timestamp,
718
599
  r.test_case,
719
- r.nist_800_53_security_control,
720
- r.cwe,
600
+ { text: r.nist_section, link: r.nist_800_53_security_control, style: {decoration: 'underline'} },
601
+ { text: r.cwe_id, link: r.cwe, style: {decoration: 'underline'} },
721
602
  r.path,
722
603
  r.line_no,
723
604
  r.contents,
@@ -761,7 +642,6 @@ module PWN
761
642
  }
762
643
  });
763
644
  }
764
-
765
645
  // Detect window size changes and recalculate/update scrollY
766
646
  $(window).resize(function() {
767
647
  var newWindowHeight = $(window).height();
@@ -773,7 +653,7 @@ module PWN
773
653
  </script>
774
654
  </body>
775
655
  </html>
776
- }
656
+ )
777
657
 
778
658
  File.open("#{dir_path}/#{report_name}.html", 'w') do |f|
779
659
  f.print(html_report)
data/lib/pwn/reports.rb CHANGED
@@ -9,6 +9,7 @@ module PWN
9
9
  # autoload :JSON, 'pwn/reports/json'
10
10
  # autoload :PDF, 'pwn/reports/pdf'
11
11
  autoload :Fuzz, 'pwn/reports/fuzz'
12
+ autoload :HTMLHeader, 'pwn/reports/html_header'
12
13
  autoload :Phone, 'pwn/reports/phone'
13
14
  autoload :SAST, 'pwn/reports/sast'
14
15
  autoload :URIBuster, 'pwn/reports/uri_buster'
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.387'
4
+ VERSION = '0.5.390'
5
5
  end
data/pwn.gemspec CHANGED
@@ -59,6 +59,9 @@ Gem::Specification.new do |spec|
59
59
  gem_name = columns[1].delete("'").delete(',')
60
60
  gem_version = columns.last.delete("'")
61
61
 
62
+ # Good for debugging issues in Gemfile
63
+ # puts "pwn.gemspec: Adding dependency: #{gem_name} #{gem_version}"
64
+
62
65
  if dev_dependency_arr.include?(gem_name.to_sym)
63
66
  spec.add_development_dependency(
64
67
  gem_name,
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe PWN::Reports::HTMLHeader do
6
+ it 'should display information for authors' do
7
+ authors_response = PWN::Reports::HTMLHeader
8
+ expect(authors_response).to respond_to :authors
9
+ end
10
+
11
+ it 'should display information for existing help method' do
12
+ help_response = PWN::Reports::HTMLHeader
13
+ expect(help_response).to respond_to :help
14
+ end
15
+ end
@@ -901,7 +901,7 @@
901
901
  {"messages":[{"role":"user","content":"PWN::Plugins::SSN.generate Usage"},{"role":"assistant","content":"`PWN::Plugins::SSN.generate`: Supported Method Parameters\n\nPWN::Plugins::SSN.generate(\n\ncount: 'required - number of SSN numbers to generate'\n\n)\n"}]}
902
902
  {"messages":[{"role":"user","content":"PWN::Plugins::SSN.help Usage"},{"role":"assistant","content":"`PWN::Plugins::SSN.help`: "}]}
903
903
  {"messages":[{"role":"user","content":"PWN::Plugins::ScannableCodes.authors Usage"},{"role":"assistant","content":"`PWN::Plugins::ScannableCodes.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
904
- {"messages":[{"role":"user","content":"PWN::Plugins::ScannableCodes.generate Usage"},{"role":"assistant","content":"`PWN::Plugins::ScannableCodes.generate`: Supported Method Parameters\n\nresponse = PWN::Plugins::ScannableCodes.generate(\n\ndata: 'required - data to encode',\ntype: 'optional - :barcode || :qrcode (defaults to :qrcode)',\npath: 'optional - path to save image (defaults to \"./#{data}.png\")'\n\n)\n"}]}
904
+ {"messages":[{"role":"user","content":"PWN::Plugins::ScannableCodes.generate Usage"},{"role":"assistant","content":"`PWN::Plugins::ScannableCodes.generate`: Supported Method Parameters\n\nresponse = PWN::Plugins::ScannableCodes.generate(\n\ndata: 'required - data to encode',\ntype: 'optional - :barcode || :qrcode (defaults to :qrcode)',\nsize: 'optional - size of the image when type is :qrcode (defaults to 200)',\npath: 'optional - path to save image (defaults to \"./#{data}.png\")'\nreturn_type: 'optional - :base64 || :file (defaults to :file)'\n\n)\n"}]}
905
905
  {"messages":[{"role":"user","content":"PWN::Plugins::ScannableCodes.help Usage"},{"role":"assistant","content":"`PWN::Plugins::ScannableCodes.help`: "}]}
906
906
  {"messages":[{"role":"user","content":"PWN::Plugins::Serial.authors Usage"},{"role":"assistant","content":"`PWN::Plugins::Serial.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
907
907
  {"messages":[{"role":"user","content":"PWN::Plugins::Serial.connect Usage"},{"role":"assistant","content":"`PWN::Plugins::Serial.connect`: Supported Method Parameters\n\nserial_obj = PWN::Plugins::Serial.connect(\n\nblock_dev: 'optional - serial block device path (defaults to /dev/ttyUSB0)',\nbaud: 'optional - (defaults to 9600)',\ndata_bits: 'optional - (defaults to 8)',\nstop_bits: 'optional - (defaults to 1)',\nparity: 'optional - :even|:mark|:odd|:space|:none (defaults to :none)'\n\n)\n"}]}
@@ -1053,9 +1053,7 @@
1053
1053
  {"messages":[{"role":"user","content":"PWN::Reports::Phone.authors Usage"},{"role":"assistant","content":"`PWN::Reports::Phone.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
1054
1054
  {"messages":[{"role":"user","content":"PWN::Reports::Phone.generate Usage"},{"role":"assistant","content":"`PWN::Reports::Phone.generate`: Supported Method Parameters\n\nPWN::Reports::Phone.generate(\n\ndir_path: dir_path,\nresults_hash: results_hash\n\n)\n"}]}
1055
1055
  {"messages":[{"role":"user","content":"PWN::Reports::Phone.help Usage"},{"role":"assistant","content":"`PWN::Reports::Phone.help`: "}]}
1056
- {"messages":[{"role":"user","content":"PWN::Reports::SAST.authors Usage"},{"role":"assistant","content":"`PWN::Reports::SAST.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
1057
1056
  {"messages":[{"role":"user","content":"PWN::Reports::SAST.generate Usage"},{"role":"assistant","content":"`PWN::Reports::SAST.generate`: Supported Method Parameters\n\nPWN::Reports::SAST.generate(\n\ndir_path: 'optional - Directory path to save the report (defaults to .)',\nresults_hash: 'optional - Hash containing the results of the SAST analysis (defaults to empty hash structure)',\nreport_name: 'optional - Name of the report file (defaults to current directory name)',\nai_engine: 'optional - AI engine to use for analysis (:grok, :ollama, or :openai)',\nai_model: 'optionnal - AI Model to Use for Respective AI Engine (e.g., grok-4i-0709, chargpt-4o-latest, llama-3.1, etc.)',\nai_key: 'optional - AI Key/Token for Respective AI Engine',\nai_fqdn: 'optional - AI FQDN (Only Required for \"ollama\" AI Engine)',\nai_system_role_content: 'optional - AI System Role Content (Defaults to \"Is this code vulnerable or a false positive? Valid responses are only: \"VULNERABLE\" or \"FALSE+\". DO NOT PROVIDE ANY OTHER TEXT OR EXPLANATIONS.\")',\nai_temp: 'optional - AI Temperature (Defaults to 0.9)'\n\n)\n"}]}
1058
- {"messages":[{"role":"user","content":"PWN::Reports::SAST.help Usage"},{"role":"assistant","content":"`PWN::Reports::SAST.help`: "}]}
1059
1057
  {"messages":[{"role":"user","content":"PWN::Reports::URIBuster.authors Usage"},{"role":"assistant","content":"`PWN::Reports::URIBuster.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
1060
1058
  {"messages":[{"role":"user","content":"PWN::Reports::URIBuster.generate Usage"},{"role":"assistant","content":"`PWN::Reports::URIBuster.generate`: Supported Method Parameters\n\nPWN::Reports::URIBuster.generate(\n\ndir_path: dir_path,\nresults_hash: results_hash\n\n)\n"}]}
1061
1059
  {"messages":[{"role":"user","content":"PWN::Reports::URIBuster.help Usage"},{"role":"assistant","content":"`PWN::Reports::URIBuster.help`: "}]}
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.387
4
+ version: 0.5.390
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -939,14 +939,14 @@ dependencies:
939
939
  requirements:
940
940
  - - '='
941
941
  - !ruby/object:Gem::Version
942
- version: 1.80.0
942
+ version: 1.80.1
943
943
  type: :runtime
944
944
  prerelease: false
945
945
  version_requirements: !ruby/object:Gem::Requirement
946
946
  requirements:
947
947
  - - '='
948
948
  - !ruby/object:Gem::Version
949
- version: 1.80.0
949
+ version: 1.80.1
950
950
  - !ruby/object:Gem::Dependency
951
951
  name: rubocop-rake
952
952
  requirement: !ruby/object:Gem::Requirement
@@ -1900,6 +1900,7 @@ files:
1900
1900
  - lib/pwn/plugins/xxd.rb
1901
1901
  - lib/pwn/reports.rb
1902
1902
  - lib/pwn/reports/fuzz.rb
1903
+ - lib/pwn/reports/html_header.rb
1903
1904
  - lib/pwn/reports/phone.rb
1904
1905
  - lib/pwn/reports/sast.rb
1905
1906
  - lib/pwn/reports/uri_buster.rb
@@ -2242,6 +2243,7 @@ files:
2242
2243
  - spec/lib/pwn/plugins/xxd_spec.rb
2243
2244
  - spec/lib/pwn/plugins_spec.rb
2244
2245
  - spec/lib/pwn/reports/fuzz_spec.rb
2246
+ - spec/lib/pwn/reports/html_header_spec.rb
2245
2247
  - spec/lib/pwn/reports/phone_spec.rb
2246
2248
  - spec/lib/pwn/reports/sast_spec.rb
2247
2249
  - spec/lib/pwn/reports/uri_buster_spec.rb