Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@ An **unofficial**, modern, secure Model Context Protocol (MCP) server that provi
- **Security Validation**: Built-in bind address validation and input sanitization

### Security Features
- **Bind Address Validation**: Ensures listeners only bind to authorized interfaces
- **Input Sanitization**: Comprehensive validation of all parameters
- **Secure Defaults**: Listeners default to `0.0.0.0` binding for maximum compatibility
- **Bind Address Validation**: Rejects bind addresses that are neither a wildcard nor an IP configured on the host
- **Input Sanitization**: Comprehensive validation of all parameters, including rejection of control characters in module options (command-injection guard)
- **Error Handling**: Prevents information leakage through proper error management

> ⚠️ **Binding default is `0.0.0.0` (all interfaces) for compatibility, not security.**
> Reverse-handler listeners default to binding all interfaces so payloads on remote
> targets can connect back. This is intentional for offensive use but is **not** a
> locked-down default — on a shared or untrusted network, restrict it by passing an
> explicit `reverselistenerbindaddress` (e.g. a specific interface IP).

### Modern Development
- **Poetry Dependency Management**: Modern Python packaging and dependency resolution
- **Comprehensive Testing**: 92+ tests covering unit, integration, and security scenarios
Expand Down Expand Up @@ -211,14 +216,18 @@ metasploit-mcp --transport http --host 0.0.0.0 --port 8085

### Security Features

- **Bind Address Validation**: Prevents binding to unauthorized network interfaces
- **Input Sanitization**: All parameters are validated before processing
- **Secure Defaults**: Listeners default to `0.0.0.0` for maximum compatibility
- **Bind Address Validation**: Rejects addresses that are neither a wildcard nor a host-configured IP
- **Input Sanitization**: All parameters are validated before processing; control characters in module options are rejected (command-injection guard)
- **Error Handling**: Prevents information disclosure through proper error management

> ⚠️ **Listeners bind `0.0.0.0` (all interfaces) by default** — a compatibility choice for
> catching reverse connections, **not** a hardened default. Pass an explicit
> `reverselistenerbindaddress` to restrict the binding on shared/untrusted networks.

### Best Practices

- Only use in authorized testing environments
- Restrict listener bind addresses (`reverselistenerbindaddress`) when you don't need all interfaces
- Validate all commands before execution
- Monitor generated payloads and their usage
- Use strong passwords for Metasploit RPC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
- [x] 2.2 Add a `quality` job: `black --check` (blocking) over `src` and `tests`
- [x] 2.3 Add `mypy` to the `quality` job for `src/metasploit_mcp` (non-blocking / advisory initially per design D4 — 27 pre-existing errors)
- [x] 2.4 Add a `sbom-check` job (or step) running `scripts/generate_sbom.py --check`
- [ ] 2.5 Verify all new jobs run green on this branch's PR (each step verified locally; actual PR run pending push)
- [x] 2.5 Verify all new jobs run green on this branch's PR (confirmed green on PRs #17/#18 and on main)

## 3. SBOM-on-release (release.yml)

Expand All @@ -27,6 +27,6 @@
## 5. Verification & follow-up

- [x] 5.1 Run `openspec validate release-and-ci-hardening` (valid)
- [ ] 5.2 Dry-run a release on a throwaway tag (or `workflow_dispatch`) to confirm SBOM attaches and PyPI/GH-release steps still pass (requires push; build/twine/sbom steps verified locally)
- [ ] 5.3 (Follow-up) Once the baseline is clean, flip `mypy` to blocking (27 errors in 4 files as of now)
- [ ] 5.4 Archive the change once shipped
- [x] 5.2 Dry-run a release: satisfied by the real v3.0.1 release — SBOM attached to the GitHub Release and PyPI publish succeeded
- [ ] 5.3 (Deferred follow-up) Once the mypy baseline is clean, flip `mypy` to blocking (27 errors in 4 files at ship time)
- [x] 5.4 Archive the change once shipped
47 changes: 47 additions & 0 deletions openspec/specs/ci-quality-gates/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ci-quality-gates Specification

## Purpose
TBD - created by archiving change release-and-ci-hardening. Update Purpose after archive.
## Requirements
### Requirement: CI verifies the distribution is buildable and well-formed

CI SHALL, on every pull request and push to the default branch, build the source distribution and wheel and run `twine check` against them, failing the pipeline if the build fails or metadata is invalid.

#### Scenario: Packaging error caught before release

- **WHEN** a change breaks package metadata or the build
- **THEN** the CI packaging job fails on the pull request, before any release tag is created

#### Scenario: Valid package passes

- **WHEN** the package builds and `twine check` reports no errors
- **THEN** the packaging job succeeds and uploads the built artifacts for inspection

### Requirement: CI enforces code-quality gates

CI SHALL run the project's existing formatting and type-checking tools (`black --check` and `mypy`) on every pull request and push, failing the pipeline on any violation.

#### Scenario: Unformatted code fails CI

- **WHEN** a pull request contains code that does not satisfy `black --check`
- **THEN** the CI quality job fails

#### Scenario: Type error fails CI

- **WHEN** a pull request introduces a `mypy` type error in checked paths
- **THEN** the CI quality job fails

### Requirement: CI verifies the SBOM is up to date

CI SHALL regenerate the SBOM from `poetry.lock` and fail if the committed `sbom.json` differs from the regenerated output, preventing the SBOM from drifting out of sync with the locked dependencies.

#### Scenario: Stale SBOM caught

- **WHEN** dependencies change but `sbom.json` is not regenerated in the same pull request
- **THEN** the CI SBOM-freshness check fails and reports that `sbom.json` is out of date

#### Scenario: Fresh SBOM passes

- **WHEN** `sbom.json` matches the output regenerated from the current `poetry.lock`
- **THEN** the SBOM-freshness check succeeds

33 changes: 33 additions & 0 deletions openspec/specs/sbom-release-integration/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# sbom-release-integration Specification

## Purpose
TBD - created by archiving change release-and-ci-hardening. Update Purpose after archive.
## Requirements
### Requirement: Release build produces a verified SBOM

The release workflow SHALL generate the CycloneDX SBOM during the release build and verify it matches the committed `sbom.json`, failing the release if it is stale.

#### Scenario: SBOM generated at release time

- **WHEN** a release build runs for a pushed version tag
- **THEN** the workflow regenerates the SBOM from `poetry.lock` and confirms it matches the committed `sbom.json`

#### Scenario: Stale SBOM blocks release

- **WHEN** the committed `sbom.json` does not match the regenerated SBOM during a release build
- **THEN** the release build fails with a clear message before publishing

### Requirement: SBOM is published as a release artifact

The release workflow SHALL attach the SBOM to the GitHub Release alongside the built distributions, so consumers can retrieve the bill of materials for any published version.

#### Scenario: SBOM attached to GitHub Release

- **WHEN** a GitHub Release is created for a version tag
- **THEN** the release assets include `sbom.json` in addition to the sdist and wheel

#### Scenario: SBOM version matches release

- **WHEN** the SBOM is attached to a release for version X
- **THEN** the SBOM's root component version equals X

Loading