T09 · Insecure Skill Coding Practices
- Location
SKILL.md:337- Finding
Unsigned credential payloads are presented as SD-JWT-VC credentials
- Content
View full analysis
dict: """Build the issuer-signed JWT payload.""" payload = { "iss": self.issuer_did, "sub": self.subject_did, "iat": int(self.issued_at), "exp": int(self.expires_at), "vct": self.credential_type, "_sd": self.sd_digests(), "_sd_alg": "sha-256", } # Include non-disclosable claims directly for name, value in self.claims.items(): if name not in self.disclosable_claims: payload[name] = value if self.parent_hash: payload["parent_credential"] = self.parent_hash return payload def present(self, disclosed_claims: List[str]) -> dict: """Create a presentation with only the specified claims disclosed.""" selected = [d for d in self.disclosures if d.claim_name in disclosed_claims] return { "jwt_payload": self.jwt_payload(), "disclosures": [d.encode() for d in selected], "disclosed_values": { d.claim_name: d.claim_value for d in selected }, } def credential_hash(self) -> str: """SHA-256 hash of the credential payload for chain linking.""" payload_bytes = json.dumps(self.jwt_payload(), sort_keys=True).encode() return hashlib.sha256(payload_bytes).hexdigest() ``` ### Technical Analysis The implementation describes `jwt_payload()` as issuer-signed, but it only constructs and returns a Python dictionary. It never creates a compact JWT, applies a JWS signature, protects the signing algorithm, or associates the signature with a trusted issuer key. The presentation also lacks a holder key-binding JWT. Hashing the payload with SHA-256 does not authenticate it because an attacker who modifies the payload can simply recompute the hash. Disclosure digests protect neither the ...[truncated 1139 chars]- Remediation
View remediation
