Files
hermes-agent/tests/skills/test_google_workspace_setup.py
T
Eugeniusz Gilewski 64dd865912 fix(deps): repair Google transitive security floors (#72108)
Google API and authentication packages permit vulnerable httplib2 and pyasn1
transitives, while the Workspace and Google Chat runtime installers previously
treated any importable version as sufficient. Existing environments could
therefore remain vulnerable after the project dependency pins were repaired.

Carry the fixed versions through the Google and Vertex extras, lazy feature
requirements, lockfile, and both runtime installers. Route the documented
Google Chat installation path through its maintained secure requirements
instead of an unconstrained direct pip command.

Detect stale distributions, install only unsatisfied requirements, and verify
the result before continuing. Behavioral tests cover those repair invariants
without freezing manifests, lockfiles, or complete package sets.

Related #72108
Extracted from #72840
Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>
2026-07-31 23:18:38 -07:00

91 lines
2.2 KiB
Python

"""Security-floor tests for the Google Workspace runtime installer."""
from __future__ import annotations
import importlib.util
from importlib.metadata import PackageNotFoundError
from pathlib import Path
import pytest
SETUP_PATH = (
Path(__file__).resolve().parents[2]
/ "skills/productivity/google-workspace/scripts/setup.py"
)
@pytest.fixture()
def setup_module():
spec = importlib.util.spec_from_file_location(
"test_google_workspace_setup_module",
SETUP_PATH,
)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def test_stale_google_transitives_are_reported_missing(setup_module, monkeypatch):
installed = {
"google-api-python-client": "2.194.0",
"google-auth": "2.55.0",
"google-auth-oauthlib": "1.3.1",
"google-auth-httplib2": "0.3.1",
"httplib2": "0.31.2",
"pyasn1": "0.6.3",
}
def fake_version(name):
try:
return installed[name]
except KeyError:
raise PackageNotFoundError(name) from None
monkeypatch.setattr(setup_module, "_distribution_version", fake_version)
assert setup_module._missing_required_packages() == [
"google-auth==2.55.1",
"httplib2==0.32.0",
"pyasn1==0.6.4",
]
def test_installer_repairs_stale_transitives(setup_module, monkeypatch):
states = iter(
[
[
"google-auth==2.55.1",
"httplib2==0.32.0",
"pyasn1==0.6.4",
],
[],
]
)
monkeypatch.setattr(
setup_module,
"_missing_required_packages",
lambda: next(states),
)
calls = []
monkeypatch.setattr(
setup_module.subprocess,
"check_call",
lambda argv, **kwargs: calls.append(argv),
)
assert setup_module.install_deps() is True
assert calls == [
[
setup_module.sys.executable,
"-m",
"pip",
"install",
"--quiet",
"google-auth==2.55.1",
"httplib2==0.32.0",
"pyasn1==0.6.4",
]
]