Static read-through audit of crates/dpp-seal — an explicitly-declared stub with no reachable attack surface yet. One verified finding.
1. Capability report contradicts actual operation behavior
Location: src/adapter.rs:50-52
Issue: QtspSealAdapter::capabilities() unconditionally returns GhostSeal.capabilities() regardless of self.qtsp_url, even in the "configured" branch where seal() and verify() both unconditionally return Err(Internal("not yet implemented")).
Failure scenario: A caller configures QTSP_URL, calls capabilities() first (as one naturally would) and is told supported_formats: [Jades] / sealing is supported — then calls seal() and gets an Internal error instead. SealCapabilities has no field distinguishing "ghost-backed" from "real" capability, so there's no way to detect the contradiction from the return value alone.
The refuse-rather-than-degrade behavior of seal()/verify() themselves is correct, intentional fail-closed design for a stub — only the capability report is inconsistent with it.
Static read-through audit of
crates/dpp-seal— an explicitly-declared stub with no reachable attack surface yet. One verified finding.1. Capability report contradicts actual operation behavior
Location:
src/adapter.rs:50-52Issue:
QtspSealAdapter::capabilities()unconditionally returnsGhostSeal.capabilities()regardless ofself.qtsp_url, even in the "configured" branch whereseal()andverify()both unconditionally returnErr(Internal("not yet implemented")).Failure scenario: A caller configures
QTSP_URL, callscapabilities()first (as one naturally would) and is toldsupported_formats: [Jades]/ sealing is supported — then callsseal()and gets anInternalerror instead.SealCapabilitieshas no field distinguishing "ghost-backed" from "real" capability, so there's no way to detect the contradiction from the return value alone.The refuse-rather-than-degrade behavior of
seal()/verify()themselves is correct, intentional fail-closed design for a stub — only the capability report is inconsistent with it.