From 6207ad9a0fded4ca393b5ab22613d2bf2e42b0be Mon Sep 17 00:00:00 2001 From: cbdmaul Date: Fri, 31 Jul 2026 12:53:33 -0400 Subject: [PATCH] docs+chore: correct listener bind-default wording; archive release-and-ci-hardening - README: the 0.0.0.0 listener bind default was mislabeled a "Secure Default". It binds all interfaces for reverse-connection compatibility, which is not a hardened default. Reframe it as a compatibility choice with an explicit warning and point operators at `reverselistenerbindaddress` to restrict it. Also correct the overstated "bind address validation" / "input sanitization" descriptions to match what the code actually enforces. - Archive the shipped release-and-ci-hardening OpenSpec change; sync its specs (ci-quality-gates, sbom-release-integration) into openspec/specs/. Co-Authored-By: Claude Opus 4.8 --- README.md | 21 ++++++--- .../.openspec.yaml | 0 .../design.md | 0 .../proposal.md | 0 .../specs/ci-quality-gates/spec.md | 0 .../specs/sbom-release-integration/spec.md | 0 .../tasks.md | 8 ++-- openspec/specs/ci-quality-gates/spec.md | 47 +++++++++++++++++++ .../specs/sbom-release-integration/spec.md | 33 +++++++++++++ 9 files changed, 99 insertions(+), 10 deletions(-) rename openspec/changes/{release-and-ci-hardening => archive/2026-07-31-release-and-ci-hardening}/.openspec.yaml (100%) rename openspec/changes/{release-and-ci-hardening => archive/2026-07-31-release-and-ci-hardening}/design.md (100%) rename openspec/changes/{release-and-ci-hardening => archive/2026-07-31-release-and-ci-hardening}/proposal.md (100%) rename openspec/changes/{release-and-ci-hardening => archive/2026-07-31-release-and-ci-hardening}/specs/ci-quality-gates/spec.md (100%) rename openspec/changes/{release-and-ci-hardening => archive/2026-07-31-release-and-ci-hardening}/specs/sbom-release-integration/spec.md (100%) rename openspec/changes/{release-and-ci-hardening => archive/2026-07-31-release-and-ci-hardening}/tasks.md (79%) create mode 100644 openspec/specs/ci-quality-gates/spec.md create mode 100644 openspec/specs/sbom-release-integration/spec.md diff --git a/README.md b/README.md index d421f88..2ddd0fe 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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 diff --git a/openspec/changes/release-and-ci-hardening/.openspec.yaml b/openspec/changes/archive/2026-07-31-release-and-ci-hardening/.openspec.yaml similarity index 100% rename from openspec/changes/release-and-ci-hardening/.openspec.yaml rename to openspec/changes/archive/2026-07-31-release-and-ci-hardening/.openspec.yaml diff --git a/openspec/changes/release-and-ci-hardening/design.md b/openspec/changes/archive/2026-07-31-release-and-ci-hardening/design.md similarity index 100% rename from openspec/changes/release-and-ci-hardening/design.md rename to openspec/changes/archive/2026-07-31-release-and-ci-hardening/design.md diff --git a/openspec/changes/release-and-ci-hardening/proposal.md b/openspec/changes/archive/2026-07-31-release-and-ci-hardening/proposal.md similarity index 100% rename from openspec/changes/release-and-ci-hardening/proposal.md rename to openspec/changes/archive/2026-07-31-release-and-ci-hardening/proposal.md diff --git a/openspec/changes/release-and-ci-hardening/specs/ci-quality-gates/spec.md b/openspec/changes/archive/2026-07-31-release-and-ci-hardening/specs/ci-quality-gates/spec.md similarity index 100% rename from openspec/changes/release-and-ci-hardening/specs/ci-quality-gates/spec.md rename to openspec/changes/archive/2026-07-31-release-and-ci-hardening/specs/ci-quality-gates/spec.md diff --git a/openspec/changes/release-and-ci-hardening/specs/sbom-release-integration/spec.md b/openspec/changes/archive/2026-07-31-release-and-ci-hardening/specs/sbom-release-integration/spec.md similarity index 100% rename from openspec/changes/release-and-ci-hardening/specs/sbom-release-integration/spec.md rename to openspec/changes/archive/2026-07-31-release-and-ci-hardening/specs/sbom-release-integration/spec.md diff --git a/openspec/changes/release-and-ci-hardening/tasks.md b/openspec/changes/archive/2026-07-31-release-and-ci-hardening/tasks.md similarity index 79% rename from openspec/changes/release-and-ci-hardening/tasks.md rename to openspec/changes/archive/2026-07-31-release-and-ci-hardening/tasks.md index 0c65a35..6a587f9 100644 --- a/openspec/changes/release-and-ci-hardening/tasks.md +++ b/openspec/changes/archive/2026-07-31-release-and-ci-hardening/tasks.md @@ -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) @@ -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 diff --git a/openspec/specs/ci-quality-gates/spec.md b/openspec/specs/ci-quality-gates/spec.md new file mode 100644 index 0000000..b238705 --- /dev/null +++ b/openspec/specs/ci-quality-gates/spec.md @@ -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 + diff --git a/openspec/specs/sbom-release-integration/spec.md b/openspec/specs/sbom-release-integration/spec.md new file mode 100644 index 0000000..d1d33dd --- /dev/null +++ b/openspec/specs/sbom-release-integration/spec.md @@ -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 +