Skip to content

feat(dotnet): credential injection and offload (#2535)#2574

Closed
Ricky-G wants to merge 3 commits into
mainfrom
feat/cred-vault-dotnet
Closed

feat(dotnet): credential injection and offload (#2535)#2574
Ricky-G wants to merge 3 commits into
mainfrom
feat/cred-vault-dotnet

Conversation

@Ricky-G
Copy link
Copy Markdown
Contributor

@Ricky-G Ricky-G commented May 25, 2026

Summary

.NET port of the credential vault primitive landed for Python in #2534. Part of #2535.

Agents reference secrets via opaque {{cred:NAME}} placeholders only; resolved values stay inside the trust boundary. Library-only — agt cred remains the canonical CLI.

Design parity with the Python reference

Property .NET surface
Opaque handles, agents never see values CredentialHandle
Encrypted at-rest CredentialVault — AES-256-GCM via System.Security.Cryptography.AesGcm
Per-DID + per-action-class scoping CredentialProfile
Workflow policy runs before vault read InjectionOptions.PolicyCheck
Allowlist-gated placeholders (MCP untrusted) InjectionOptions.AllowedHandles
Deterministic deny DenyReceipt
Audit events without values VaultAuditEvent, CredentialAudit.Digest
Rotation preserves handle name CredentialVault.Rotate
HTTP / MCP / env injection surfaces InjectHeaders / InjectToolArgs / InjectEnv

Changes

File What changed
agent-governance-dotnet/src/AgentGovernance/Security/CredentialVault.cs New module: vault, injector, profile, handle, deny receipt, audit digest.
agent-governance-dotnet/tests/AgentGovernance.Tests/CredentialVaultTests.cs 27 xUnit cases.

Testing

  • dotnet build AgentGovernance.sln — clean
  • dotnet test --filter "FullyQualifiedName~Credential" — 27 passed

Wire format

AES-256-GCM with a 12-byte random nonce prefixed to the ciphertext (16-byte tag appended). Not currently interoperable with the Python SDK's Fernet format — cross-language interop spec is the remaining sub-task on #2535.

References

@github-actions github-actions Bot added the tests label May 25, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 25, 2026

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 25, 2026

🤖 AI Agent: security-scanner — View details

No security issues found.

@github-actions github-actions Bot added the size/XL Extra large PR (500+ lines) label May 25, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 25, 2026

🤖 AI Agent: test-generator — `agent-governance-dotnet/src/AgentGovernance/Security/CredentialVault.cs`

agent-governance-dotnet/src/AgentGovernance/Security/CredentialVault.cs

  • Test_Put_InvalidName -- Validate that Put method throws an exception for invalid credential names.
  • Test_Rotate_NonExistentCredential -- Ensure Rotate method throws an exception when attempting to rotate a non-existent credential.
  • Test_Delete_NonExistentCredential -- Verify Delete method returns false when trying to delete a non-existent credential.
  • Test_ResolveInternal_DenyAccess -- Test ResolveInternal for scenarios where access is denied due to missing or mismatched profiles or credentials.
  • Test_ResolveInternal_AuditEvent -- Ensure ResolveInternal correctly logs audit events for both allowed and denied resolutions.

agent-governance-dotnet/tests/AgentGovernance.Tests/CredentialVaultTests.cs

  • Test_EncryptedPersistence -- Validate that credentials are correctly encrypted and decrypted during persistence operations.
  • Test_GenerateKey_Length -- Ensure GenerateKey produces a 32-byte key as expected.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 25, 2026

🤖 AI Agent: breaking-change-detector — API Compatibility

API Compatibility

Severity Change Impact
High CredentialVault.Rotate throws KeyNotFoundException for unknown credential names. Code relying on silent failure or different exception types for non-existent credentials will break.
High CredentialVault persistence format is not interoperable with Python SDK's Fernet format. Cross-language compatibility is broken; users relying on interoperability between .NET and Python SDKs will encounter issues.
Medium CredentialVault.Put enforces stricter validation on credential names (regex [A-Za-z0-9_.\-]{1,128}). Code using credential names that don't match the new regex will fail.
Medium CredentialVault requires a 32-byte encryption key for persistence. Existing integrations using different key lengths will break.
Medium CredentialVault.Delete returns a boolean instead of throwing an exception for non-existent credentials. Code expecting exceptions for missing credentials will need adjustment.
Medium CredentialVault.CheckAccess behavior changes: now explicitly returns false for missing profiles or unbound handles. Code relying on implicit behavior may need updates.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 25, 2026

🤖 AI Agent: code-reviewer — Action Items:

TL;DR: 0 blockers, 1 warning. Solid implementation with minor interoperability concern.

# Sev Issue Where
1 Warn Lack of cross-language interoperability CredentialVault.cs: AES-256-GCM format differs from Python's Fernet.

Action Items:

  • None.

Warnings:

# Issue Where Follow-up
1 Lack of cross-language interoperability CredentialVault.cs: AES-256-GCM format differs from Python's Fernet. Fine as follow-up PR.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 25, 2026

🤖 AI Agent: docs-sync-checker — Docs Sync

Docs Sync

  • CredentialVault and related classes in CredentialVault.cs -- missing docstrings for several public methods and properties.
  • README.md -- no mention of the new .NET credential vault feature.
  • CHANGELOG.md -- missing entry for the addition of the .NET credential vault feature.

Please address these issues to ensure documentation is in sync.

@github-actions
Copy link
Copy Markdown

🟡 Contributor Check: MEDIUM

Check Result
Profile MEDIUM
Credential NONE
Overall MEDIUM

Automated check by AGT Contributor Check.

@github-actions github-actions Bot added the needs-review:MEDIUM Contributor check flagged MEDIUM risk label May 25, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 25, 2026

PR Review Summary

Check Status Details
🔍 Code Review ⚠️ Warning See details
🛡️ Security Scan ✅ Passed No issues found
🔄 Breaking Changes ✅ Completed Analysis complete
📝 Docs Sync ✅ Passed No issues found
🧪 Test Coverage ✅ Completed Analysis complete

Verdict: ⚠️ Ready for human review

…2535)

Port the Python credential vault primitive (#2481 / #2534) to the .NET SDK with full API parity. Library-only; agt cred remains the canonical CLI.

Surfaces in AgentGovernance.Security namespace:

- CredentialVault, CredentialInjector, CredentialProfile, CredentialHandle, DenyReceipt, VaultAuditEvent, CredentialAudit.Digest.

Security properties match the Python reference: opaque handles, action-class scoping, workflow policy runs before vault read, allowlist-gated placeholders (MCP metadata untrusted), deterministic DenyReceipt, value-free audit events, rotation preserves handle name.

Encryption: AES-256-GCM via System.Security.Cryptography.AesGcm with 12-byte random nonce prefixed to ciphertext (and 16-byte tag appended). Not currently interoperable with the Python SDK's Fernet format -- cross-language spec tracked in #2535.

Tests: 27 xUnit cases. dotnet build clean. dotnet test passes.
Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
@Ricky-G Ricky-G force-pushed the feat/cred-vault-dotnet branch from 42e55b7 to ccfcbef Compare May 25, 2026 10:20
Ricky-G added 2 commits May 25, 2026 23:00
Dispose MemoryStream in audit digest, use LINQ projections requested by code quality, simplify Put record construction with a conditional expression, switch temp path construction to Path.Join, and add dotnet credential vault spell-check terms.

Signed-off-by: Ricky Gummadi <ricky.gummadi@outlook.com>
@imran-siddique
Copy link
Copy Markdown
Member

Taken in via #2581 (rebased on current main, cspell conflicts resolved). Thanks for the dotnet credential vault implementation!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review:MEDIUM Contributor check flagged MEDIUM risk size/XL Extra large PR (500+ lines) tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants