Skip to content

Conversation

@stas-schaller
Copy link
Contributor

@stas-schaller stas-schaller commented Dec 22, 2025

Summary

Release Python SDK v17.1.0 with security dependency update, Gov Cloud support, storage package boto3 fix, notation shortcut fix, GraphSync links support, secure config file permissions, client version detection fix, proxy SSL settings fix, improved error messages for malformed configs, and improved test coverage.

Changes

Added

  • KSM-740: Added transmission public key renamed module to keepercommandersm and published it to pypi #18 for Gov Cloud Dev support
    • Enables connection to Keeper's Gov Cloud development environment
    • New public key added to keeper_public_keys dictionary in keeper_globals.py
  • KSM-628: Added GraphSync links support
    • Records now include links field with related record references
    • Supports recordUid, data, and path attributes for linked records

Security

  • KSM-760: Fixed CVE-2026-23949 (jaraco.context path traversal) in SBOM generation workflow

    • Upgraded jaraco.context to >= 6.1.0 in SBOM build environment
    • Build-time dependency only, does not affect runtime or published packages
  • Added version-specific urllib3 dependency to address CVE-2025-66418 and CVE-2025-66471 (HIGH severity)

  • KSM-695: Fixed file permissions for client-config.json

    • Config files now created atomically with 0600 permissions (owner read/write only)
    • Prevents world-readable config files containing sensitive credentials
    • Uses os.open() with secure mode instead of regular open()

Fixed

  • KSM-763: Fixed file upload/download operations failing when using proxy with verify_ssl_certs=False (PR KSM-763: fix file upload/download SSL and proxy settings #923)
    • Problem: When using the SDK with a proxy server and verify_ssl_certs=False, file upload and download operations failed with SSL certificate verification errors. The verify_ssl_certs and proxy_url settings were not being passed to the underlying requests library calls.
    • Root Cause:
      • __upload_file_function() was missing verify parameter in requests.post()
      • KeeperFile.get_file_data() was missing both verify and proxies parameters in requests.get()
      • KeeperFile.save_file() didn't pass parameters through to get_file_data()
    • Solution:
      • Added verify_ssl_certs parameter to __upload_file_function() and pass to requests.post()
      • Added verify_ssl_certs and proxy_url parameters to KeeperFile.get_file_data() and save_file()
      • Updated all callers to pass these parameters from SecretsManager instance
    • Test Coverage: Added 2 new tests in tests/proxy_test.py
      • test_verify_ssl_certs_passed_to_upload_file - Verifies upload respects SSL settings
      • test_verify_ssl_certs_passed_to_file_download - Verifies download respects SSL settings
    • Verification: Tested in vitro with mitmproxy - both file upload and download work correctly through proxy with SSL verification disabled
    • Impact: Users can now successfully upload and download files when using proxies with custom SSL certificate handling
  • KSM-650: Improved error messages for malformed config files (PR KSM-650: improve error messages for malformed config files #922)
    • Problem: Cryptic errors when config files are corrupted or truncated (common during copy-paste)
      • Previous: binascii.Error: Incorrect padding or ValueError: Could not deserialize key data
      • Users couldn't identify the root cause (malformed config file)
    • Solution: Added comprehensive error handling with helpful messages
      • base64_to_bytes() now catches binascii.Error and raises KeeperError with context
      • der_base64_private_key_to_private_key() wraps decoding errors with configuration hints
      • extract_public_key_bytes() provides clear guidance when private key is invalid
      • All error messages explicitly mention "configuration" and suggest checking for truncation
    • Test Coverage: Added tests/config_error_test.py with 7 comprehensive tests (125 lines)
      • Tests malformed base64 (incorrect padding, invalid length)
      • Tests truncated private keys (common user error)
      • Tests empty/corrupted private keys
      • Validates error messages are helpful and actionable
    • Impact: Users will get clear, actionable error messages when config files are malformed
    • Example new error: "Failed to decode base64 data: Incorrect padding. This may indicate a malformed or corrupted value in your configuration. Please verify your configuration file is valid and has not been truncated."
  • KSM-749: Fixed client version detection from stale .dist-info metadata (PR KSM-749: fix client version detection from stale .dist-info metadata #910)
    • Problem: SDK relied on importlib_metadata.version() which reads filesystem metadata. During package upgrades, stale .dist-info directories from previous installations could remain, causing SDK to report incorrect versions and triggering "invalid client version id" backend authentication failures
    • Solution: Introduced single source of truth via _version.py
      • Created keeper_secrets_manager_core/_version.py with __version__ attribute
      • Modified get_client_version() to prioritize package __version__ over importlib_metadata
      • Updated setup.py to import version dynamically (eliminates manual sync across files)
      • Added fallback chain: __version__importlib_metadata → hardcoded default
    • Impact: Users will no longer encounter "invalid client version id: X, mpY.Z.W" errors after upgrading the package
    • Fully backward compatible, no breaking changes
  • KSM-732: Fixed notation lookup when record shortcuts exist
    • Deduplicates records by UID before notation resolution
    • Prevents ValueError: Notation error - found multiple records with same UID when KSM app has access to both original record and its shortcut
    • Preserves genuine ambiguity check for different records with same title
  • Storage package now declares boto3>=1.20.0 as explicit dependency
    • Fixes ImportError: cannot import name 'IMDSFetcher' from 'botocore.utils'
    • Storage v1.0.2 → v1.0.3
    • Previously boto3 was an undeclared dependency causing test failures

Changed

  • Core SDK: Version bumped from v17.0.0 to v17.1.0
  • Storage: Version bumped from v1.0.2 to v1.0.3
  • Updated README.md with deprecation notice, CVE fixes, and full changelog

Tests

  • Added KSM-763 test suite: 2 new tests for proxy SSL settings (PR KSM-763: fix file upload/download SSL and proxy settings #923)
    • Tests upload respects verify_ssl_certs and proxy_url parameters
    • Tests download respects verify_ssl_certs and proxy_url parameters
    • Verified in vitro with mitmproxy
  • Added KSM-650 test suite: 7 new tests (125 lines) for config error handling
    • Tests all error paths for malformed base64 and private keys
    • Validates error messages are helpful and actionable
  • Improved test coverage: All 18 transmission keys now validated (was only 1-6)
  • Added GraphSync links test: Verifies links field structure and data
  • Added comprehensive client version detection tests (KSM-749):
    • Tests normal __version__ path
    • Tests hardcode mode
    • Tests fallback to importlib_metadata
    • Tests version format validation
    • Tests stale metadata scenario: Verifies __version__ takes precedence over stale importlib_metadata (the actual KSM-749 bug)
  • Updated mock framework: Added links support to mock.Record class
  • 57 tests now pass (was 50, added 7 KSM-650 + 2 KSM-763 tests)

Testing

  • Verify correct urllib3 version installed based on Python version:
    • Python 3.10+: pip show urllib3 should show 2.6.0+
    • Python 3.6-3.9: pip show urllib3 should show 1.26.x
  • Run existing test suite across Python 3.8-3.12: pytest (57 tests pass)
  • Check dependency resolution: pip show urllib3 and pip show boto3
  • Verify Gov Cloud public key renamed module to keepercommandersm and published it to pypi #18 is present in keeper_globals.py
  • Verify storage package installs boto3: pip install keeper-secrets-manager-storage
  • Test proxy SSL settings (KSM-763):
    • Run proxy tests: pytest tests/proxy_test.py -v
    • Verify file uploads work through proxy with verify_ssl_certs=False
    • Verify file downloads work through proxy with verify_ssl_certs=False
  • Test client version detection (KSM-749):
    • Verify version: python -c "import keeper_secrets_manager_core; print(keeper_secrets_manager_core.__version__)"
    • Should output: 17.1.0
    • Run version tests: pytest tests/smoke_test.py::SmokeTest::test_client_version -v
  • Test config error messages (KSM-650):
    • Run error tests: pytest tests/config_error_test.py -v
    • Manually test with truncated config file to verify helpful error message
  • Test GraphSync links: Verify records with linked records include links field with correct structure
  • Test notation with shortcuts: Access record via notation when both original and shortcut exist, verify no duplicate UID error
  • Test secure file permissions: Verify new client-config.json files created with 0600 permissions

Upgrade Path

No immediate action required, but users should plan to upgrade Python before v17.2.0 release:

  1. Check your Python version: python --version
  2. If < 3.10, plan upgrade before ~February 16, 2026:
  3. Update your virtual environment or container images to Python 3.10+
  4. Test with current SDK version before v17.2.0 releases

Known CI Issue (Not Related to This Release)

test-ansible failures on all Python versions are NOT caused by Python SDK changes.

Root Cause: Test isolation bug in integration/keeper_secrets_manager_ansible/tests/keeper_ansible_test.py

  • Test test_ansible_cli_config sets PSModulePath environment variable but never cleans it up
  • Causes test to fail with: AssertionError: Regex didn't match: 'set ANSIBLE_ACTION_PLUGINS' not found
  • Expected: set ANSIBLE_ACTION_PLUGINS (Windows CMD syntax)
  • Actual: $env:ANSIBLE_ACTION_PLUGINS (PowerShell syntax, due to PSModulePath pollution)

Evidence This Is Not a Python SDK Issue:

  • All test-python tests pass (3.8-3.12) - 57/57 tests
  • All test-cli tests pass (3.8-3.12)
  • No changes to Ansible integration code in this PR
  • Same test failure occurs across all Python versions (3.8-3.12)

Fix Location: Will be addressed in Ansible Integration v1.2.7 release (PR #904)

Verification: Python SDK v17.1.0 functionality is fully validated by passing test-python and test-cli suites.

Related Issues

  • Closes Python package should require urllib3>=2.6.0 to avoid vulnerable resolver outcomes #878 (urllib3 security vulnerability - partial fix, see note below)
  • Implements KSM-740 (Gov Cloud support)
  • Implements KSM-628 (GraphSync links support)
  • Implements KSM-763 (proxy SSL settings fix)
  • Implements KSM-650 (improved error messages for malformed configs)
  • Fixes KSM-749 (client version detection from stale metadata)
  • Fixes KSM-732 (notation lookup with shortcuts)
  • Fixes KSM-695 (secure config file permissions)
  • Fixes test-cli (3.9) failure from undeclared boto3 dependency
  • Fixes KSM-760 (CVE-2026-23949 in SBOM generation)

Note on Issue #878 (urllib3 Security)

Full fix applied: Python 3.10+ users get urllib3>=2.6.0 (CVE-free)

Partial fix: Python 3.6-3.9 users get urllib3 1.26.x due to boto3/botocore compatibility constraints

  • urllib3 1.26.x is still vulnerable to CVE-2025-66418 and CVE-2025-66471
  • Affected users should upgrade to Python 3.10+ for full security fixes
  • We are investigating which Python versions will be unsupported in v17.2.0

Note

KSM-747 (record key decryption for shared folders) was initially included but has been removed in commit 6e921dd. This fix will be released in a separate coordinated release across all SDKs.

@stas-schaller stas-schaller marked this pull request as ready for review January 8, 2026 17:47
stas-schaller and others added 11 commits January 8, 2026 15:56
- Add boto3>=1.20.0 as explicit dependency (required for IMDSFetcher in AWS storage provider)
- Raise minimum Python version from 3.6 to 3.9 (aligns with Core SDK v17.1.0)
- Bump storage version to 1.0.3

This fixes ImportError when storage_aws_secret.py tries to import IMDSFetcher
from botocore.utils, which was introduced in botocore 1.13.25.
Records in flat response.records[] array with folderUid now use folder key
for decryption instead of app key.

- Add folderUid detection in core.py
- Update mock.py to support folder_uid
- Add test coverage in record_key_test.py
…ecord-key-decryption

KSM-747: Fix record key decryption for shared folder records
* KSM-628 Added GraphSync links

* Adjusted requestLinks in payload
Deduplicate records by UID before notation resolution. When a KSM
application has access to both an original record and its shortcut,
the same UID appears multiple times but should not be treated as
ambiguous.

- Add deduplication logic in both notation methods (get_notation and try_get_notation_results)
- Preserve genuine ambiguity check for different records with same title
- Add test case for duplicate UID handling in notation_test.py
- All 6 notation tests pass (5 existing + 1 new)
- Revert python_requires to >=3.6 (was >=3.9)
- Add conditional urllib3 requirements:
  - Python 3.10+: urllib3>=2.6.0 (CVE fixes)
  - Python 3.6-3.9: urllib3>=1.26.0,<1.27 (boto3 compatible)
- Add deprecation notice for Python <3.10 (removal in v17.2.0)
- Add Python 3.6, 3.7, 3.8 back to CI test matrix
- Resolves urllib3/boto3 dependency conflict on Python 3.9
@stas-schaller
Copy link
Contributor Author

stas-schaller commented Jan 15, 2026

The ansible tests(https://github.com/Keeper-Security/secrets-manager/actions/runs/21037087361/job/60487919983) failing are an issue in ansible repo and will be fixed in the next release. They are not due to an issue with this PR.

…Sync links

- Update transmission key test to validate all 18 keys (was only 1-6)
- Add GraphSync links test to verify links field structure
- Add links support to mock.Record class
- Update README to remove premature deprecation notice
- 51 tests now pass (was 50)
…on-detection

KSM-749: fix client version detection from stale .dist-info metadata
KSM-747 (record key decryption for shared folders) will be released
in a separate coordinated release across all SDKs.

Changes removed:
- Removed folder key lookup logic from core.py
- Removed folder_uid support from mock.py
- Removed record_key_test.py test file
- Removed KSM-747 entry from changelog
stas-schaller added a commit that referenced this pull request Jan 21, 2026
Revert minimum Python version from 3.9 back to 3.7 to give clients
time to migrate. Python SDK v17.1.0 is researching deprecation timeline
for EOL Python versions with migration guidance coming soon.

This aligns CLI deprecation timeline with the Python SDK v17.1.0
approach of providing advance notice before removing support.

Related: Python SDK v17.1.0 release (PR #886)
KSM-763: fix file upload/download SSL and proxy settings

Pass verify_ssl_certs and proxy_url to requests.post() in __upload_file_function and requests.get() in KeeperFile.get_file_data(). Previously these parameters were ignored, causing SSL verification errors when using proxies with verify_ssl_certs=False.

Tested in vitro with mitmproxy - both file upload and download work correctly through proxy with SSL verification disabled.
@stas-schaller
Copy link
Contributor Author

Note: CLI Test Failures

The test-cli failures are expected and will be fixed in CLI v1.3.0 release.

Root Cause: KSM-763 added verify_ssl_certs and proxy_url parameters to KeeperFile.get_file_data(), which are now passed as keyword arguments to requests.get(). The CLI test mocks in tests/secret_test.py need to be updated to accept these kwargs.

Failed Tests:

  • test_download - Mock function signature: def mock_download_get(_): needs **kwargs
  • test_notation_file - Same issue

Fix Location: CLI release branch release/tool/cli/v1.3.0

The Python SDK v17.1.0 functionality is fully validated - all 57 core SDK tests pass. The CLI test failures are isolated to test infrastructure, not actual functionality.

@stas-schaller
Copy link
Contributor Author

Update: CLI Test Fix Pushed

The CLI test failures have been fixed in CLI v1.3.0 release branch.

Commit: d991cd5 - "fix(cli): update test mocks to accept verify/proxy kwargs from KSM-763"

Changes: Updated mock_download_get functions in tests/secret_test.py to accept **kwargs for compatibility with KSM-763's new parameters.

Tests: Both test_download and test_notation_file now pass.

The CLI v1.3.0 release will include this fix and will be compatible with Python SDK v17.1.0.

Core SDK changes:
- Exclude cryptography 44.0.0 (CVE-2026-23949) via !=44.0.0 constraint
- Maintains Python 3.6 support (uses cryptography 40.x on 3.6, 46.0.3 on 3.7+)

Build/SBOM workflow changes:
- Pin wheel>=0.46.3 (CVE-2026-24049) in SBOM generation workflow
- Pin wheel>=0.46.3 in SDK and Helper publish workflows
- Ensures Manifest Cyber scans show patched versions

Both CVEs are now mitigated without breaking Python 3.6 compatibility.
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.

Python package should require urllib3>=2.6.0 to avoid vulnerable resolver outcomes

4 participants