The signature is valid. The string is still dangerous.
Bidirectional controls, zero-width characters, homoglyphs, and normalization differences can hide inside valid UTF-8. Hashes and signatures prove those bytes did not change. They do not decide whether the bytes should be accepted.
Keep three questions separate
| Question | Control | Result |
|---|---|---|
| Did the signed metadata change? | Verify the DSSE signature over the exact payload bytes. | Authentic or invalid signature. |
| Did the artifact change? | Hash the received bytes and match the signed subject digest. | Exact match or artifact mismatch. |
| Are the unchanged strings acceptable? | Apply a required organizational profile to the statement or actual structured artifact. | Profile passes or fails with a content-rule diagnostic. |
Put the decision in a profile
A team can keep its policy schema private and pin its exact digest in the signed statement. The profile can reject prohibited controls, require a declared normalization form, constrain selected fields, or require analysis metadata. Portable string constraints use the bounded makotoPattern vocabulary so the receiver can enforce resource limits.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://policy.example.invalid/customer-safe.schema.json",
"type": "object",
"properties": {
"display_name": {
"type": "string",
"makotoPattern": "^[A-Za-z0-9 .'-]{1,80}$"
}
},
"required": ["display_name"],
"additionalProperties": false
}The example policy is intentionally narrow, not a universal Unicode rule. Different languages and identifiers need different, reviewed constraints.
What the receiver should report
- Signature remains validThe attacker did not need to alter the signed statement.
- Artifact digest remains validThe dangerous character was already present in the signed data.
- Required profile failsThe receiving policy rejects the specific field and rule while preserving the evidence for investigation.
- Decision is denyThe report shows a content-policy failure, not a misleading integrity failure.
Add the exact string your pipeline must reject.
A useful fixture preserves the raw bytes, profile, expected path, and diagnostic so another verifier can reproduce the same decision.