Hi,
while reviewing the current veraison/ear package, I noticed that AttestationResult.Verify() appears to skip the final semantic validation step.
This may be adjacent to #6, but it seems narrower and more concrete:
Verify() verifies the JWT signature and parses claims, but does not call validate() before returning.
Current behavior
The doc comment for Verify() says:
The payload is then parsed and validated.
However, the current implementation returns directly from:
return o.populateFromMap(claims)
By contrast, UnmarshalJSON() does:
if err := o.populateFromMap(oMap); err != nil {
return err
}
return o.validate()
and Sign() also calls validate().
Confirmed example
I reproduced this locally against the current main code with Go 1.24.2.
A signed JWT with an invalid eat_profile, for example:
completely-invalid-profile
is accepted by Verify().
The same populated object is then rejected by validate() with:
invalid value(s) for eat_profile (completely-invalid-profile)
I also checked the broader case of missing mandatory top-level fields.
Those are already rejected during parsing, so the issue seems to be the narrower one: Verify() accepts structurally valid but semantically invalid EARs because it does not call validate().
Why this matters
This looks like an API-contract / conformance bug rather than a crypto issue.
A caller that uses Verify() as the package's fully validated entry point may accept tokens from unrecognized profiles unless it performs additional
semantic checks after verification.
Suggested fix
Would it make sense to make Verify() consistent with UnmarshalJSON() and Sign() by calling validate() after populateFromMap() succeeds?
Conceptually:
if err := o.populateFromMap(claims); err != nil {
return err
}
return o.validate()
If useful, I can also share the small local repro test I used.
Thanks.
Hi,
while reviewing the current
veraison/earpackage, I noticed thatAttestationResult.Verify()appears to skip the final semantic validation step.This may be adjacent to #6, but it seems narrower and more concrete:
Verify()verifies the JWT signature and parses claims, but does not callvalidate()before returning.Current behavior
The doc comment for
Verify()says:However, the current implementation returns directly from:
By contrast,
UnmarshalJSON()does:and
Sign()also callsvalidate().Confirmed example
I reproduced this locally against the current
maincode with Go1.24.2.A signed JWT with an invalid
eat_profile, for example:is accepted by
Verify().The same populated object is then rejected by
validate()with:I also checked the broader case of missing mandatory top-level fields.
Those are already rejected during parsing, so the issue seems to be the narrower one:
Verify()accepts structurally valid but semantically invalid EARs because it does not callvalidate().Why this matters
This looks like an API-contract / conformance bug rather than a crypto issue.
A caller that uses
Verify()as the package's fully validated entry point may accept tokens from unrecognized profiles unless it performs additionalsemantic checks after verification.
Suggested fix
Would it make sense to make
Verify()consistent withUnmarshalJSON()andSign()by callingvalidate()afterpopulateFromMap()succeeds?Conceptually:
If useful, I can also share the small local repro test I used.
Thanks.