Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
9bd6672
docs: add testing guide for external testers and customers
imran-siddique Mar 20, 2026
b62e0c5
docs: add regulatory alignment table and Purview positioning to README
imran-siddique Mar 21, 2026
3ab4a65
Merge branch 'main' of https://github.com/microsoft/agent-governance-…
imran-siddique Mar 21, 2026
33df318
fix(ci): restore read-all at workflow level for Scorecard verification
imran-siddique Mar 21, 2026
f7d49a9
docs: add comprehensive docstrings to mcp_adapter.py classes (#324)
parsa-faraji Mar 21, 2026
baeed60
ci: add markdown link checker workflow (#323)
mvanhorn Mar 21, 2026
8ee3c81
feat: add policy evaluation heatmap to SRE dashboard (#309) (#326)
zeel2104 Mar 21, 2026
057b908
fix: remove unregistered PyPI packages from notebooks and requirement…
x4v13r64 Mar 21, 2026
7a3fdb9
fix(security): complete dependency confusion fix — replace all pip in…
imran-siddique Mar 21, 2026
58bc4fd
docs: update framework star counts to current values
imran-siddique Mar 21, 2026
96b2046
Merge branch 'main' of https://github.com/microsoft/agent-governance-…
imran-siddique Mar 22, 2026
3ac1f73
Merge branch 'main' of https://github.com/microsoft/agent-governance-…
imran-siddique Mar 22, 2026
d0681ff
Merge branch 'main' of https://github.com/microsoft/agent-governance-…
imran-siddique Mar 23, 2026
18aa288
feat(security): add dependency confusion pre-commit hook + weekly aud…
imran-siddique Mar 23, 2026
44a2b80
fix(security): proactive audit — dependency confusion + MD5→SHA-256 (…
imran-siddique Mar 23, 2026
9fad202
fix(security): replace unregistered package names + MD5→SHA-256
imran-siddique Mar 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 112 additions & 0 deletions .github/workflows/weekly-security-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: Weekly Security Audit

on:
schedule:
- cron: "0 8 * * 1" # Monday 8:00 UTC
workflow_dispatch:

permissions:
contents: read
issues: write

jobs:
dependency-confusion-check:
name: Dependency Confusion Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.11"

- name: Scan for unregistered pip install targets
id: dep-check
run: |
# Find all pip install commands and check package names
python scripts/check_dependency_confusion.py \
$(find . -name "*.md" -o -name "*.py" -o -name "*.ts" -o -name "*.txt" -o -name "*.yaml" -o -name "*.svg" -o -name "*.ipynb" \
| grep -v node_modules | grep -v .git | grep -v __pycache__ | grep -v .venv) \
> dep-confusion-report.txt 2>&1 || true
if [ -s dep-confusion-report.txt ]; then
echo "has-findings=true" >> "$GITHUB_OUTPUT"
echo "### ⚠️ Dependency Confusion Findings" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
cat dep-confusion-report.txt >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
else
echo "has-findings=false" >> "$GITHUB_OUTPUT"
echo "### ✅ No dependency confusion findings" >> "$GITHUB_STEP_SUMMARY"
fi

security-skills-scan:
name: Security Skills Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: "3.11"

- name: Install dependencies
run: pip install pyyaml

- name: Run security skills scan
continue-on-error: true
run: |
python scripts/security_scan.py packages/ \
--exclude-tests \
--min-severity high \
--format text | tee security-report.txt

- name: Generate JSON report
if: always()
run: |
python scripts/security_scan.py packages/ \
--exclude-tests \
--format json > weekly-security-report.json || true

- name: Upload reports
if: always()
uses: actions/upload-artifact@ea165f8d65b6db9a6b7e75b195db6a6b2be22da8 # v4.6.2
with:
name: weekly-security-audit
path: |
weekly-security-report.json
dep-confusion-report.txt
retention-days: 90

weak-crypto-check:
name: Weak Cryptography Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Check for MD5/SHA1 in non-test code
run: |
echo "### Weak Cryptography Check" >> "$GITHUB_STEP_SUMMARY"
FINDINGS=$(grep -rn "hashlib\.md5\|hashlib\.sha1" --include="*.py" packages/ \
| grep -v "test_" | grep -v "text_tool" | grep -v "security_skills" \
| grep -v "example" | grep -v "benchmark" | grep -v "red_team" || true)
if [ -n "$FINDINGS" ]; then
echo "⚠️ MD5/SHA1 found in production code:" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
echo "$FINDINGS" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
else
echo "✅ No weak cryptography in production code" >> "$GITHUB_STEP_SUMMARY"
fi

- name: Check for pickle in non-test code
run: |
FINDINGS=$(grep -rn "pickle\.load" --include="*.py" packages/ \
| grep -v "test_" | grep -v "security_skills" | grep -v "# " || true)
if [ -n "$FINDINGS" ]; then
echo "⚠️ pickle usage found:" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
echo "$FINDINGS" >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
else
echo "✅ No pickle deserialization in production code" >> "$GITHUB_STEP_SUMMARY"
fi
2 changes: 1 addition & 1 deletion docs/integrations/openshell.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Install the toolkit as an [OpenClaw skill](../packages/agentmesh-integrations/op

```bash
# Inside the sandbox
pip install agentmesh
pip install agentmesh-platform

# Use the skill scripts
scripts/check-policy.sh --action "web_search" --tokens 1500 --policy policy.yaml
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The stack consists of four components:
| Component | Role | Install |
|---|---|---|
| **Agent OS** | Governance kernel — policy, sandbox, memory, MCP security | `pip install agent-os-kernel` |
| **AgentMesh** | Identity & trust — DIDs, SPIFFE, handshake, reputation | `pip install agentmesh` |
| **AgentMesh** | Identity & trust — DIDs, SPIFFE, handshake, reputation | `pip install agentmesh-platform` |
| **Agent SRE** | Observability — SLOs, anomaly detection, chaos, OpenTelemetry | `pip install agent-sre` |
| **Agent Runtime** | Runtime control — kill switch, execution rings, saga rollback | `pip install agent-runtime` |

Expand Down
2 changes: 1 addition & 1 deletion packages/agent-mesh/src/agentmesh/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ def register(agent_dir: str, name: str = None):
try:
from agentmesh.identity import AgentIdentity
except ImportError:
console.print("[red]Error: agentmesh is not installed. Run: pip install agentmesh[/red]")
console.print("[red]Error: agentmesh is not installed. Run: pip install agentmesh-platform[/red]")
return
identity = AgentIdentity.create(agent_name)

Expand Down
4 changes: 2 additions & 2 deletions packages/agent-mesh/src/agentmesh/transport/grpc_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
Requires the ``grpcio`` and ``grpcio-tools`` libraries::
pip install agentmesh[grpc]
pip install agentmesh-platform[grpc]
"""

from __future__ import annotations
Expand Down Expand Up @@ -41,7 +41,7 @@ def _require_grpc() -> None:
if not HAS_GRPC:
raise ImportError(
"The 'grpcio' package is required for gRPC transport. "
"Install it with: pip install agentmesh[grpc]"
"Install it with: pip install agentmesh-platform[grpc]"
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2427,11 +2427,11 @@ def _compute_version(self, module_name: str) -> str:
module = sys.modules.get(module_name)
if module and hasattr(module, '__file__') and module.__file__:
with open(module.__file__, 'rb') as f:
return hashlib.md5(f.read()).hexdigest()
return hashlib.sha256(f.read()).hexdigest()
except Exception as e:
logger.warning(f"Could not compute version for {module_name}: {e}")

return hashlib.md5(module_name.encode()).hexdigest()
return hashlib.sha256(module_name.encode()).hexdigest()

async def check_for_changes(self, agent_id: str) -> bool:
"""Check if an agent's code has changed"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def from_text(text: str) -> 'EmbeddingVector':
"""Create a simplified embedding from text"""
# In production, would call actual embedding model
# This is a simplified hash-based approach for demonstration
vector_hash = hashlib.md5(text.lower().encode()).hexdigest()
vector_hash = hashlib.sha256(text.lower().encode()).hexdigest()
return EmbeddingVector(text=text, vector_hash=vector_hash)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ async def _verify_claim(self, claim: str, context: str, threshold: float) -> dic
# responses = [await call_model(m, claim) for m in models]

# For demo: Generate deterministic mock responses
claim_hash = int(hashlib.md5(claim.encode()).hexdigest()[:8], 16)
claim_hash = int(hashlib.sha256(claim.encode()).hexdigest()[:8], 16)

# Simulate model responses (in production, actual API calls)
responses = []
Expand Down
2 changes: 1 addition & 1 deletion packages/agent-os/modules/observability/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ This package provides metrics, tracing, and dashboards for monitoring Agent OS d
### Install Package

```bash
pip install agent-os-observability
pip install agent-os-kernel[observability]
```

### Basic Usage
Expand Down
2 changes: 1 addition & 1 deletion packages/agentmesh-integrations/openclaw-skill/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ score trust, and maintain tamper-evident audit logs — all from your agent's co
Install the AgentMesh governance CLI:

```bash
pip install agentmesh-governance
pip install agent-governance-toolkit
```

> If `agentmesh-governance` is not yet on PyPI, install directly from source:
Expand Down
131 changes: 131 additions & 0 deletions scripts/check_dependency_confusion.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#!/usr/bin/env python3
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
"""Pre-commit hook: detect unregistered PyPI package names in pip install commands.

Scans staged files for `pip install <name>` where <name> is not a known
registered package. Prevents dependency confusion attacks.

Usage:
# Install as pre-commit hook
cp scripts/check_dependency_confusion.py .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit

# Or run manually
python scripts/check_dependency_confusion.py [files...]
"""

import re
import subprocess
import sys

# Known registered PyPI package names for this project
REGISTERED_PACKAGES = {
# Core packages (on PyPI)
"agent-os-kernel",
"agentmesh-platform",
"agent-hypervisor",
"agent-runtime",
"agent-sre",
"agent-governance-toolkit",
"agent-lightning",
"agent-marketplace",
# Common dependencies
"pydantic", "pyyaml", "cryptography", "pynacl", "httpx", "aiohttp",
"fastapi", "uvicorn", "structlog", "click", "rich", "numpy", "scipy",
"pytest", "pytest-asyncio", "pytest-cov", "ruff", "mypy", "build",
"openai", "anthropic", "langchain", "langchain-core", "crewai",
"redis", "sqlalchemy", "asyncpg", "chromadb", "pinecone-client",
"sentence-transformers", "prometheus-client", "opentelemetry-api",
"opentelemetry-sdk", "fhir.resources", "hl7apy", "zenpy", "freshdesk",
"google-adk", "safety", "jupyter", "vitest", "tsup", "typescript",
# With extras (base name is what matters)
}

# Patterns that are always safe
SAFE_PATTERNS = {
"-e", "--editable", "-r", "--requirement", "--upgrade", "--no-cache-dir",
"--quiet", "--require-hashes", "--hash", ".", "..", "../..",
}

PIP_INSTALL_RE = re.compile(
r'pip\s+install\s+(.+?)(?:\s*\\?\s*$|(?=\s*&&|\s*\||\s*;|\s*#))',
re.MULTILINE,
)


def extract_package_names(install_args: str) -> list[str]:
"""Extract package names from a pip install argument string."""
packages = []
for token in install_args.split():
# Skip flags
if token.startswith("-") or token in SAFE_PATTERNS:
continue
if token.startswith((".", "/", "\\", "http", "git+")):
continue
# Strip extras: package[extra] -> package
base = re.sub(r'\[.*\]', '', token)
# Strip version specifiers: package>=1.0 -> package
base = re.split(r'[><=!~]', base)[0]
# Strip markdown/quote artifacts
base = base.strip('`"\'(){}')
if base and base not in SAFE_PATTERNS:
packages.append(base)
return packages


def check_file(filepath: str) -> list[str]:
"""Check a file for potentially unregistered pip install targets."""
findings = []
try:
with open(filepath, encoding="utf-8", errors="ignore") as f:
content = f.read()
except (OSError, UnicodeDecodeError):
return findings

for match in PIP_INSTALL_RE.finditer(content):
line_num = content[:match.start()].count("\n") + 1
packages = extract_package_names(match.group(1))
for pkg in packages:
if pkg.lower() not in {p.lower() for p in REGISTERED_PACKAGES}:
findings.append(
f" {filepath}:{line_num}: "
f"'{pkg}' may not be registered on PyPI"
)
return findings


def main() -> int:
# Get files to check
if len(sys.argv) > 1:
files = sys.argv[1:]
else:
# Pre-commit mode: check staged files
result = subprocess.run(
["git", "diff", "--cached", "--name-only", "--diff-filter=ACM"],
capture_output=True, text=True,
)
files = [
f for f in result.stdout.strip().split("\n")
if f.endswith((".md", ".py", ".ts", ".txt", ".yaml", ".yml", ".ipynb", ".svg"))
]

all_findings = []
for f in files:
all_findings.extend(check_file(f))

if all_findings:
print("⚠️ Potential dependency confusion detected:")
print()
for finding in all_findings:
print(finding)
print()
print("If the package IS registered on PyPI, add it to REGISTERED_PACKAGES")
print("in scripts/check_dependency_confusion.py")
return 1

return 0


if __name__ == "__main__":
sys.exit(main())
Loading