AeadDecryptionTagLengthUnchecked
warning native off by default PHP ≥ 7.1Group: Security
Authenticated decryption needs a tag of the expected length. Validate request-supplied tag lengths before calling the decryptor. This inspection is disabled by default because the intended policy or use can vary.
Example
php
<?php
openssl_decrypt($cipher,"aes-256-gcm",$key,OPENSSL_RAW_DATA,$iv,$_POST["tag"]);Reported:
- line 2: Validate the authentication tag length before decrypting.
Detection
- Resolved openssl_decrypt uses literal GCM cipher and tag directly derived from request superglobal, without a dominating strlen(tag)===16 guard. Restrict to configured expected GCM tag length 16 by default; CCM and known constant tags excluded.
- A guard is a comparison of a resolved
strlencall (ormb_strlenwith the8bitencoding) of the tag with an integer, in either operand order, strict or loose (strlenreturns an integer, so both read alike), that leaves only the expected length where the tag is read. It may sit in any guarding position: the branch of anif/elseif/elseor of a ternary the comparison selects, the right operand of a short-circuit operator, or code after an earlierifwhose body always exits. The measured expression must be the value passed as the tag: the same variable while it still holds the measured value, or a read of the same key of the same request superglobal while nothing can have written it: no write to that element or the whole superglobal, and no call that may run project code, which can write any superglobal, between the guard and the tag (also later in a loop around the tag). A short ternary, another length and a guard on another element prove nothing. - Source provenance additionally requires an untouched lexical superglobal prefix. Exclude earlier explicit writes to or reference escapes of that superglobal and any earlier write or reference target involving GLOBALS. Reject all earlier object construction and unknown calls, including calls with no arguments, method calls and static calls; only resolved strlen, is_string, ctype_alnum, ctype_digit or in_array are supported pure-call exceptions. Traverse at most 4096 AST nodes, excluding nested variable scopes; exhaustion or unsupported source mutation discards the request-origin proof.
- Resolve builtin functions, classes, constants and methods; user-defined lookalikes are excluded. Follow only bounded local proof in one lexical scope.
- Emit one finding per violating operation, not per supporting evidence statement. When the proof is inconclusive, nothing is reported.
Exceptions (no report)
- Do not report unresolved or shadowed builtin names, unknown values, or incomplete receiver/type provenance. Unknown calls, aliases escaping, and intervening writes invalidate local proof. Similar code outside the stated detection contract is not a finding.
- Both standard suppression forms suppress this native ID.
Fix
None. Choosing a repair requires intent or additional runtime information.
PHP versions
Requires PHP 7.1 or later.
Options
| Option | Type | Default | Effect |
|---|---|---|---|
| tagLength | int | 16 | Expected GCM tag length in bytes that the length guard must check. |
Configure
In custos.json:
json
{
"rules": {
"AeadDecryptionTagLengthUnchecked": {
"enabled": true,
"options": {
"tagLength": 16
}
}
}
}Suppress
Before the statement or declaration (or the first statement of the file):
php
// @custos-ignore AeadDecryptionTagLengthUnchecked