Skip to content

feat: sb-runtime governance skill (signed decision receipts, nono-composable)#1203

Merged
imran-siddique merged 1 commit intomicrosoft:mainfrom
tomjwxf:integrations/sb-runtime-skill
Apr 19, 2026
Merged

feat: sb-runtime governance skill (signed decision receipts, nono-composable)#1203
imran-siddique merged 1 commit intomicrosoft:mainfrom
tomjwxf:integrations/sb-runtime-skill

Conversation

@tomjwxf
Copy link
Copy Markdown
Contributor

@tomjwxf tomjwxf commented Apr 19, 2026

Summary

PR 2 of the three-PR sequence discussed on #748 and #1202. Adds a drop-in governance skill under packages/agentmesh-integrations/sb-runtime-skill/ that mirrors the existing openshell-skill contract and layers Ed25519-signed decision receipts in the Veritas Acta receipt format on top.

Builds on:

What's in the shim

  • Policy contract parity with openshell-skill. Same YAML schema, same check_policy(action, context) surface, same trust-score and audit-log methods. An operator swapping openshell_agentmesh for sb_runtime_agentmesh does not need to change call sites.
  • Ed25519-signed decision receipts. Every check_policy call returns a PolicyDecision with a receipt field: a JCS-canonical, Ed25519-signed envelope that verifies offline against @veritasacta/verify with no dependency on this shim, sb-runtime, or AgentMesh.
  • Chain linkage via previousReceiptHash.
  • Policy digest pinned into every receipt as sha256:<hex> of the active canonicalized ruleset.
  • Sandbox backend recorded in the signed payload. sandbox_backend is one of sb_runtime_builtin, nono (Ring 2 composition per docs: sb-runtime integration guide (a Veritas Acta receipt format implementation) #1202), openshell (Ring 2 container composition), or none. Auditors see which layer wrapped the process because it is covered by the signature.
  • CLI (sb-runtime-governance). check-policy (with --receipts-dir for on-disk persistence), verify, trust-score, and public-key subcommands.

Tests

23 passing under pytest tests/:

  • Policy contract parity with openshell-skill (9): allow, deny, default-deny, trust, audit, load, missing, priority.
  • Receipt signing (6): receipt attached on allow and on deny (denials MUST produce a receipt too, else there is no proof the block happened), external verification via public key, tampering detection, chain linkage, sign=False opt-out.
  • Sandbox backend (4): default, nono composition, openshell composition, sandbox-backend field covered by signature.
  • Policy digest (2): determinism, rule-change detection.
  • Key loading (2): generate then from_pem round-trip preserves kid, explicit kid override.

No changes outside packages/agentmesh-integrations/sb-runtime-skill/.

Spec alignment

Notes

  • Dependencies: pyyaml>=6,<7 (same as openshell-skill) + cryptography>=41,<47 for Ed25519.
  • The worked example PR (PR 3) will consume this shim in examples/sb-runtime-governed/ and exercise both standalone and nono-composed configurations.

Cc @imran-siddique (per the three-PR sequence on #1202), @lukehinds (the nono composition path is first-class here; happy to adjust the expected flag layout or capability-file conventions if anything would align better with nono's defaults).

Adds a new AgentMesh integration under
packages/agentmesh-integrations/sb-runtime-skill/ parallel to the
existing openshell-skill. Same policy contract; adds Ed25519-signed
decision receipts in the Veritas Acta receipt format
(draft-farley-acta-signed-receipts-02).

Three supported deployment shapes, all recording the sandbox layer
in the signed payload for auditor visibility:

- sandbox_backend=sb_runtime_builtin, ring=3: one binary owns
  Cedar + Landlock/seccomp + receipts (default).
- sandbox_backend=nono, ring=2: nono wraps the agent process and
  owns the sandbox; this skill contributes only Cedar + receipts.
  Recommended Linux composition per docs/integrations/sb-runtime.md.
- sandbox_backend=openshell, ring=2: OpenShell owns the container
  boundary; this skill contributes Cedar + receipts.

Receipts verify offline against @veritasacta/verify without
dependency on this skill, sb-runtime, or AgentMesh. Policy digest
(sha256 of the canonicalized ruleset) is pinned into every receipt;
chain linkage via previousReceiptHash across successive decisions.

Tests: 23 passing, covering policy contract parity with
openshell-skill (9), receipt signing / verification / tampering (6),
sandbox-backend recording (4), policy digest determinism (2), and
signer key loading (2).

Part of PR microsoft#1202 (integration doc) + this shim + a forthcoming
worked example.
@github-actions
Copy link
Copy Markdown

Welcome to the Agent Governance Toolkit! Thanks for your first pull request.
Please ensure tests pass, code follows style (ruff check), and you have signed the CLA.
See our Contributing Guide.

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests size/XL Extra large PR (500+ lines) labels Apr 19, 2026
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 AI Agent: code-reviewer

Review Summary

This PR introduces the sb-runtime-skill package, a governance skill for policy evaluation and Ed25519-signed decision receipts in the Veritas Acta format. The implementation appears well-aligned with the stated goals and specifications, including policy contract parity with openshell-skill, cryptographic receipt signing, sandbox backend recording, and chain linkage. However, several critical security issues, potential breaking changes, and areas for improvement have been identified.


🔴 CRITICAL: Security Issues

  1. Receipt Signing Vulnerability:

    • The sign_receipt function does not validate the structure of the payload before signing. This could allow an attacker to inject malicious or malformed data into the receipt payload, which would then be signed and appear valid to verifiers.
    • Recommendation: Implement strict validation of the payload structure before signing. Ensure all required fields are present and conform to expected types.
  2. Key Management:

    • The Signer.generate() method creates ephemeral keys but does not provide a secure mechanism for long-term key storage or rotation. This could lead to compromised operator keys being used indefinitely.
    • Recommendation: Introduce key rotation and secure storage mechanisms, such as integration with a hardware security module (HSM) or a secure key management service.
  3. Sandbox Escape Risk:

    • The SandboxBackend.NONE option allows execution without any sandboxing. While this is marked as suitable for test harnesses, it could be misused in production environments, exposing the system to potential security risks.
    • Recommendation: Add explicit warnings in the documentation and code comments about the risks of using SandboxBackend.NONE in production. Consider adding runtime checks to prevent accidental use.
  4. Receipt Verification:

    • The verify_receipt function returns False for invalid signatures but does not provide detailed error messages for debugging or auditing purposes. This could hinder incident response and forensic analysis.
    • Recommendation: Log detailed error messages when verification fails, including the reason (e.g., invalid signature, malformed envelope).

🟡 WARNING: Potential Breaking Changes

  1. Python Version Requirement:

    • The package requires Python >=3.10. This may break compatibility for users on older Python versions (e.g., 3.9), which are still supported by the repository.
    • Recommendation: Consider lowering the requirement to >=3.9 or explicitly document the rationale for requiring Python 3.10.
  2. Policy Directory Loading:

    • The load_policies method clears existing rules before loading new ones. This could lead to unexpected behavior if the method is called multiple times during runtime.
    • Recommendation: Add a parameter to control whether existing rules should be cleared or merged with new ones.

💡 Suggestions for Improvement

  1. Thread Safety:

    • The GovernanceSkill class maintains mutable state (e.g., _previous_receipt_hash, _trust_scores, _audit_log) that could lead to race conditions in concurrent environments.
    • Recommendation: Use thread-safe data structures (e.g., threading.Lock or concurrent.futures) to protect shared state.
  2. Type Safety:

    • While the code uses type hints, there is no enforcement of schema validation for the PolicyDecision or receipt payloads.
    • Recommendation: Use Pydantic models for strict validation of PolicyDecision and receipt payloads.
  3. CLI Usability:

    • The CLI does not provide clear error messages for invalid input (e.g., malformed JSON in --context).
    • Recommendation: Add input validation and user-friendly error messages for CLI arguments.
  4. Documentation:

    • The README does not explicitly warn about the risks of using SandboxBackend.NONE in production.
    • Recommendation: Add a dedicated "Security Considerations" section to the README.
  5. Backward Compatibility:

    • The sb-runtime-skill package introduces new functionality but does not provide migration guidance for users transitioning from openshell-skill.
    • Recommendation: Include a migration guide in the documentation.
  6. Testing Coverage:

    • While the PR includes 23 tests, there is no mention of edge cases, such as malformed policies, invalid receipt payloads, or corrupted keys.
    • Recommendation: Add tests for edge cases and failure scenarios.

Conclusion

This PR introduces valuable functionality for policy evaluation and signed decision receipts, but it has several critical security vulnerabilities and potential breaking changes that need to be addressed before merging. The recommendations provided should be implemented to ensure the robustness, security, and backward compatibility of the sb-runtime-skill package.

@github-actions
Copy link
Copy Markdown

🤖 AI Agent: security-scanner — Security Findings for Pull Request: feat: sb-runtime governance skill

Security Findings for Pull Request: feat: sb-runtime governance skill

  1. Prompt Injection Defense Bypass: 🔴 CRITICAL

    • Attack Vector: The check_policy method accepts an action parameter that is directly used in policy evaluation. If the policies do not adequately sanitize or validate this input, an attacker could craft a malicious action string that could manipulate the policy evaluation process.
    • Suggested Fix: Implement strict validation and sanitization of the action input. Ensure that only predefined actions are allowed and that they conform to expected formats.
  2. Policy Engine Circumvention: 🟠 HIGH

    • Attack Vector: The sandbox_backend parameter allows for different execution contexts. If the policies are not enforced uniformly across different backends, an attacker could exploit a weaker backend to bypass security checks.
    • Suggested Fix: Ensure that all sandbox backends enforce the same policy checks and that there is no variation in how policies are applied based on the backend used.
  3. Trust Chain Weaknesses: 🟡 MEDIUM

    • Attack Vector: The implementation uses Ed25519 signatures for receipts but does not specify how public keys are managed or verified. If an attacker can substitute a public key, they could forge valid receipts.
    • Suggested Fix: Implement a robust public key management system that includes key rotation, revocation, and validation mechanisms to ensure that only trusted keys are used for verification.
  4. Credential Exposure: 🔴 CRITICAL

    • Attack Vector: The CLI commands allow for the output of sensitive information, such as the operator's private key. If this information is logged or mishandled, it could lead to credential exposure.
    • Suggested Fix: Ensure that sensitive information is never logged or printed in a way that could be exposed. Use secure methods for handling and storing sensitive data.
  5. Sandbox Escape: 🟡 MEDIUM

    • Attack Vector: The use of different sandbox backends (e.g., nono, openshell) introduces potential vulnerabilities if any of these backends have known escape routes. If an attacker can exploit a vulnerability in the sandbox, they could escape and execute arbitrary code.
    • Suggested Fix: Regularly audit and update the sandbox implementations to ensure they are secure. Implement additional layers of security to monitor and restrict actions within the sandbox.
  6. Deserialization Attacks: 🔵 LOW

    • Attack Vector: The use of YAML for policy loading could be susceptible to deserialization attacks if untrusted input is processed. Malicious YAML could lead to arbitrary code execution.
    • Suggested Fix: Use safe loading methods (e.g., yaml.safe_load()) and validate the structure of the loaded data to prevent malicious payloads.
  7. Race Conditions: 🟡 MEDIUM

    • Attack Vector: The check_policy method does not appear to handle concurrent access to shared resources (e.g., policy rules). This could lead to race conditions where policies are modified while being evaluated.
    • Suggested Fix: Implement locking mechanisms or use atomic operations when accessing shared resources to prevent race conditions.
  8. Supply Chain Weaknesses: 🟠 HIGH

    • Attack Vector: The dependencies specified (e.g., pyyaml, cryptography) could be vulnerable to supply chain attacks, such as typosquatting or dependency confusion.
    • Suggested Fix: Use a dependency management tool that verifies the integrity of packages (e.g., using hash checks) and consider pinning dependencies to specific versions to avoid unintentional upgrades to malicious versions.

Summary

This pull request introduces significant functionality that enhances the governance capabilities of the toolkit. However, it also introduces several critical security concerns that must be addressed to ensure the integrity and security of the entire system. Immediate attention should be given to the critical findings, particularly around input validation and credential exposure, to mitigate potential risks to downstream users.

Copy link
Copy Markdown
Member

@imran-siddique imran-siddique left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work — correctly placed under \packages/agentmesh-integrations/\ as an extension (not core). The skill follows the same contract as openshell-skill, receipts implementation looks solid, and tests are included. Merging.

@imran-siddique imran-siddique merged commit de39284 into microsoft:main Apr 19, 2026
10 of 11 checks passed
tomjwxf pushed a commit to tomjwxf/agent-governance-toolkit that referenced this pull request Apr 20, 2026
…pt portability)

PR 3 in the three-PR sequence proposed on microsoft#748 (after microsoft#1202 integration
doc and microsoft#1203 provider shim, both merged). Demonstrates the
architectural claim of the sb-runtime integration: a single Cedar
policy produces semantically-equivalent signed receipts regardless of
which sandbox layer wraps the agent process, and the sandbox_backend
field is covered by the Ed25519 signature (not sidecar metadata).

The demo runs six governed actions (three allowed, three denied)
through three sandbox-backend configurations using the same Cedar
policy and the same operator key:

  1. standalone   sandbox_backend=sb_runtime_builtin  ring=3
  2. nono         sandbox_backend=nono                ring=2
  3. openshell    sandbox_backend=openshell           ring=2

Then:

  - Cross-verifies all 18 receipts against the single operator public
    key (zero dependency on the sb_runtime_agentmesh skill at verify
    time; matches what @veritasacta/verify would do offline).
  - Demonstrates tamper-evidence by flipping sandbox_backend on a
    receipt and confirming verification fails (the field is inside the
    signature scope).
  - Confirms chain linkage: receipt[1].previousReceiptHash equals
    sha256(canonical(receipt[0])).
  - Writes the receipts + operator public key to disk under
    examples/sb-runtime-governed/receipts/ (gitignored) so the output
    is inspectable and re-verifiable with external tooling.

Files:
  - README.md:         walkthrough with expected output
  - getting_started.py: ~280-line demo, three scenarios + verification
  - policies/sandbox-policy.yaml: shared across all three scenarios
  - .gitignore:        excludes receipts/ and __pycache__

No changes outside examples/sb-runtime-governed/. Depends on:
  - pyyaml>=6,<7       (same as openshell-skill)
  - cryptography>=41   (for Ed25519 + JCS canonicalization)

Both are declared in the sb-runtime-skill pyproject.toml (microsoft#1203).

Cc @imran-siddique (closing the three-PR sequence as committed),
@lukehinds (the nono scenario uses sandbox_backend="nono" matching
the composition pattern documented in microsoft#1202; happy to match nono's
native CLI flag conventions when the nono Python library is wired
in for actual runtime enforcement).
imran-siddique pushed a commit that referenced this pull request Apr 22, 2026
… 3 of 3 from #748) (#1205)

* examples: add sb-runtime-governed worked example (multi-backend receipt portability)

PR 3 in the three-PR sequence proposed on #748 (after #1202 integration
doc and #1203 provider shim, both merged). Demonstrates the
architectural claim of the sb-runtime integration: a single Cedar
policy produces semantically-equivalent signed receipts regardless of
which sandbox layer wraps the agent process, and the sandbox_backend
field is covered by the Ed25519 signature (not sidecar metadata).

The demo runs six governed actions (three allowed, three denied)
through three sandbox-backend configurations using the same Cedar
policy and the same operator key:

  1. standalone   sandbox_backend=sb_runtime_builtin  ring=3
  2. nono         sandbox_backend=nono                ring=2
  3. openshell    sandbox_backend=openshell           ring=2

Then:

  - Cross-verifies all 18 receipts against the single operator public
    key (zero dependency on the sb_runtime_agentmesh skill at verify
    time; matches what @veritasacta/verify would do offline).
  - Demonstrates tamper-evidence by flipping sandbox_backend on a
    receipt and confirming verification fails (the field is inside the
    signature scope).
  - Confirms chain linkage: receipt[1].previousReceiptHash equals
    sha256(canonical(receipt[0])).
  - Writes the receipts + operator public key to disk under
    examples/sb-runtime-governed/receipts/ (gitignored) so the output
    is inspectable and re-verifiable with external tooling.

Files:
  - README.md:         walkthrough with expected output
  - getting_started.py: ~280-line demo, three scenarios + verification
  - policies/sandbox-policy.yaml: shared across all three scenarios
  - .gitignore:        excludes receipts/ and __pycache__

No changes outside examples/sb-runtime-governed/. Depends on:
  - pyyaml>=6,<7       (same as openshell-skill)
  - cryptography>=41   (for Ed25519 + JCS canonicalization)

Both are declared in the sb-runtime-skill pyproject.toml (#1203).

Cc @imran-siddique (closing the three-PR sequence as committed),
@lukehinds (the nono scenario uses sandbox_backend="nono" matching
the composition pattern documented in #1202; happy to match nono's
native CLI flag conventions when the nono Python library is wired
in for actual runtime enforcement).

* fix: use Microsoft copyright header per imran-siddique review

Per @imran-siddique in #1205, swap the Tom Farley (ScopeBlind) header
for the repo's standard Microsoft Corporation / MIT License header.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: tommylauren <tfarley@utexas.edu>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
imran-siddique pushed a commit to imran-siddique/agent-governance-toolkit that referenced this pull request May 4, 2026
… 3 of 3 from microsoft#748) (microsoft#1205)

* examples: add sb-runtime-governed worked example (multi-backend receipt portability)

PR 3 in the three-PR sequence proposed on microsoft#748 (after microsoft#1202 integration
doc and microsoft#1203 provider shim, both merged). Demonstrates the
architectural claim of the sb-runtime integration: a single Cedar
policy produces semantically-equivalent signed receipts regardless of
which sandbox layer wraps the agent process, and the sandbox_backend
field is covered by the Ed25519 signature (not sidecar metadata).

The demo runs six governed actions (three allowed, three denied)
through three sandbox-backend configurations using the same Cedar
policy and the same operator key:

  1. standalone   sandbox_backend=sb_runtime_builtin  ring=3
  2. nono         sandbox_backend=nono                ring=2
  3. openshell    sandbox_backend=openshell           ring=2

Then:

  - Cross-verifies all 18 receipts against the single operator public
    key (zero dependency on the sb_runtime_agentmesh skill at verify
    time; matches what @veritasacta/verify would do offline).
  - Demonstrates tamper-evidence by flipping sandbox_backend on a
    receipt and confirming verification fails (the field is inside the
    signature scope).
  - Confirms chain linkage: receipt[1].previousReceiptHash equals
    sha256(canonical(receipt[0])).
  - Writes the receipts + operator public key to disk under
    examples/sb-runtime-governed/receipts/ (gitignored) so the output
    is inspectable and re-verifiable with external tooling.

Files:
  - README.md:         walkthrough with expected output
  - getting_started.py: ~280-line demo, three scenarios + verification
  - policies/sandbox-policy.yaml: shared across all three scenarios
  - .gitignore:        excludes receipts/ and __pycache__

No changes outside examples/sb-runtime-governed/. Depends on:
  - pyyaml>=6,<7       (same as openshell-skill)
  - cryptography>=41   (for Ed25519 + JCS canonicalization)

Both are declared in the sb-runtime-skill pyproject.toml (microsoft#1203).

Cc @imran-siddique (closing the three-PR sequence as committed),
@lukehinds (the nono scenario uses sandbox_backend="nono" matching
the composition pattern documented in microsoft#1202; happy to match nono's
native CLI flag conventions when the nono Python library is wired
in for actual runtime enforcement).

* fix: use Microsoft copyright header per imran-siddique review

Per @imran-siddique in microsoft#1205, swap the Tom Farley (ScopeBlind) header
for the repo's standard Microsoft Corporation / MIT License header.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: tommylauren <tfarley@utexas.edu>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/XL Extra large PR (500+ lines) tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants