Octal Values

ID

php.octal_values

Severity

critical

Remediation Complexity

trivial

Remediation Risk

medium

Remediation Effort

low

Resource

Code Smell

Language

Php

Tags

code-style, reliability

Description

Reports an octal integer literal that is not being used as a Unix file mode.

PHP writes octal with a bare leading zero, 0644. The literal reads like a decimal number and is not one, and outside a permission bitmask neither base 8 nor the leading zero carries meaning a reader can act on.

File modes are exempt: octal is the conventional notation for permissions and umasks, and 0755 is how the PHP manual documents them. See Configuration for how a file mode is recognised.

Rationale

$slots = 010;                 // this is 8, not 10
const RETRY_BUDGET = 0123;    // octal bound to an ordinary constant
$head = 010;                  // an offset written in base 8 for no reason

The leading-zero form is a silent trap. 010 is decimal 8, and nothing on the line says so: the literal looks like the decimal number ten to every reader who has not memorised the rule. A count, a size, a port, a timeout or an array index typed with an accidental leading zero parses and runs with a different value than the author wrote, and no test that only exercises the happy path will notice.

The trap has teeth in PHP specifically because a leading zero is how the language writes an aligned column of numbers. ['0644', '0755'] is a pair of strings and means what it says; dropping the quotes silently changes both values.

Remediation

Write the value in the base that matches how it is used, and let the name say when a value is a permission.

$slots = 8;                   // a count, in decimal
const RETRY_BUDGET = 83;      // if 83 really was the intent

// If the value is a file mode, say so — then octal is the right notation and is accepted.
$dirPerm = 0755;
chmod($path, 0644);
mkdir($dir, 0750, true);
$options = ['mode' => 0777];

For bit flags, prefer the base that shows the bits: 0b1010 for a bitmask, 0x1F for a byte pattern. Both are excluded from this rule.

The PHP 8.1 explicit form 0o755 is not reported, because the analyzer’s PHP grammar does not accept it; only the legacy leading-zero form reaches this rule, which is the form the check is about — an explicit prefix cannot be misread.

Configuration

A literal is treated as a file mode, and not reported, when either of these says so.

Property Meaning Default

fileModeFunctions

Function names whose arguments are permissions or umasks. A call is matched on the last segment of its callee name, so one entry covers chmod(…), \chmod(…), $fs→chmod(…) and Filesystem::chmod(…). Any octal anywhere in such a call’s argument list is accepted.

chmod, mkdir, umask, mkfifo, ftp_chmod, posix_mkfifo, posix_mknod, sem_get, shm_attach, msg_get_queue, decoct, octdec, makeDirectory, ensureDirectoryExists

fileModeNames

Name words that make a literal a file mode. The name the literal is bound to — a variable, a class field, a const, a parameter default, an array entry key such as 'mode' ⇒ 0755, or a named argument — is split on its camel-case and underscore boundaries, so $filePermissions, $dirPerm and DEFAULT_FILE_MODE match without needing an entry each.

mode, modes, filemode, dirmode, perm, perms, permission, permissions, umask, mask

Add a project’s own permission wrapper to fileModeFunctions to silence findings inside it.

© 2026 Xygeni. All rights reserved