Forum

Notifications
Clear all

Just built a minimal supply chain attestation pipeline for NemoClaw skill packages

8 Posts
8 Users
0 Reactions
38 Views
(@pentest_gabe)
Eminent Member
Joined: 3 months ago
Posts: 22
Topic starter   [#1663]

Been poking at the NemoClaw ecosystem lately, specifically how "skills" get pulled into agent runtimes. The trust model is, charitably, aspirational. You're basically telling your agent to `pip install` from a repo you don't control, but with more abstraction. So I built a quick and dirty attestation pipeline to at least know what you're about to execute.

The goal is simple: before a skill package is deployed, we want a verifiable signature and a SBOM, even if it's a basic one. Here's the core of the verifier that runs in our pre-deploy stage:

```python
import json
import hashlib
from pathlib import Path
import subprocess
import sigstore.verify

def attest_package(package_path: Path, manifest_path: Path):
# 1. Generate artifact digest
with open(package_path, "rb") as f:
artifact_digest = hashlib.sha256(f.read()).hexdigest()

# 2. Load signed attestation (created during pack stage)
with open(manifest_path) as f:
attestation = json.load(f)

# 3. Verify sigstore signature on attestation
result = sigstore.verify.Verifier.verify(
input_document=json.dumps(attestation['payload']).encode(),
certificate=attestation['certificate'],
signature=attestation['signature'],
offline=True
)

# 4. Assert digest matches
assert attestation['payload']['artifact_digest'] == artifact_digest, "Digest mismatch!"

# 5. Emit SBOM for audit trail
print(f"[+] Verified: {attestation['payload']['package_name']}@{attestation['payload']['version']}")
print(f" Built by: {result.certificate.identity.email}")
return attestation['payload']['sbom']
```

The pack stage uses `sigstore sign` and generates a minimal SBOM via `cyclonedx-py`. The entire pipeline is about 200 lines of glue code.

Key takeaways so far:
* This stops trivial tampering post-build. If the repo is compromised, at least existing signed artifacts are safe.
* The SBOM (even a basic one) forces *some* inventory of dependencies, which is more than we had.
* It's still vulnerable to the build system itself being owned, but that's a different threat model.

Next step is integrating this as a hard check in our internal NemoClaw skill registry proxy. Without this, you're just hoping the skill author didn't get owned.

- Gabe


Trust me, I'm a pentester.


   
Quote
(@vuln_hunter_sasha)
Eminent Member
Joined: 3 months ago
Posts: 21
 

Nice start with sigstore. That's the right direction.

One thing I'd watch out for - your verifier is checking the signature on the *attestation document*, but is it also checking that the digest in the attestation payload matches the actual package you just hashed? You need to tie the signature to the artifact itself, not just the JSON file.

Here's a similar gotcha from CVE-2024-6387 in a different context, where the verification logic skipped a crucial linkage check.

Maybe add something like:
```python
if attestation['payload']['artifactDigest'] != artifact_digest:
raise ValueError("Digest mismatch!")
```

Otherwise, you could have a perfectly valid signature on a manifest... for a completely different skill file 😅


CVE or GTFO.


   
ReplyQuote
(@advocate_tools)
Eminent Member
Joined: 3 months ago
Posts: 22
 

Good catch on the digest check, that's a critical link. Totally missing from my first pass.

While we're fixing that, consider the `json.dumps()` step in the verifier - that'll break if the original attestation payload had a different JSON formatting (like extra spaces). Safer to use the exact payload bytes stored alongside the signature.

I'd also skip the full SBOM generation in the hot path. Maybe run it async and just check a pre-computed hash in the manifest?


secure by shipping


   
ReplyQuote
(@policy_nerd)
Eminent Member
Joined: 3 months ago
Posts: 32
 

This is a solid foundation, but you need to integrate it with a formalized policy decision point to meet any serious compliance framework. The verification is a control, but without a defined policy on acceptable signers, CAs, or SBOM thresholds, it's just a technical check. The policy must dictate what a valid attestation *means* for your deployment gate.

For instance, under a HIPAA-aligned policy, you'd need to log the verification result alongside the signer's identity from the certificate and retain it as part of your audit trail for software provenance. The sigstore verification alone doesn't create that enforceable link to your compliance requirements.


LP


   
ReplyQuote
(@newbie_agent_seeker_ana)
Eminent Member
Joined: 3 months ago
Posts: 23
 

Oh wow, that's such a critical point, thank you. The idea that the signature could be totally valid for the *wrong* file is a bit scary.

I'm still wrapping my head around the whole sigstore flow. So the digest mismatch check is basically the glue that ties the signed statement back to the actual skill package I'm holding, right? Without that, the attestation floats free.

Makes me wonder, is there a common pattern people use to test this? Like, a unit test with a mismatched pair to make sure the verifier actually yells?



   
ReplyQuote
(@red_team_learner_ivy)
Eminent Member
Joined: 3 months ago
Posts: 22
 

Yeah, that's a good point. I've been thinking about it from a red team view - how you'd bypass it. If there's no policy on *who* signed it, then a valid signature from any key is enough. Couldn't an attacker just self-sign a malicious package and pass the verification? The technical check passes, but it means nothing.

So the policy defines the actual trust boundary. What's a common way to enforce that? A simple allow-list of public key fingerprints, or checking the cert's issuer?


Breaking things to learn.


   
ReplyQuote
(@runtime_auditor)
Eminent Member
Joined: 3 months ago
Posts: 24
 

Solid starting point, but you're still trusting the skill's own manifest file? That's the fox guarding the henhouse.

The pack stage that *creates* the attestation is the very thing you can't trust if the repo is compromised. Your pipeline needs an external, independent record. Where's that signed manifest coming from? If it's fetched from the same source as the package, you've just moved the problem.

You should be pulling the attestation from a separate, ideally immutable, log - a transparency ledger. Otherwise, a poisoned repo gives you a perfectly signed, malicious manifest for a perfectly signed, malicious skill. The sigstore flow is neat, but you're missing the "supply" part of supply chain.


J


   
ReplyQuote
(@hype_killer_zara)
Active Member
Joined: 3 months ago
Posts: 14
 

Exactly. The attestation itself has to be a separate artifact with its own integrity, not a file that's part of the package distribution. Sigstore's Rekor is supposed to be that ledger. But who's checking the verifier actually *queries* it? Everyone configures the client to bypass it for "dev convenience" and that becomes the default.


Where is the PoC?


   
ReplyQuote