Skip to content

security: pre-release hardening#7

Merged
notque merged 1 commit into
mainfrom
security/pre-release-hardening
May 7, 2026
Merged

security: pre-release hardening#7
notque merged 1 commit into
mainfrom
security/pre-release-hardening

Conversation

@notque
Copy link
Copy Markdown
Owner

@notque notque commented May 7, 2026

Summary

Comprehensive security hardening before public release. Addresses findings from security audit of credential handling, input validation, and response sanitization.

Critical

  • Nova AdminPass leak: getServerHandler was marshalling the entire gophercloud Server struct, which includes AdminPass. Switched to explicit field allowlist (same pattern as ironic.go)

High

  • SSE binds localhost: Changed from 0.0.0.0 to 127.0.0.1 (SSE has no auth — network binding was dangerous)
  • URL path injection: Added UUID validation to all ID parameters used in URL path construction (archer, keppel, limes). Prevents ../../admin/tokens style attacks
  • Query param injection: Replaced raw string concatenation with SafeQueryParams() using proper url.QueryEscape() (archer, keppel, limes)
  • adminPass in sanitizer: Added adminPass and admin_pass to sensitive keys as defense-in-depth

Medium

  • Token race fix: provider.Token() now uses gophercloud's mutex-protected Token() method instead of direct .TokenID field access

Release readiness

  • Added root LICENSE file (GitHub license detection)
  • Added SECURITY.md (vulnerability reporting policy)
  • Fixed 6 wrong tool names in README Services table
  • Added companion toolkit link

Tests

  • UUID validation (valid + 8 injection vectors)
  • Path segment validation (valid + 9 attack patterns)
  • SafeQueryParams encoding (special chars, spaces, empty values)
  • adminPass redaction (case-insensitive)

Test plan

  • make build-all passes
  • go test ./... — all tests pass (including new security tests)
  • make run-golangci-lint — 0 issues
  • reuse lint — compliant
  • UUID validation rejects path traversal, SQL injection, query injection
  • SafeQueryParams properly encodes &, =, spaces
  • adminPass field is now redacted by sanitizer

CRITICAL:
- Nova getServerHandler: switch to field allowlist (AdminPass was leaking
  via full struct serialization)

HIGH:
- SSE transport: bind 127.0.0.1 by default (was 0.0.0.0 with no auth)
- URL path injection: add UUID validation for all ID params in URL paths
  (archer, keppel, limes)
- Query param injection: use SafeQueryParams with url.QueryEscape instead
  of raw string concatenation
- Sanitizer: add "adminPass" and "admin_pass" to sensitive keys list

MEDIUM:
- Token race: use mutex-protected Token() accessor instead of direct
  .TokenID field access

Also:
- Add root LICENSE file (GitHub detection)
- Add SECURITY.md (vulnerability reporting)
- Fix README tool names (6 were wrong)
- Add companion toolkit link to README
- Add security validation tests (UUID, path segment, query encoding,
  adminPass redaction)
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2026

Merging this branch changes the coverage (2 decrease, 3 increase)

Impacted Packages Coverage Δ 🤖
github.com/notque/openstack-mcp-server/internal/auth 0.00% (ø)
github.com/notque/openstack-mcp-server/internal/server 0.00% (ø)
github.com/notque/openstack-mcp-server/internal/tools/archer 11.76% (+0.34%) 👍
github.com/notque/openstack-mcp-server/internal/tools/keppel 10.71% (-1.05%) 👎
github.com/notque/openstack-mcp-server/internal/tools/limes 10.34% (+2.45%) 👍
github.com/notque/openstack-mcp-server/internal/tools/nova 10.47% (-0.12%) 👎
github.com/notque/openstack-mcp-server/internal/tools/shared 68.52% (+14.67%) 🎉

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
github.com/notque/openstack-mcp-server/internal/auth/provider.go 0.00% (ø) 132 0 132
github.com/notque/openstack-mcp-server/internal/server/server.go 0.00% (ø) 58 0 58
github.com/notque/openstack-mcp-server/internal/tools/archer/archer.go 11.76% (+0.34%) 68 (-2) 8 60 (-2) 👍
github.com/notque/openstack-mcp-server/internal/tools/keppel/keppel.go 10.71% (-1.05%) 56 (+5) 6 50 (+5) 👎
github.com/notque/openstack-mcp-server/internal/tools/limes/limes.go 10.34% (+2.45%) 58 (-18) 6 52 (-18) 👍
github.com/notque/openstack-mcp-server/internal/tools/nova/nova.go 10.47% (-0.12%) 86 (+1) 9 77 (+1) 👎
github.com/notque/openstack-mcp-server/internal/tools/shared/helpers.go 50.00% (+50.00%) 64 (+30) 32 (+32) 32 (-2) 🌟
github.com/notque/openstack-mcp-server/internal/tools/shared/sanitize.go 95.45% (ø) 44 42 2

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • github.com/notque/openstack-mcp-server/internal/tools/shared/helpers_test.go

@notque notque merged commit 7e8f70c into main May 7, 2026
4 checks passed
@notque notque deleted the security/pre-release-hardening branch May 7, 2026 13:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant