{"owner":"rapid7","repo":"metasploit-framework","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md",".github/copilot-instructions.md"],"files":{"AGENTS.md":"# AI Agent Instructions for Metasploit Framework\n\n## Project Overview\n\nMetasploit 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.\n\n## Project Structure\n\n- `modules/` — Metasploit modules (exploits, auxiliary, post, payloads, encoders, evasion, nops)\n- `lib/msf/` — Core framework library code\n- `lib/rex/` — Rex (Ruby Exploitation) library\n- `lib/metasploit/` — Metasploit namespace libraries\n- `data/` — Data files used by modules (wordlists, templates, binaries)\n- `spec/` — RSpec test suite\n- `tools/` — Developer and operational tools\n- `plugins/` — msfconsole plugins\n- `scripts/` — Example automation scripts\n- `documentation/modules/` — Markdown documentation for Metasploit modules\n\n## Coding Conventions\n\n- Ruby (see `.ruby-version` for the current version). Minimum supported: 3.1+\n- Follow the project's `.rubocop.yml` configuration — run `rubocop` on changed files before submitting\n- Run `ruby tools/dev/msftidy.rb <module_file_path>` to catch common module issues\n- `# 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\n- No enforced line length limit, but keep code readable\n- Use `%q{}` for long multi-line strings (curly braces preferred for module descriptions)\n- Multiline block comments are acceptable for embedded code snippets/payloads\n- Don't use `get_`/`set_` prefixes for accessor methods in new code\n- Method parameter names must be at least 2 characters (exception for well-known crypto abbreviations)\n\n## Module Structure Templates\n\n### Exploit Module Template\n\nNew exploit modules should follow this canonical structure and ordering:\n\n```ruby\n##\n# This module requires Metasploit: https://metasploit.com/download\n# Current source: https://github.com/rapid7/metasploit-framework\n##\n\nclass MetasploitModule < Msf::Exploit::Remote\n  Rank = ExcellentRanking\n\n  # 1. Protocol mixins first\n  include Msf::Exploit::Remote::HttpClient\n  # 2. Utility/feature mixins second\n  include Msf::Exploit::FileDropper\n  # 3. Reporting mixins (if needed)\n  # include Msf::Auxiliary::Report\n  # 4. AutoCheck ALWAYS LAST — must be prepend, not include\n  prepend Msf::Exploit::Remote::AutoCheck\n\n  def initialize(info = {})\n    super(\n      update_info(\n        info,\n        'Name' => 'Vendor Product Vulnerability Type',\n        'Description' => %q{\n          Description of the vulnerability and what this module does.\n        },\n        'Author' => [\n          'Discoverer Name', # Vulnerability discovery\n          'Module Author'    # Metasploit module\n        ],\n        'License' => MSF_LICENSE,\n        'References' => [\n          ['CVE', '2024-XXXXX'],\n          ['URL', 'https://example.com/advisory']\n        ],\n        'Targets' => [\n          [\n            'Automatic',\n            {\n              'Platform' => ['linux'], # or 'win', 'osx', 'unix', 'php', 'python', 'java'\n              '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\n              'Type' => :cmd # or :dropper, :psh_stager — determines payload delivery\n            }\n          ]\n        ],\n        'DefaultTarget' => 0,\n        'DisclosureDate' => '2024-01-01',\n        'Notes' => {\n          'Stability' => [], # e.g. CRASH_SAFE, CRASH_SERVICE_RESTARTS\n          'SideEffects' => [], # e.g. IOC_IN_LOGS, ARTIFACTS_ON_DISK\n          'Reliability' => [] # e.g. REPEATABLE_SESSION\n        }\n      )\n    )\n  end\n\n  def check\n    # Always return CheckCode with a reason string\n    CheckCode::Safe('Target is not vulnerable')\n  end\n\n  def exploit\n    # Exploitation logic\n  end\nend\n```\n\n### Auxiliary Module Template\n\nAuxiliary modules use `def run` (not `exploit`) and inherit from `Msf::Auxiliary`:\n\n```ruby\nclass MetasploitModule < Msf::Auxiliary\n  include Msf::Exploit::Remote::HttpClient\n  include Msf::Auxiliary::Report\n  prepend Msf::Exploit::Remote::AutoCheck\n\n  def initialize(info = {})\n    super(\n      update_info(\n        info,\n        'Name' => 'Vendor Product Scanner/Gatherer',\n        'Description' => %q{\n          Description of what this module discovers or does.\n        },\n        'Author' => ['Author Name'],\n        'License' => MSF_LICENSE,\n        'References' => [['CVE', '2024-XXXXX']],\n        'Notes' => {\n          'Stability' => [], # e.g. CRASH_SAFE\n          'SideEffects' => [], # e.g. IOC_IN_LOGS\n          'Reliability' => [] # e.g. REPEATABLE_SESSION\n        }\n      )\n    )\n\n    register_options([\n      OptString.new('TARGETURI', [true, 'Base path', '/'])\n    ])\n  end\n\n  def check\n    CheckCode::Safe('Target is not affected')\n  end\n\n  def run\n    # Main logic — use report_service, report_vuln, print_good, etc.\n  end\nend\n```\n\n### Post Module Template\n\nPost modules inherit from `Msf::Post`, require a session, and declare compatible session types:\n\n```ruby\nclass MetasploitModule < Msf::Post\n  include Msf::Post::File\n  include Msf::Post::Linux::System\n\n  def initialize(info = {})\n    super(\n      update_info(\n        info,\n        'Name' => 'Platform Subsystem Gather/Action',\n        'Description' => %q{\n          Description of what this post module does on the target.\n        },\n        'Author' => ['Author Name'],\n        'License' => MSF_LICENSE,\n        'Platform' => ['linux'], # or 'win', 'osx', 'unix', 'bsd', 'solaris'\n        'SessionTypes' => ['meterpreter', 'shell'], # or just ['meterpreter'] if shell won't work\n        'Notes' => {\n          'Stability' => [], # e.g. CRASH_SAFE\n          'SideEffects' => [], # e.g. ARTIFACTS_ON_DISK, CONFIG_CHANGES\n          'Reliability' => []\n        }\n      )\n    )\n  end\n\n  def run\n    # Use create_process, file_exist?, read_file, etc.\n    # Access session via `session` method\n  end\nend\n```\n\n### Notes Hash Reference\n\nThe `Notes` hash declares the module's operational characteristics:\n\n| Key | Values | Meaning |\n|-----|--------|---------|\n| `Stability` | `CRASH_SAFE`, `CRASH_SERVICE_RESTARTS`, `CRASH_SERVICE_DOWN`, `CRASH_OS_RESTARTS`, `CRASH_OS_DOWN` | Impact on target stability |\n| `SideEffects` | `IOC_IN_LOGS`, `ARTIFACTS_ON_DISK`, `CONFIG_CHANGES`, `ACCOUNT_LOCKOUTS`, `SCREEN_EFFECTS`, `AUDIO_EFFECTS`, `PHYSICAL_EFFECTS` | Observable traces left on target |\n| `Reliability` | `REPEATABLE_SESSION`, `FIRST_ATTEMPT_FAIL`, `UNRELIABLE_SESSION`, `EVENT_DEPENDENT` | How reliably the module succeeds |\n\nSee also: [`lib/msf/core/constants.rb`](lib/msf/core/constants.rb) for the full list of valid values with descriptions.\n\n**Which module types require Notes:**\n\n| Module Type | Notes Required? | Enforced By |\n|-------------|----------------|-------------|\n| Exploit | **Yes** | msftidy + rubocop (`Lint/ModuleEnforceNotes`) |\n| Auxiliary | **Yes** | rubocop (`Lint/ModuleEnforceNotes`) |\n| Post | **Yes** | rubocop (`Lint/ModuleEnforceNotes`) |\n| Evasion | No | — |\n| Payload | No | — |\n| Encoder | No | — |\n| Nop | No | — |\n\nThe 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.\n\n### Metadata Source Reference\n\nThe inline comments in the templates above list common values but are **not exhaustive**. Consult these source files for the full set:\n\n| Field | Source File | Notes |\n|-------|------------|-------|\n| 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'`) |\n| 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. |\n| Stability / SideEffects / Reliability | [`lib/msf/core/constants.rb`](lib/msf/core/constants.rb) | All valid Notes hash values with descriptions |\n| Rank | [`lib/msf/core/constants.rb`](lib/msf/core/constants.rb) | `ManualRanking` through `ExcellentRanking` |\n| CheckCode | [`lib/msf/core/exploit.rb`](lib/msf/core/exploit.rb) (line ~52) | `Vulnerable`, `Appears`, `Safe`, `Detected`, `Unknown`, `Unsupported` |\n\n### Mixin Ordering\n\nFollow this order for includes and prepends in module classes:\n\n1. **Protocol mixins** — `Msf::Exploit::Remote::HttpClient`, `RubySMB`, `Msf::Exploit::Remote::Udp`, etc.\n2. **Utility/feature mixins** — `Msf::Exploit::FileDropper`, `Msf::Exploit::CmdStager`, `Msf::Exploit::EXE`, etc.\n3. **Reporting mixins** — `Msf::Auxiliary::Report`\n4. **Post mixins** (if needed) — `Msf::Post::File`, `Msf::Post::Linux::Priv`, etc.\n5. **`prepend Msf::Exploit::Remote::AutoCheck`** — always last, after all includes\n\nAutoCheck must use `prepend`, not `include` (the module raises `NotImplementedError` if included). It wraps the `exploit`/`run` method to automatically call `check` before exploitation.\n\n### Module Development\n\n#### Metadata and Structure\n\n- 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\n- Prefer using hash over an array for return values, and use kwargs for reusable APIs for future extensions\n- Before writing a new module, check that there is not an existing module or open pull request that already covers the same functionality\n- Each module should be in its own file under the appropriate `modules/` subdirectory. In some scenarios adding module actions or targets is preferred\n- Exploits require a `DisclosureDate` field\n- Exploits, auxiliary, and post modules require `Notes` with `Stability`, `SideEffects`, and `Reliability`\n- License new code with `MSF_LICENSE` (the project default, defined in `lib/msf/core/constants.rb`)\n- Module descriptions or documentation should list the range of vulnerable versions and the fixed version of the affected software, when known\n- Module descriptions should only use ASCII characters\n- 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\n- If there's only one `ACTION` in the exploit, it can likely be omitted\n\n#### Payloads and Targets\n\n- When possible don't set a default payload (`DefaultOptions` with `'PAYLOAD'`) in modules — let the framework choose the most appropriate payload automatically\n- Define bad characters instead of explicitly base-64 encoding payloads\n- Don't check the number of sessions at the end of an exploit and report success based on that — not all payloads open sessions\n- Don't submit any kind of opaque binary blob — everything must include source code and build instructions\n\n**Payload selection guidance:**\n\n| Scenario | Approach |\n|----------|----------|\n| Only command execution available (no file write) | Use `ARCH_CMD` payloads |\n| Only HTTP(S) outbound (curl/wget available) | Use fetch payload (`Msf::Exploit::Remote::HttpServer` + fetch handler) |\n| File write possible on target | Use dropper/EXE payload (`Msf::Exploit::EXE`) |\n| Full command stager needed (multi-step upload) | Use `Msf::Exploit::CmdStager` — but prefer fetch when only download mechanisms are available |\n\n#### File and Network Operations\n\n- When overriding `cleanup`, always call `super` to ensure the parent mixin chain cleans up connections and sessions properly\n- When opening a file, make sure the file exists first\n- Don't print host information like `#{ip}:#{port}` because it doesn't handle IPv6 addresses — use `#{Rex::Socket.to_authority(ip, port)}`\n- 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\n\n#### Output and Reporting\n\n- All `print_*` calls should start with a capital letter\n- Call `report_service` when a service can be reported\n- Call `report_vuln` when a vulnerability can be reported\n- When creating a fake account / username use the `Faker` gem (e.g. `Faker::Internet.username`) not `Rex::Text.rand_text_alphanumeric`\n\n#### Session and Post-Exploitation\n\n- Use `create_process(executable, args: [], time_out: 15, opts: {})` instead of the deprecated `cmd_exec` with separate arguments\n- Use `Msf::OptionalSession` for modules that work both with and without an existing session (e.g. local exploits that can also run standalone)\n- Use the module mixin APIs — don't reinvent the wheel\n\n#### Internationalisation Considerations\n\n- When checking for a string in a response — will it always be in English?\n- Ensure hardcoded strings being regex'ed will be consistent across multiple versions\n\n### Check Methods\n\n- `check` methods must only return `CheckCode` values (e.g. `CheckCode::Vulnerable`, `CheckCode::Safe`) — never raise exceptions or call `fail_with`\n- When writing a `check` method, verify it does not produce false positives when run against unrelated software or services\n- Prefer using `Rex::Version` for version checks\n- 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\n- `get_version` methods should return a REX version\n- `CheckCode::Vulnerable` is only used when the vulnerability has been exploited\n- `CheckCode::Appears` is only used when the application's version has been checked\n- 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\n- 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\n- Catch exceptions that may be raised and ensure a valid CheckCode is returned\n- Research and determine a minimum version where the application is vulnerable; mark prior versions as safe\n- 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\n- Prefer `prepend Msf::Exploit::Remote::AutoCheck` over manually calling `check` inside `exploit` — this lets the framework handle check-before-exploit automatically\n\n### Library Code\n\nWhen writing or modifying code in `lib/`:\n\n#### Error Handling\n- Use specific error classes (`Rex::RuntimeError`, `Rex::ConnectionError`, `ArgumentError`, `Rex::TimeoutError`) — never `raise \"bare string\"` which makes targeted rescue impossible\n- 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)\n- Propagate errors with context: `raise Rex::ConnectionError, \"Failed to connect to #{host}: #{e.message}\"`\n\n#### Documentation and Style\n- Add YARD `@param` and `@return` tags to all public methods\n- Add `# frozen_string_literal: true` to new library files\n- 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`)\n- Link to the specification or RFC when implementing binary/protocol parsers\n\n#### Quality\n- Write RSpec tests for any library changes — tests live in `spec/` mirroring the `lib/` structure\n- Follow [Better Specs](https://www.betterspecs.org/) conventions\n- Keep PRs focused — small fixes are easier to review\n- Any new hash cracking implementations require adding a test hash to `tools/dev/hash_cracker_validator.rb` and ensuring that passes without error\n\n### Testing\n\n- Tests live in `spec/` mirroring the `lib/` structure\n- Run a single spec file: `bundle exec rspec spec/path/to/spec.rb`\n- Run a single example by line: `bundle exec rspec spec/path/to/spec.rb:42`\n- Run the full suite: `bundle exec rake spec` (slow — prefer targeted runs during development)\n- Module functional tests live under `spec/modules/` and test end-to-end behaviour\n- Always run specs relevant to your change before submitting\n\n### Preferred Libraries\n\n- Use the `RubySMB` library for SMB modules\n- Use `Rex::Stopwatch.elapsed_time` to track elapsed time\n- Use the `Rex::MIME::Message` class for MIME messages instead of hardcoding XML\n- 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\n- Use `Msf::Exploit::SQLi` when exploiting SQL injection vulnerabilities\n\n## Common Patterns\n\n### Options Registration\n\n```ruby\nregister_options([\n  OptString.new('TARGETURI', [true, 'Base path to the application', '/']),\n  OptInt.new('TIMEOUT', [true, 'Request timeout in seconds', 10]),\n  OptBool.new('SSL', [false, 'Use SSL/TLS', false])\n])\n\nregister_advanced_options([\n  OptString.new('UserAgent', [false, 'Custom User-Agent header'])\n])\n```\n\n- Use `SCREAMING_SNAKE_CASE` for standard option names and `CamelCase` for advanced option names\n- Access options via `datastore['OPTION_NAME']`\n\n### Console Output\n\n- Use `print_status`, `print_good`, `print_error`, `print_warning` for console output\n- Use `vprint_*` variants for verbose-only output (shown when user sets `VERBOSE true`)\n\n### HTTP Response Handling\n\n```ruby\nres = send_request_cgi(\n  'method' => 'GET',\n  'uri' => normalize_uri(target_uri.path, 'api', 'version')\n)\n\nfail_with(Failure::Unreachable, 'Target did not respond') unless res\nfail_with(Failure::UnexpectedReply, \"Unexpected status: #{res.code}\") unless res.code == 200\n\njson = res.get_json_document\nfail_with(Failure::UnexpectedReply, 'Response is not valid JSON') if json.empty?\n\n# For HTML parsing:\nhtml = res.get_html_document\nversion = html.at_css('meta[name=\"version\"]')&.[]('content')\n```\n\n- Always use `res.get_json_document` — never `JSON.parse(res.body)`\n- Use `res.get_html_document` with CSS selectors for HTML parsing\n- Check `res` for nil (target didn't respond) before accessing `.code` or `.body`\n- Use `fail_with(Failure::*, 'reason')` for error conditions in `exploit`/`run`\n\n### Network Operations\n\n- Use `send_request_cgi` for HTTP requests in modules\n- Use `connect` / `disconnect` for TCP socket operations\n- Use the `srvhost` method to access the server host — don't use `datastore['SRVHOST']` directly (enforced by `Lint/DatastoreSrvhostUsage` cop)\n\n## Legacy Patterns (Migration Guidance)\n\nThese 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:\n\n| Legacy Pattern | Modern Replacement | Notes |\n|---------------|-------------------|-------|\n| `HttpFingerprint = { :pattern => [...] }` | Implement a `check` method + `prepend AutoCheck` | HttpFingerprint is a passive fingerprinting mechanism that predates the check API |\n| `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 |\n| `cmd_exec(cmd, args_string, timeout)` | `create_process(cmd, args: args_array, time_out: timeout)` | Enforced by `Lint/DetectOutdatedCmdExecApi` rubocop cop |\n| `DefaultOptions => { 'PAYLOAD' => '...' }` | Remove — let the framework choose automatically | Only acceptable when the module genuinely only works with a single specific payload |\n| `include Msf::Exploit::Remote::AutoCheck` | `prepend Msf::Exploit::Remote::AutoCheck` | Include raises NotImplementedError; prepend is required |\n| Bare `rescue` in library code | `rescue StandardError => e` | Bare rescue discards the exception object; `rescue Exception` is worse — it catches signals/exits |\n| `raise \"error message\"` in library code | `raise Rex::RuntimeError, \"message\"` | Specific classes enable targeted error handling |\n| Manual `check` call inside `exploit` | `prepend AutoCheck` + separate `check` method | Let the framework handle check-before-exploit |\n\n### Modernizing Existing Modules\n\nWhen updating an existing module, the lowest-effort improvement is adding AutoCheck:\n\n```ruby\n# If the module already has a `def check` method, just add this line\n# after the other includes:\nprepend Msf::Exploit::Remote::AutoCheck\n```\n\nThis 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`).\n\n## Before Submitting\n\n- Work on a topic branch — don't commit directly to `master`\n- 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)\n- Ensure `rubocop` and `msftidy` pass on any changed files with no new offenses\n- Ensure `ruby tools/dev/msftidy_docs.rb <documentation_file>` passes on any changed documentation markdown docs with no new offenses\n- Include console output (especially `msfconsole` demonstrations) in your pull request when the changes have observable effects\n- Include verification steps so reviewers can test your changes\n- Reference associated issues in your pull request description (e.g., `See #1234`)\n\n## What NOT to Do\n\n- Don't submit untested code — all code must be manually verified\n- Don't include sensitive information (IPs, credentials, API keys, hashes of credentials) in code or docs\n- Don't include more than one module per pull request\n- Don't add new scripts to `scripts/` — use post modules instead\n- Don't use `pack`/`unpack` with invalid directives (enforced by linter)\n",".github/copilot-instructions.md":"# Copilot Instructions\n\nRefer to [AGENTS.md](../AGENTS.md) in the repository root for all project conventions, coding standards, and AI agent guidelines.\n\nPath-scoped instructions in `.github/instructions/` provide file-type-specific guidance for modules, library code, tests, and documentation.\n"}}