RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/rapid7/metasploit-framework/diff

Two files, one repository

rapid7/metasploit-framework ships 2 formats across 6 indexed files. The question worth asking is whether the second one says anything the first does not.

CompareAGENTS.md ↔ Copilot instructions
A · AGENTS.md · 2929 wordsB · .github/copilot-instructions.md · 34 words
What each file covers, counted
DimensionSharedOnly in AOnly in BOverlap
Sections03110%
Commands0300%
Section tags16014%

What each file covers

Sections

0 shared · 31 only in A · 1 only in B
  • − AI Agent Instructions for Metasploit Framework
  • − Project Overview
  • − Project Structure
  • − Coding Conventions
  • − Module Structure Templates
  • − Exploit Module Template
  • − # This module requires Metasploit: https://metasploit.com/download
  • − Current source: https://github.com/rapid7/metasploit-framework
  • − class MetasploitModule < Msf::Exploit::Remote
  • − Auxiliary Module Template
  • − Post Module Template
  • − Notes Hash Reference
  • − Metadata Source Reference
  • − Mixin Ordering
  • − Module Development
  • − Check Methods
  • − Library Code
  • − Testing
  • − Preferred Libraries
  • − Common Patterns
  • − Options Registration
  • − Console Output
  • − HTTP Response Handling
  • − For HTML parsing:
  • − Network Operations
  • − Legacy Patterns (Migration Guidance)
  • − Modernizing Existing Modules
  • − If the module already has a `def check` method, just add this line
  • − after the other includes:
  • − Before Submitting
  • − What NOT to Do
  • + Copilot Instructions

Commands

0 shared · 3 only in A · 0 only in B
  • − bundle exec rspec spec/path/to/spec.rb
  • − bundle exec rspec spec/path/to/spec.rb:42
  • − bundle exec rake spec

Section tags

1 shared · 6 only in A · 0 only in B
  • − test
  • − code-style
  • − architecture
  • − git-pr
  • − dependencies
  • − database
  •   agent-behaviour

Line diff

+3 added−442 removed3 unchanged0.7% identical
rapid7/metasploit-framework · AGENTS.md
@@ −1 @@
1# AI Agent Instructions for Metasploit Framework
2 
3## Project Overview
4 
5Metasploit Framework is an open-source penetration testing and exploitation framework written in Ruby. It provides infrastructure for developing, testing, and executing exploit code against remote targets.
6 
7## Project Structure
8 
9- `modules/` — Metasploit modules (exploits, auxiliary, post, payloads, encoders, evasion, nops)
10- `lib/msf/` — Core framework library code
11- `lib/rex/` — Rex (Ruby Exploitation) library
12- `lib/metasploit/` — Metasploit namespace libraries
13- `data/` — Data files used by modules (wordlists, templates, binaries)
14- `spec/` — RSpec test suite
15- `tools/` — Developer and operational tools
16- `plugins/` — msfconsole plugins
17- `scripts/` — Example automation scripts
18- `documentation/modules/` — Markdown documentation for Metasploit modules
19 
20## Coding Conventions
21 
22- Ruby (see `.ruby-version` for the current version). Minimum supported: 3.1+
23- Follow the project's `.rubocop.yml` configuration — run `rubocop` on changed files before submitting
24- Run `ruby tools/dev/msftidy.rb <module_file_path>` to catch common module issues
25- `# frozen_string_literal: true` — add to new **library** files (`lib/`); use `String.new` where a mutable string is needed. Do NOT add to module files or spec files (the framework extensively mutates string buffers via instance variables, and the RuboCop cop `Style/FrozenStringLiteralComment` is disabled project-wide). Existing files that already have it are fine to leave
26- No enforced line length limit, but keep code readable
27- Use `%q{}` for long multi-line strings (curly braces preferred for module descriptions)
28- Multiline block comments are acceptable for embedded code snippets/payloads
29- Don't use `get_`/`set_` prefixes for accessor methods in new code
30- Method parameter names must be at least 2 characters (exception for well-known crypto abbreviations)
31 
32## Module Structure Templates
33 
34### Exploit Module Template
35 
36New exploit modules should follow this canonical structure and ordering:
37 
38```ruby
39##
40# This module requires Metasploit: https://metasploit.com/download
41# Current source: https://github.com/rapid7/metasploit-framework
42##
43 
44class MetasploitModule < Msf::Exploit::Remote
45 Rank = ExcellentRanking
46 
47 # 1. Protocol mixins first
48 include Msf::Exploit::Remote::HttpClient
49 # 2. Utility/feature mixins second
50 include Msf::Exploit::FileDropper
51 # 3. Reporting mixins (if needed)
52 # include Msf::Auxiliary::Report
53 # 4. AutoCheck ALWAYS LAST — must be prepend, not include
54 prepend Msf::Exploit::Remote::AutoCheck
55 
56 def initialize(info = {})
57 super(
58 update_info(
59 info,
60 'Name' => 'Vendor Product Vulnerability Type',
61 'Description' => %q{
62 Description of the vulnerability and what this module does.
63 },
64 'Author' => [
65 'Discoverer Name', # Vulnerability discovery
66 'Module Author' # Metasploit module
67 ],
68 'License' => MSF_LICENSE,
69 'References' => [
70 ['CVE', '2024-XXXXX'],
71 ['URL', 'https://example.com/advisory']
72 ],
73 'Targets' => [
74 [
75 'Automatic',
76 {
77 'Platform' => ['linux'], # or 'win', 'osx', 'unix', 'php', 'python', 'java'
78 'Arch' => [ARCH_CMD], # or ARCH_X86, ARCH_X64, ARCH_PHP, ARCH_JAVA, ARCH_PYTHON, ARCH_ARMLE, ARCH_AARCH64, ARCH_MIPSLE — see rex-arch gem for full list
79 'Type' => :cmd # or :dropper, :psh_stager — determines payload delivery
80 }
81 ]
82 ],
83 'DefaultTarget' => 0,
84 'DisclosureDate' => '2024-01-01',
85 'Notes' => {
86 'Stability' => [], # e.g. CRASH_SAFE, CRASH_SERVICE_RESTARTS
87 'SideEffects' => [], # e.g. IOC_IN_LOGS, ARTIFACTS_ON_DISK
88 'Reliability' => [] # e.g. REPEATABLE_SESSION
89 }
90 )
91 )
92 end
93 
94 def check
95 # Always return CheckCode with a reason string
96 CheckCode::Safe('Target is not vulnerable')
97 end
98 
99 def exploit
100 # Exploitation logic
101 end
102end
103```
104 
105### Auxiliary Module Template
106 
107Auxiliary modules use `def run` (not `exploit`) and inherit from `Msf::Auxiliary`:
108 
109```ruby
110class MetasploitModule < Msf::Auxiliary
111 include Msf::Exploit::Remote::HttpClient
112 include Msf::Auxiliary::Report
113 prepend Msf::Exploit::Remote::AutoCheck
114 
115 def initialize(info = {})
116 super(
117 update_info(
118 info,
119 'Name' => 'Vendor Product Scanner/Gatherer',
120 'Description' => %q{
121 Description of what this module discovers or does.
122 },
123 'Author' => ['Author Name'],
124 'License' => MSF_LICENSE,
125 'References' => [['CVE', '2024-XXXXX']],
126 'Notes' => {
127 'Stability' => [], # e.g. CRASH_SAFE
128 'SideEffects' => [], # e.g. IOC_IN_LOGS
129 'Reliability' => [] # e.g. REPEATABLE_SESSION
130 }
131 )
132 )
133 
134 register_options([
135 OptString.new('TARGETURI', [true, 'Base path', '/'])
136 ])
137 end
138 
139 def check
140 CheckCode::Safe('Target is not affected')
141 end
142 
143 def run
144 # Main logic — use report_service, report_vuln, print_good, etc.
145 end
146end
147```
148 
149### Post Module Template
150 
151Post modules inherit from `Msf::Post`, require a session, and declare compatible session types:
152 
153```ruby
154class MetasploitModule < Msf::Post
155 include Msf::Post::File
156 include Msf::Post::Linux::System
157 
158 def initialize(info = {})
159 super(
160 update_info(
161 info,
162 'Name' => 'Platform Subsystem Gather/Action',
163 'Description' => %q{
164 Description of what this post module does on the target.
165 },
166 'Author' => ['Author Name'],
167 'License' => MSF_LICENSE,
168 'Platform' => ['linux'], # or 'win', 'osx', 'unix', 'bsd', 'solaris'
169 'SessionTypes' => ['meterpreter', 'shell'], # or just ['meterpreter'] if shell won't work
170 'Notes' => {
171 'Stability' => [], # e.g. CRASH_SAFE
172 'SideEffects' => [], # e.g. ARTIFACTS_ON_DISK, CONFIG_CHANGES
173 'Reliability' => []
174 }
175 )
176 )
177 end
178 
179 def run
180 # Use create_process, file_exist?, read_file, etc.
181 # Access session via `session` method
182 end
183end
184```
185 
186### Notes Hash Reference
187 
188The `Notes` hash declares the module's operational characteristics:
189 
190| Key | Values | Meaning |
191|-----|--------|---------|
192| `Stability` | `CRASH_SAFE`, `CRASH_SERVICE_RESTARTS`, `CRASH_SERVICE_DOWN`, `CRASH_OS_RESTARTS`, `CRASH_OS_DOWN` | Impact on target stability |
193| `SideEffects` | `IOC_IN_LOGS`, `ARTIFACTS_ON_DISK`, `CONFIG_CHANGES`, `ACCOUNT_LOCKOUTS`, `SCREEN_EFFECTS`, `AUDIO_EFFECTS`, `PHYSICAL_EFFECTS` | Observable traces left on target |
194| `Reliability` | `REPEATABLE_SESSION`, `FIRST_ATTEMPT_FAIL`, `UNRELIABLE_SESSION`, `EVENT_DEPENDENT` | How reliably the module succeeds |
195 
196See also: [`lib/msf/core/constants.rb`](lib/msf/core/constants.rb) for the full list of valid values with descriptions.
197 
198**Which module types require Notes:**
199 
200| Module Type | Notes Required? | Enforced By |
201|-------------|----------------|-------------|
202| Exploit | **Yes** | msftidy + rubocop (`Lint/ModuleEnforceNotes`) |
203| Auxiliary | **Yes** | rubocop (`Lint/ModuleEnforceNotes`) |
204| Post | **Yes** | rubocop (`Lint/ModuleEnforceNotes`) |
205| Evasion | No | — |
206| Payload | No | — |
207| Encoder | No | — |
208| Nop | No | — |
209 
210The same `Stability`, `SideEffects`, and `Reliability` constants apply uniformly — there are no type-specific values. Payloads, encoders, and nops don't use Notes because they don't independently interact with targets.
211 
212### Metadata Source Reference
213 
214The inline comments in the templates above list common values but are **not exhaustive**. Consult these source files for the full set:
215 
216| Field | Source File | Notes |
217|-------|------------|-------|
218| Platform | [`lib/msf/core/module/platform.rb`](lib/msf/core/module/platform.rb) | Class hierarchy — use the lowercase short name (e.g. `'linux'`, `'win'`, `'osx'`) |
219| Arch | [`rex-arch` gem](https://github.com/rapid7/rex-arch/blob/master/lib/rex/arch.rb) | Constants like `ARCH_CMD`, `ARCH_X86`, `ARCH_X64`, `ARCH_PHP` etc. |
220| Stability / SideEffects / Reliability | [`lib/msf/core/constants.rb`](lib/msf/core/constants.rb) | All valid Notes hash values with descriptions |
221| Rank | [`lib/msf/core/constants.rb`](lib/msf/core/constants.rb) | `ManualRanking` through `ExcellentRanking` |
222| CheckCode | [`lib/msf/core/exploit.rb`](lib/msf/core/exploit.rb) (line ~52) | `Vulnerable`, `Appears`, `Safe`, `Detected`, `Unknown`, `Unsupported` |
223 
224### Mixin Ordering
225 
226Follow this order for includes and prepends in module classes:
227 
2281. **Protocol mixins** — `Msf::Exploit::Remote::HttpClient`, `RubySMB`, `Msf::Exploit::Remote::Udp`, etc.
2292. **Utility/feature mixins** — `Msf::Exploit::FileDropper`, `Msf::Exploit::CmdStager`, `Msf::Exploit::EXE`, etc.
2303. **Reporting mixins** — `Msf::Auxiliary::Report`
2314. **Post mixins** (if needed) — `Msf::Post::File`, `Msf::Post::Linux::Priv`, etc.
2325. **`prepend Msf::Exploit::Remote::AutoCheck`** — always last, after all includes
233 
234AutoCheck must use `prepend`, not `include` (the module raises `NotImplementedError` if included). It wraps the `exploit`/`run` method to automatically call `check` before exploitation.
235 
236### Module Development
237 
238#### Metadata and Structure
239 
240- Prefer writing modules in Ruby. Go and Python modules are accepted, but their external runtimes don't support the full framework API (e.g. network pivoting). Ruby modules do not have this limitation
241- Prefer using hash over an array for return values, and use kwargs for reusable APIs for future extensions
242- Before writing a new module, check that there is not an existing module or open pull request that already covers the same functionality
243- Each module should be in its own file under the appropriate `modules/` subdirectory. In some scenarios adding module actions or targets is preferred
244- Exploits require a `DisclosureDate` field
245- Exploits, auxiliary, and post modules require `Notes` with `Stability`, `SideEffects`, and `Reliability`
246- License new code with `MSF_LICENSE` (the project default, defined in `lib/msf/core/constants.rb`)
247- Module descriptions or documentation should list the range of vulnerable versions and the fixed version of the affected software, when known
248- Module descriptions should only use ASCII characters
249- New modules require an associated markdown file in the `documentation/modules` folder with the same structure, including steps to set up the vulnerable environment for testing. If a Dockerfile or docker-compose file is used for the test environment, include the setup commands in the markdown rather than committing separate Docker files. The Scenarios section must be filled out by a human at all times. Follow `documentation/modules/module_doc_template.md` as a template
250- If there's only one `ACTION` in the exploit, it can likely be omitted
251 
252#### Payloads and Targets
253 
254- When possible don't set a default payload (`DefaultOptions` with `'PAYLOAD'`) in modules — let the framework choose the most appropriate payload automatically
255- Define bad characters instead of explicitly base-64 encoding payloads
256- Don't check the number of sessions at the end of an exploit and report success based on that — not all payloads open sessions
257- Don't submit any kind of opaque binary blob — everything must include source code and build instructions
258 
259**Payload selection guidance:**
260 
261| Scenario | Approach |
262|----------|----------|
263| Only command execution available (no file write) | Use `ARCH_CMD` payloads |
264| Only HTTP(S) outbound (curl/wget available) | Use fetch payload (`Msf::Exploit::Remote::HttpServer` + fetch handler) |
265| File write possible on target | Use dropper/EXE payload (`Msf::Exploit::EXE`) |
266| Full command stager needed (multi-step upload) | Use `Msf::Exploit::CmdStager` — but prefer fetch when only download mechanisms are available |
267 
268#### File and Network Operations
269 
270- When overriding `cleanup`, always call `super` to ensure the parent mixin chain cleans up connections and sessions properly
271- When opening a file, make sure the file exists first
272- Don't print host information like `#{ip}:#{port}` because it doesn't handle IPv6 addresses — use `#{Rex::Socket.to_authority(ip, port)}`
273- Use the TEST-NET-1 range for example / non-routeable IP addresses in unit tests and spec files: `192.0.2.0`. Local/private IPs are fine in module documentation scenarios
274 
275#### Output and Reporting
276 
277- All `print_*` calls should start with a capital letter
278- Call `report_service` when a service can be reported
279- Call `report_vuln` when a vulnerability can be reported
280- When creating a fake account / username use the `Faker` gem (e.g. `Faker::Internet.username`) not `Rex::Text.rand_text_alphanumeric`
281 
282#### Session and Post-Exploitation
283 
284- Use `create_process(executable, args: [], time_out: 15, opts: {})` instead of the deprecated `cmd_exec` with separate arguments
285- Use `Msf::OptionalSession` for modules that work both with and without an existing session (e.g. local exploits that can also run standalone)
286- Use the module mixin APIs — don't reinvent the wheel
287 
288#### Internationalisation Considerations
289 
290- When checking for a string in a response — will it always be in English?
291- Ensure hardcoded strings being regex'ed will be consistent across multiple versions
292 
293### Check Methods
294 
295- `check` methods must only return `CheckCode` values (e.g. `CheckCode::Vulnerable`, `CheckCode::Safe`) — never raise exceptions or call `fail_with`
296- When writing a `check` method, verify it does not produce false positives when run against unrelated software or services
297- Prefer using `Rex::Version` for version checks
298- Use `fail_with(Failure::UnexpectedReply, '...')` (and other `Failure::*` constants) to bail out of `exploit`/`run` methods — don't use `raise` or bare `return` for error conditions
299- `get_version` methods should return a REX version
300- `CheckCode::Vulnerable` is only used when the vulnerability has been exploited
301- `CheckCode::Appears` is only used when the application's version has been checked
302- Always provide a human-readable reason string when returning a CheckCode, e.g. `CheckCode::Safe("Target is running patched version #{version}")` — never return a bare constant or empty call
303- Use specific regular expressions or `res.get_html_document` for version extraction with CSS selectors. Don't use generic selectors like `href .*` to grab the version — be more precise
304- Catch exceptions that may be raised and ensure a valid CheckCode is returned
305- Research and determine a minimum version where the application is vulnerable; mark prior versions as safe
306- Check helper methods used by both `#check` and `#exploit` (or `#run`) — ensure there is no condition (exception, return, etc.) where `#check` could return something other than a CheckCode
307- Prefer `prepend Msf::Exploit::Remote::AutoCheck` over manually calling `check` inside `exploit` — this lets the framework handle check-before-exploit automatically
308 
309### Library Code
310 
311When writing or modifying code in `lib/`:
312 
313#### Error Handling
314- Use specific error classes (`Rex::RuntimeError`, `Rex::ConnectionError`, `ArgumentError`, `Rex::TimeoutError`) — never `raise "bare string"` which makes targeted rescue impossible
315- Use `rescue StandardError => e` or a more specific class — never bare `rescue` (it discards the exception object, making debugging impossible) and never `rescue Exception` (it catches `SignalException` and `SystemExit`, hiding Ctrl-C and kill signals)
316- Propagate errors with context: `raise Rex::ConnectionError, "Failed to connect to #{host}: #{e.message}"`
317 
318#### Documentation and Style
319- Add YARD `@param` and `@return` tags to all public methods
320- Add `# frozen_string_literal: true` to new library files
321- Avoid `get_`/`set_` prefixes for accessor-style methods in new code (Ruby convention: use the attribute name directly, e.g. `def version` not `def get_version`)
322- Link to the specification or RFC when implementing binary/protocol parsers
323 
324#### Quality
325- Write RSpec tests for any library changes — tests live in `spec/` mirroring the `lib/` structure
326- Follow [Better Specs](https://www.betterspecs.org/) conventions
327- Keep PRs focused — small fixes are easier to review
328- Any new hash cracking implementations require adding a test hash to `tools/dev/hash_cracker_validator.rb` and ensuring that passes without error
329 
330### Testing
331 
332- Tests live in `spec/` mirroring the `lib/` structure
333- Run a single spec file: `bundle exec rspec spec/path/to/spec.rb`
334- Run a single example by line: `bundle exec rspec spec/path/to/spec.rb:42`
335- Run the full suite: `bundle exec rake spec` (slow — prefer targeted runs during development)
336- Module functional tests live under `spec/modules/` and test end-to-end behaviour
337- Always run specs relevant to your change before submitting
338 
339### Preferred Libraries
340 
341- Use the `RubySMB` library for SMB modules
342- Use `Rex::Stopwatch.elapsed_time` to track elapsed time
343- Use the `Rex::MIME::Message` class for MIME messages instead of hardcoding XML
344- When creating random variable names prefer `Rex::RandomIdentifier::Generator` and specify the runtime language used. This avoids generating language keywords that would break the script
345- Use `Msf::Exploit::SQLi` when exploiting SQL injection vulnerabilities
346 
347## Common Patterns
348 
349### Options Registration
350 
351```ruby
352register_options([
353 OptString.new('TARGETURI', [true, 'Base path to the application', '/']),
354 OptInt.new('TIMEOUT', [true, 'Request timeout in seconds', 10]),
355 OptBool.new('SSL', [false, 'Use SSL/TLS', false])
356])
357 
358register_advanced_options([
359 OptString.new('UserAgent', [false, 'Custom User-Agent header'])
360])
361```
362 
363- Use `SCREAMING_SNAKE_CASE` for standard option names and `CamelCase` for advanced option names
364- Access options via `datastore['OPTION_NAME']`
365 
366### Console Output
367 
368- Use `print_status`, `print_good`, `print_error`, `print_warning` for console output
369- Use `vprint_*` variants for verbose-only output (shown when user sets `VERBOSE true`)
370 
371### HTTP Response Handling
372 
373```ruby
374res = send_request_cgi(
375 'method' => 'GET',
376 'uri' => normalize_uri(target_uri.path, 'api', 'version')
377)
378 
379fail_with(Failure::Unreachable, 'Target did not respond') unless res
380fail_with(Failure::UnexpectedReply, "Unexpected status: #{res.code}") unless res.code == 200
381 
382json = res.get_json_document
383fail_with(Failure::UnexpectedReply, 'Response is not valid JSON') if json.empty?
384 
385# For HTML parsing:
386html = res.get_html_document
387version = html.at_css('meta[name="version"]')&.[]('content')
388```
389 
390- Always use `res.get_json_document` — never `JSON.parse(res.body)`
391- Use `res.get_html_document` with CSS selectors for HTML parsing
392- Check `res` for nil (target didn't respond) before accessing `.code` or `.body`
393- Use `fail_with(Failure::*, 'reason')` for error conditions in `exploit`/`run`
394 
395### Network Operations
396 
397- Use `send_request_cgi` for HTTP requests in modules
398- Use `connect` / `disconnect` for TCP socket operations
399- Use the `srvhost` method to access the server host — don't use `datastore['SRVHOST']` directly (enforced by `Lint/DatastoreSrvhostUsage` cop)
400 
401## Legacy Patterns (Migration Guidance)
402 
403These patterns exist in older code but should not be used in new modules or library code. When touching existing code that uses these patterns, prefer modernizing it:
404 
405| Legacy Pattern | Modern Replacement | Notes |
406|---------------|-------------------|-------|
407| `HttpFingerprint = { :pattern => [...] }` | Implement a `check` method + `prepend AutoCheck` | HttpFingerprint is a passive fingerprinting mechanism that predates the check API |
408| `cmd_exec("command #{user_input}")` | `create_process("command", args: [user_input])` | String interpolation in cmd_exec is a command injection risk; create_process separates executable from arguments by design |
409| `cmd_exec(cmd, args_string, timeout)` | `create_process(cmd, args: args_array, time_out: timeout)` | Enforced by `Lint/DetectOutdatedCmdExecApi` rubocop cop |
410| `DefaultOptions => { 'PAYLOAD' => '...' }` | Remove — let the framework choose automatically | Only acceptable when the module genuinely only works with a single specific payload |
411| `include Msf::Exploit::Remote::AutoCheck` | `prepend Msf::Exploit::Remote::AutoCheck` | Include raises NotImplementedError; prepend is required |
412| Bare `rescue` in library code | `rescue StandardError => e` | Bare rescue discards the exception object; `rescue Exception` is worse — it catches signals/exits |
413| `raise "error message"` in library code | `raise Rex::RuntimeError, "message"` | Specific classes enable targeted error handling |
414| Manual `check` call inside `exploit` | `prepend AutoCheck` + separate `check` method | Let the framework handle check-before-exploit |
415 
416### Modernizing Existing Modules
417 
418When updating an existing module, the lowest-effort improvement is adding AutoCheck:
419 
420```ruby
421# If the module already has a `def check` method, just add this line
422# after the other includes:
423prepend Msf::Exploit::Remote::AutoCheck
424```
425 
426This single addition gives users the ability to verify vulnerability before exploitation, with automatic abort if the target is not vulnerable (overridable with `set ForceExploit true`).
427 
428## Before Submitting
429 
430- Work on a topic branch — don't commit directly to `master`
431- Follow the [50/72 rule](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) for Git commit messages (50 char subject, 72 char body wrap)
432- Ensure `rubocop` and `msftidy` pass on any changed files with no new offenses
433- Ensure `ruby tools/dev/msftidy_docs.rb <documentation_file>` passes on any changed documentation markdown docs with no new offenses
434- Include console output (especially `msfconsole` demonstrations) in your pull request when the changes have observable effects
435- Include verification steps so reviewers can test your changes
436- Reference associated issues in your pull request description (e.g., `See #1234`)
437 
438## What NOT to Do
439 
440- Don't submit untested code — all code must be manually verified
441- Don't include sensitive information (IPs, credentials, API keys, hashes of credentials) in code or docs
442- Don't include more than one module per pull request
443- Don't add new scripts to `scripts/` — use post modules instead
444- Don't use `pack`/`unpack` with invalid directives (enforced by linter)
445 
rapid7/metasploit-framework · .github/copilot-instructions.md
@@ +1 @@
1# Copilot Instructions
2 
3Refer to [AGENTS.md](../AGENTS.md) in the repository root for all project conventions, coding standards, and AI agent guidelines.
4 
5Path-scoped instructions in `.github/instructions/` provide file-type-specific guidance for modules, library code, tests, and documentation.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6 
@@ −1 +1 @@
1−# AI Agent Instructions for Metasploit Framework
1+# Copilot Instructions
22  
3−## Project Overview
3+Refer to [AGENTS.md](../AGENTS.md) in the repository root for all project conventions, coding standards, and AI agent guidelines.
44  
5−Metasploit Framework is an open-source penetration testing and exploitation framework written in Ruby. It provides infrastructure for developing, testing, and executing exploit code against remote targets.
6− 
7−## Project Structure
8− 
9−- `modules/` — Metasploit modules (exploits, auxiliary, post, payloads, encoders, evasion, nops)
10−- `lib/msf/` — Core framework library code
11−- `lib/rex/` — Rex (Ruby Exploitation) library
12−- `lib/metasploit/` — Metasploit namespace libraries
13−- `data/` — Data files used by modules (wordlists, templates, binaries)
14−- `spec/` — RSpec test suite
15−- `tools/` — Developer and operational tools
16−- `plugins/` — msfconsole plugins
17−- `scripts/` — Example automation scripts
18−- `documentation/modules/` — Markdown documentation for Metasploit modules
19− 
20−## Coding Conventions
21− 
22−- Ruby (see `.ruby-version` for the current version). Minimum supported: 3.1+
23−- Follow the project's `.rubocop.yml` configuration — run `rubocop` on changed files before submitting
24−- Run `ruby tools/dev/msftidy.rb <module_file_path>` to catch common module issues
25−- `# frozen_string_literal: true` — add to new **library** files (`lib/`); use `String.new` where a mutable string is needed. Do NOT add to module files or spec files (the framework extensively mutates string buffers via instance variables, and the RuboCop cop `Style/FrozenStringLiteralComment` is disabled project-wide). Existing files that already have it are fine to leave
26−- No enforced line length limit, but keep code readable
27−- Use `%q{}` for long multi-line strings (curly braces preferred for module descriptions)
28−- Multiline block comments are acceptable for embedded code snippets/payloads
29−- Don't use `get_`/`set_` prefixes for accessor methods in new code
30−- Method parameter names must be at least 2 characters (exception for well-known crypto abbreviations)
31− 
32−## Module Structure Templates
33− 
34−### Exploit Module Template
35− 
36−New exploit modules should follow this canonical structure and ordering:
37− 
38−```ruby
39−##
40−# This module requires Metasploit: https://metasploit.com/download
41−# Current source: https://github.com/rapid7/metasploit-framework
42−##
43− 
44−class MetasploitModule < Msf::Exploit::Remote
45− Rank = ExcellentRanking
46− 
47− # 1. Protocol mixins first
48− include Msf::Exploit::Remote::HttpClient
49− # 2. Utility/feature mixins second
50− include Msf::Exploit::FileDropper
51− # 3. Reporting mixins (if needed)
52− # include Msf::Auxiliary::Report
53− # 4. AutoCheck ALWAYS LAST — must be prepend, not include
54− prepend Msf::Exploit::Remote::AutoCheck
55− 
56− def initialize(info = {})
57− super(
58− update_info(
59− info,
60− 'Name' => 'Vendor Product Vulnerability Type',
61− 'Description' => %q{
62− Description of the vulnerability and what this module does.
63− },
64− 'Author' => [
65− 'Discoverer Name', # Vulnerability discovery
66− 'Module Author' # Metasploit module
67− ],
68− 'License' => MSF_LICENSE,
69− 'References' => [
70− ['CVE', '2024-XXXXX'],
71− ['URL', 'https://example.com/advisory']
72− ],
73− 'Targets' => [
74− [
75− 'Automatic',
76− {
77− 'Platform' => ['linux'], # or 'win', 'osx', 'unix', 'php', 'python', 'java'
78− 'Arch' => [ARCH_CMD], # or ARCH_X86, ARCH_X64, ARCH_PHP, ARCH_JAVA, ARCH_PYTHON, ARCH_ARMLE, ARCH_AARCH64, ARCH_MIPSLE — see rex-arch gem for full list
79− 'Type' => :cmd # or :dropper, :psh_stager — determines payload delivery
80− }
81− ]
82− ],
83− 'DefaultTarget' => 0,
84− 'DisclosureDate' => '2024-01-01',
85− 'Notes' => {
86− 'Stability' => [], # e.g. CRASH_SAFE, CRASH_SERVICE_RESTARTS
87− 'SideEffects' => [], # e.g. IOC_IN_LOGS, ARTIFACTS_ON_DISK
88− 'Reliability' => [] # e.g. REPEATABLE_SESSION
89− }
90− )
91− )
92− end
93− 
94− def check
95− # Always return CheckCode with a reason string
96− CheckCode::Safe('Target is not vulnerable')
97− end
98− 
99− def exploit
100− # Exploitation logic
101− end
102−end
103−```
104− 
105−### Auxiliary Module Template
106− 
107−Auxiliary modules use `def run` (not `exploit`) and inherit from `Msf::Auxiliary`:
108− 
109−```ruby
110−class MetasploitModule < Msf::Auxiliary
111− include Msf::Exploit::Remote::HttpClient
112− include Msf::Auxiliary::Report
113− prepend Msf::Exploit::Remote::AutoCheck
114− 
115− def initialize(info = {})
116− super(
117− update_info(
118− info,
119− 'Name' => 'Vendor Product Scanner/Gatherer',
120− 'Description' => %q{
121− Description of what this module discovers or does.
122− },
123− 'Author' => ['Author Name'],
124− 'License' => MSF_LICENSE,
125− 'References' => [['CVE', '2024-XXXXX']],
126− 'Notes' => {
127− 'Stability' => [], # e.g. CRASH_SAFE
128− 'SideEffects' => [], # e.g. IOC_IN_LOGS
129− 'Reliability' => [] # e.g. REPEATABLE_SESSION
130− }
131− )
132− )
133− 
134− register_options([
135− OptString.new('TARGETURI', [true, 'Base path', '/'])
136− ])
137− end
138− 
139− def check
140− CheckCode::Safe('Target is not affected')
141− end
142− 
143− def run
144− # Main logic — use report_service, report_vuln, print_good, etc.
145− end
146−end
147−```
148− 
149−### Post Module Template
150− 
151−Post modules inherit from `Msf::Post`, require a session, and declare compatible session types:
152− 
153−```ruby
154−class MetasploitModule < Msf::Post
155− include Msf::Post::File
156− include Msf::Post::Linux::System
157− 
158− def initialize(info = {})
159− super(
160− update_info(
161− info,
162− 'Name' => 'Platform Subsystem Gather/Action',
163− 'Description' => %q{
164− Description of what this post module does on the target.
165− },
166− 'Author' => ['Author Name'],
167− 'License' => MSF_LICENSE,
168− 'Platform' => ['linux'], # or 'win', 'osx', 'unix', 'bsd', 'solaris'
169− 'SessionTypes' => ['meterpreter', 'shell'], # or just ['meterpreter'] if shell won't work
170− 'Notes' => {
171− 'Stability' => [], # e.g. CRASH_SAFE
172− 'SideEffects' => [], # e.g. ARTIFACTS_ON_DISK, CONFIG_CHANGES
173− 'Reliability' => []
174− }
175− )
176− )
177− end
178− 
179− def run
180− # Use create_process, file_exist?, read_file, etc.
181− # Access session via `session` method
182− end
183−end
184−```
185− 
186−### Notes Hash Reference
187− 
188−The `Notes` hash declares the module's operational characteristics:
189− 
190−| Key | Values | Meaning |
191−|-----|--------|---------|
192−| `Stability` | `CRASH_SAFE`, `CRASH_SERVICE_RESTARTS`, `CRASH_SERVICE_DOWN`, `CRASH_OS_RESTARTS`, `CRASH_OS_DOWN` | Impact on target stability |
193−| `SideEffects` | `IOC_IN_LOGS`, `ARTIFACTS_ON_DISK`, `CONFIG_CHANGES`, `ACCOUNT_LOCKOUTS`, `SCREEN_EFFECTS`, `AUDIO_EFFECTS`, `PHYSICAL_EFFECTS` | Observable traces left on target |
194−| `Reliability` | `REPEATABLE_SESSION`, `FIRST_ATTEMPT_FAIL`, `UNRELIABLE_SESSION`, `EVENT_DEPENDENT` | How reliably the module succeeds |
195− 
196−See also: [`lib/msf/core/constants.rb`](lib/msf/core/constants.rb) for the full list of valid values with descriptions.
197− 
198−**Which module types require Notes:**
199− 
200−| Module Type | Notes Required? | Enforced By |
201−|-------------|----------------|-------------|
202−| Exploit | **Yes** | msftidy + rubocop (`Lint/ModuleEnforceNotes`) |
203−| Auxiliary | **Yes** | rubocop (`Lint/ModuleEnforceNotes`) |
204−| Post | **Yes** | rubocop (`Lint/ModuleEnforceNotes`) |
205−| Evasion | No | — |
206−| Payload | No | — |
207−| Encoder | No | — |
208−| Nop | No | — |
209− 
210−The same `Stability`, `SideEffects`, and `Reliability` constants apply uniformly — there are no type-specific values. Payloads, encoders, and nops don't use Notes because they don't independently interact with targets.
211− 
212−### Metadata Source Reference
213− 
214−The inline comments in the templates above list common values but are **not exhaustive**. Consult these source files for the full set:
215− 
216−| Field | Source File | Notes |
217−|-------|------------|-------|
218−| Platform | [`lib/msf/core/module/platform.rb`](lib/msf/core/module/platform.rb) | Class hierarchy — use the lowercase short name (e.g. `'linux'`, `'win'`, `'osx'`) |
219−| Arch | [`rex-arch` gem](https://github.com/rapid7/rex-arch/blob/master/lib/rex/arch.rb) | Constants like `ARCH_CMD`, `ARCH_X86`, `ARCH_X64`, `ARCH_PHP` etc. |
220−| Stability / SideEffects / Reliability | [`lib/msf/core/constants.rb`](lib/msf/core/constants.rb) | All valid Notes hash values with descriptions |
221−| Rank | [`lib/msf/core/constants.rb`](lib/msf/core/constants.rb) | `ManualRanking` through `ExcellentRanking` |
222−| CheckCode | [`lib/msf/core/exploit.rb`](lib/msf/core/exploit.rb) (line ~52) | `Vulnerable`, `Appears`, `Safe`, `Detected`, `Unknown`, `Unsupported` |
223− 
224−### Mixin Ordering
225− 
226−Follow this order for includes and prepends in module classes:
227− 
228−1. **Protocol mixins** — `Msf::Exploit::Remote::HttpClient`, `RubySMB`, `Msf::Exploit::Remote::Udp`, etc.
229−2. **Utility/feature mixins** — `Msf::Exploit::FileDropper`, `Msf::Exploit::CmdStager`, `Msf::Exploit::EXE`, etc.
230−3. **Reporting mixins** — `Msf::Auxiliary::Report`
231−4. **Post mixins** (if needed) — `Msf::Post::File`, `Msf::Post::Linux::Priv`, etc.
232−5. **`prepend Msf::Exploit::Remote::AutoCheck`** — always last, after all includes
233− 
234−AutoCheck must use `prepend`, not `include` (the module raises `NotImplementedError` if included). It wraps the `exploit`/`run` method to automatically call `check` before exploitation.
235− 
236−### Module Development
237− 
238−#### Metadata and Structure
239− 
240−- Prefer writing modules in Ruby. Go and Python modules are accepted, but their external runtimes don't support the full framework API (e.g. network pivoting). Ruby modules do not have this limitation
241−- Prefer using hash over an array for return values, and use kwargs for reusable APIs for future extensions
242−- Before writing a new module, check that there is not an existing module or open pull request that already covers the same functionality
243−- Each module should be in its own file under the appropriate `modules/` subdirectory. In some scenarios adding module actions or targets is preferred
244−- Exploits require a `DisclosureDate` field
245−- Exploits, auxiliary, and post modules require `Notes` with `Stability`, `SideEffects`, and `Reliability`
246−- License new code with `MSF_LICENSE` (the project default, defined in `lib/msf/core/constants.rb`)
247−- Module descriptions or documentation should list the range of vulnerable versions and the fixed version of the affected software, when known
248−- Module descriptions should only use ASCII characters
249−- New modules require an associated markdown file in the `documentation/modules` folder with the same structure, including steps to set up the vulnerable environment for testing. If a Dockerfile or docker-compose file is used for the test environment, include the setup commands in the markdown rather than committing separate Docker files. The Scenarios section must be filled out by a human at all times. Follow `documentation/modules/module_doc_template.md` as a template
250−- If there's only one `ACTION` in the exploit, it can likely be omitted
251− 
252−#### Payloads and Targets
253− 
254−- When possible don't set a default payload (`DefaultOptions` with `'PAYLOAD'`) in modules — let the framework choose the most appropriate payload automatically
255−- Define bad characters instead of explicitly base-64 encoding payloads
256−- Don't check the number of sessions at the end of an exploit and report success based on that — not all payloads open sessions
257−- Don't submit any kind of opaque binary blob — everything must include source code and build instructions
258− 
259−**Payload selection guidance:**
260− 
261−| Scenario | Approach |
262−|----------|----------|
263−| Only command execution available (no file write) | Use `ARCH_CMD` payloads |
264−| Only HTTP(S) outbound (curl/wget available) | Use fetch payload (`Msf::Exploit::Remote::HttpServer` + fetch handler) |
265−| File write possible on target | Use dropper/EXE payload (`Msf::Exploit::EXE`) |
266−| Full command stager needed (multi-step upload) | Use `Msf::Exploit::CmdStager` — but prefer fetch when only download mechanisms are available |
267− 
268−#### File and Network Operations
269− 
270−- When overriding `cleanup`, always call `super` to ensure the parent mixin chain cleans up connections and sessions properly
271−- When opening a file, make sure the file exists first
272−- Don't print host information like `#{ip}:#{port}` because it doesn't handle IPv6 addresses — use `#{Rex::Socket.to_authority(ip, port)}`
273−- Use the TEST-NET-1 range for example / non-routeable IP addresses in unit tests and spec files: `192.0.2.0`. Local/private IPs are fine in module documentation scenarios
274− 
275−#### Output and Reporting
276− 
277−- All `print_*` calls should start with a capital letter
278−- Call `report_service` when a service can be reported
279−- Call `report_vuln` when a vulnerability can be reported
280−- When creating a fake account / username use the `Faker` gem (e.g. `Faker::Internet.username`) not `Rex::Text.rand_text_alphanumeric`
281− 
282−#### Session and Post-Exploitation
283− 
284−- Use `create_process(executable, args: [], time_out: 15, opts: {})` instead of the deprecated `cmd_exec` with separate arguments
285−- Use `Msf::OptionalSession` for modules that work both with and without an existing session (e.g. local exploits that can also run standalone)
286−- Use the module mixin APIs — don't reinvent the wheel
287− 
288−#### Internationalisation Considerations
289− 
290−- When checking for a string in a response — will it always be in English?
291−- Ensure hardcoded strings being regex'ed will be consistent across multiple versions
292− 
293−### Check Methods
294− 
295−- `check` methods must only return `CheckCode` values (e.g. `CheckCode::Vulnerable`, `CheckCode::Safe`) — never raise exceptions or call `fail_with`
296−- When writing a `check` method, verify it does not produce false positives when run against unrelated software or services
297−- Prefer using `Rex::Version` for version checks
298−- Use `fail_with(Failure::UnexpectedReply, '...')` (and other `Failure::*` constants) to bail out of `exploit`/`run` methods — don't use `raise` or bare `return` for error conditions
299−- `get_version` methods should return a REX version
300−- `CheckCode::Vulnerable` is only used when the vulnerability has been exploited
301−- `CheckCode::Appears` is only used when the application's version has been checked
302−- Always provide a human-readable reason string when returning a CheckCode, e.g. `CheckCode::Safe("Target is running patched version #{version}")` — never return a bare constant or empty call
303−- Use specific regular expressions or `res.get_html_document` for version extraction with CSS selectors. Don't use generic selectors like `href .*` to grab the version — be more precise
304−- Catch exceptions that may be raised and ensure a valid CheckCode is returned
305−- Research and determine a minimum version where the application is vulnerable; mark prior versions as safe
306−- Check helper methods used by both `#check` and `#exploit` (or `#run`) — ensure there is no condition (exception, return, etc.) where `#check` could return something other than a CheckCode
307−- Prefer `prepend Msf::Exploit::Remote::AutoCheck` over manually calling `check` inside `exploit` — this lets the framework handle check-before-exploit automatically
308− 
309−### Library Code
310− 
311−When writing or modifying code in `lib/`:
312− 
313−#### Error Handling
314−- Use specific error classes (`Rex::RuntimeError`, `Rex::ConnectionError`, `ArgumentError`, `Rex::TimeoutError`) — never `raise "bare string"` which makes targeted rescue impossible
315−- Use `rescue StandardError => e` or a more specific class — never bare `rescue` (it discards the exception object, making debugging impossible) and never `rescue Exception` (it catches `SignalException` and `SystemExit`, hiding Ctrl-C and kill signals)
316−- Propagate errors with context: `raise Rex::ConnectionError, "Failed to connect to #{host}: #{e.message}"`
317− 
318−#### Documentation and Style
319−- Add YARD `@param` and `@return` tags to all public methods
320−- Add `# frozen_string_literal: true` to new library files
321−- Avoid `get_`/`set_` prefixes for accessor-style methods in new code (Ruby convention: use the attribute name directly, e.g. `def version` not `def get_version`)
322−- Link to the specification or RFC when implementing binary/protocol parsers
323− 
324−#### Quality
325−- Write RSpec tests for any library changes — tests live in `spec/` mirroring the `lib/` structure
326−- Follow [Better Specs](https://www.betterspecs.org/) conventions
327−- Keep PRs focused — small fixes are easier to review
328−- Any new hash cracking implementations require adding a test hash to `tools/dev/hash_cracker_validator.rb` and ensuring that passes without error
329− 
330−### Testing
331− 
332−- Tests live in `spec/` mirroring the `lib/` structure
333−- Run a single spec file: `bundle exec rspec spec/path/to/spec.rb`
334−- Run a single example by line: `bundle exec rspec spec/path/to/spec.rb:42`
335−- Run the full suite: `bundle exec rake spec` (slow — prefer targeted runs during development)
336−- Module functional tests live under `spec/modules/` and test end-to-end behaviour
337−- Always run specs relevant to your change before submitting
338− 
339−### Preferred Libraries
340− 
341−- Use the `RubySMB` library for SMB modules
342−- Use `Rex::Stopwatch.elapsed_time` to track elapsed time
343−- Use the `Rex::MIME::Message` class for MIME messages instead of hardcoding XML
344−- When creating random variable names prefer `Rex::RandomIdentifier::Generator` and specify the runtime language used. This avoids generating language keywords that would break the script
345−- Use `Msf::Exploit::SQLi` when exploiting SQL injection vulnerabilities
346− 
347−## Common Patterns
348− 
349−### Options Registration
350− 
351−```ruby
352−register_options([
353− OptString.new('TARGETURI', [true, 'Base path to the application', '/']),
354− OptInt.new('TIMEOUT', [true, 'Request timeout in seconds', 10]),
355− OptBool.new('SSL', [false, 'Use SSL/TLS', false])
356−])
357− 
358−register_advanced_options([
359− OptString.new('UserAgent', [false, 'Custom User-Agent header'])
360−])
361−```
362− 
363−- Use `SCREAMING_SNAKE_CASE` for standard option names and `CamelCase` for advanced option names
364−- Access options via `datastore['OPTION_NAME']`
365− 
366−### Console Output
367− 
368−- Use `print_status`, `print_good`, `print_error`, `print_warning` for console output
369−- Use `vprint_*` variants for verbose-only output (shown when user sets `VERBOSE true`)
370− 
371−### HTTP Response Handling
372− 
373−```ruby
374−res = send_request_cgi(
375− 'method' => 'GET',
376− 'uri' => normalize_uri(target_uri.path, 'api', 'version')
377−)
378− 
379−fail_with(Failure::Unreachable, 'Target did not respond') unless res
380−fail_with(Failure::UnexpectedReply, "Unexpected status: #{res.code}") unless res.code == 200
381− 
382−json = res.get_json_document
383−fail_with(Failure::UnexpectedReply, 'Response is not valid JSON') if json.empty?
384− 
385−# For HTML parsing:
386−html = res.get_html_document
387−version = html.at_css('meta[name="version"]')&.[]('content')
388−```
389− 
390−- Always use `res.get_json_document` — never `JSON.parse(res.body)`
391−- Use `res.get_html_document` with CSS selectors for HTML parsing
392−- Check `res` for nil (target didn't respond) before accessing `.code` or `.body`
393−- Use `fail_with(Failure::*, 'reason')` for error conditions in `exploit`/`run`
394− 
395−### Network Operations
396− 
397−- Use `send_request_cgi` for HTTP requests in modules
398−- Use `connect` / `disconnect` for TCP socket operations
399−- Use the `srvhost` method to access the server host — don't use `datastore['SRVHOST']` directly (enforced by `Lint/DatastoreSrvhostUsage` cop)
400− 
401−## Legacy Patterns (Migration Guidance)
402− 
403−These patterns exist in older code but should not be used in new modules or library code. When touching existing code that uses these patterns, prefer modernizing it:
404− 
405−| Legacy Pattern | Modern Replacement | Notes |
406−|---------------|-------------------|-------|
407−| `HttpFingerprint = { :pattern => [...] }` | Implement a `check` method + `prepend AutoCheck` | HttpFingerprint is a passive fingerprinting mechanism that predates the check API |
408−| `cmd_exec("command #{user_input}")` | `create_process("command", args: [user_input])` | String interpolation in cmd_exec is a command injection risk; create_process separates executable from arguments by design |
409−| `cmd_exec(cmd, args_string, timeout)` | `create_process(cmd, args: args_array, time_out: timeout)` | Enforced by `Lint/DetectOutdatedCmdExecApi` rubocop cop |
410−| `DefaultOptions => { 'PAYLOAD' => '...' }` | Remove — let the framework choose automatically | Only acceptable when the module genuinely only works with a single specific payload |
411−| `include Msf::Exploit::Remote::AutoCheck` | `prepend Msf::Exploit::Remote::AutoCheck` | Include raises NotImplementedError; prepend is required |
412−| Bare `rescue` in library code | `rescue StandardError => e` | Bare rescue discards the exception object; `rescue Exception` is worse — it catches signals/exits |
413−| `raise "error message"` in library code | `raise Rex::RuntimeError, "message"` | Specific classes enable targeted error handling |
414−| Manual `check` call inside `exploit` | `prepend AutoCheck` + separate `check` method | Let the framework handle check-before-exploit |
415− 
416−### Modernizing Existing Modules
417− 
418−When updating an existing module, the lowest-effort improvement is adding AutoCheck:
419− 
420−```ruby
421−# If the module already has a `def check` method, just add this line
422−# after the other includes:
423−prepend Msf::Exploit::Remote::AutoCheck
424−```
425− 
426−This single addition gives users the ability to verify vulnerability before exploitation, with automatic abort if the target is not vulnerable (overridable with `set ForceExploit true`).
427− 
428−## Before Submitting
429− 
430−- Work on a topic branch — don't commit directly to `master`
431−- Follow the [50/72 rule](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) for Git commit messages (50 char subject, 72 char body wrap)
432−- Ensure `rubocop` and `msftidy` pass on any changed files with no new offenses
433−- Ensure `ruby tools/dev/msftidy_docs.rb <documentation_file>` passes on any changed documentation markdown docs with no new offenses
434−- Include console output (especially `msfconsole` demonstrations) in your pull request when the changes have observable effects
435−- Include verification steps so reviewers can test your changes
436−- Reference associated issues in your pull request description (e.g., `See #1234`)
437− 
438−## What NOT to Do
439− 
440−- Don't submit untested code — all code must be manually verified
441−- Don't include sensitive information (IPs, credentials, API keys, hashes of credentials) in code or docs
442−- Don't include more than one module per pull request
443−- Don't add new scripts to `scripts/` — use post modules instead
444−- Don't use `pack`/`unpack` with invalid directives (enforced by linter)
5+Path-scoped instructions in `.github/instructions/` provide file-type-specific guidance for modules, library code, tests, and documentation.
4456  

Also from Kynth Studios

Built for the same person as RuleStack

ToolDrift

What the AI coding tools changed last night

tooldrift.kynth.studio

StillShipping

Which agent tools have stopped shipping

stillshipping.kynth.studio

BlockDex

Search inside every shadcn registry

blockdex.kynth.studio

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack

The studio list

One product, taken apart, once a month

Kynth Studios pulls one shipped product open every month — what it does, what it cost to build, what the pipeline behind it looks like, and what the numbers did. One email a month, nothing in between.

Double opt-in — we send one confirmation link and nothing else until you click it.

RuleStack

Built by

Kynth Studios

the studio behind ToolDrift, StillShipping and BlockDex

part of Toolproof, the measurement layer for AI agent tooling

Directory

Configs
Stacks
Compare formats
AGENTS.md vs CLAUDE.md
Cursor rules alternatives
Diff two configs
Best AGENTS.md examples
Best Cursor rules examples
What goes in a CLAUDE.md

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

© 2026 RuleStack. A Kynth Studios product. Changelog

RuleStack