Skip to content

v2026.5.5 — Security Hardening

Choose a tag to compare

@rosschurchill rosschurchill released this 18 Apr 10:07
· 51 commits to main since this release

MEDUSA v2026.5.5 — Security Hardening

Patch release addressing 8 findings from a red-team review of the MEDUSA scanner codebase. No CVEs are disclosed against earlier versions — these are defense-in-depth improvements.

What changed

Argument injection defense (C-1)

A malicious repo containing a file literally named --config=https://evil.tld/rce.yaml would previously have had the filename re-parsed as an option by semgrep and trivy, causing them to fetch attacker-controlled rule YAML from the network. This is blocked at two layers now: a -- separator before trailing path args, plus a defensive reject of any file whose basename starts with -.

Git URL SSRF defense (H-1, M-2)

medusa scan --git <URL> previously accepted any http(s)/ssh URL with no validation. Now defended with a hostname allowlist (github.com, gitlab.com, bitbucket.org, codeberg.org, plus subdomains) and DNS-rebinding-resistant private IP rejection (is_private/is_loopback/is_link_local/is_reserved/is_multicast on every resolved address). New --allow-any-host flag opts out of the hostname allowlist; private-IP rejection still applies.

Cache integrity (H-2)

~/.medusa/cache/file_cache.json is now HMAC-signed with a machine-local key at ~/.medusa/cache/.hmac_key (mode 0600). An attacker with write access to a dev workstation or CI runner can no longer forge cache entries to silently suppress findings. The v5.4 → v5.5 upgrade path discards the unsigned cache silently and rebuilds on the next scan. Cached findings are also now included in the generated report (previously silently dropped).

Markdown XSS prevention (M-1)

Generated markdown reports now use a dynamic code-fence length based on the content — source code containing ``` can no longer break out of the fence and inject raw HTML into a GitHub / GitLab markdown preview. Filenames with backticks are sanitized before interpolation into inline code spans.

Other hardening

  • L-1 + M-3: Removed two dead HTML builder functions that interpolated severity strings into style attributes without escape.
  • L-3: scan_history.json load is now crash-safe on corrupted or malicious input.

Testing

  • 55 new tests in tests/test_security_hardening.py
  • Full suite: 378 pass + 55 new security tests
  • 11 pre-existing failures (unrelated) confirmed unchanged vs v2026.5.4

Deferred

These two findings from the same review are tracked for separate sprints:

  • License HMAC forgery (medusa/core/licensing.py) — uses a keyless SHA-256 truncated to 16 hex chars. Needs Ed25519 migration + license server coordination.
  • IDE setup symlink race (medusa/ide/claude_code.py) — local attacker only.

Upgrade

pip install --upgrade medusa-security

No breaking API changes. The existing cache file is silently discarded on first scan (unsigned) and rebuilt. First scan after upgrade will be a full rescan.

Install footprint

  • Wheel: 3.2 MB (medusa_security-2026.5.5-py3-none-any.whl)
  • Source: 3.1 MB (medusa_security-2026.5.5.tar.gz)
  • 27 FP pattern YAML files bundled