Octal Values

ID

go.octal_values

Severity

critical

Remediation Complexity

trivial

Remediation Risk

medium

Remediation Effort

low

Resource

Code Smell

Language

Go

Tags

code-style, reliability

Description

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

Go writes octal two ways. The legacy form is a bare leading zero, 0644, which reads like a decimal number and is not one. The modern form, 0o644, states the base explicitly. Both are reported when the value is not a permission bitmask, because outside that one use 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 0o755 is how the Go standard library documents them. See Configuration for how a file mode is recognised.

Rationale

const bufferSlots = 010     // FLAW — this is 8, not 10
var stride = 0777           // FLAW — octal bound to an ordinary variable
head := 010                 // FLAW — 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 compiles and runs with a different value than the author wrote, and no test that only exercises the happy path will notice.

The explicit 0o form cannot be misread, but outside a permission bitmask it still leaves the question of why the value is in base 8 unanswered. Octal is only self-explanatory when its digits map onto three-bit groups, which is exactly what a Unix mode is and what an ordinary integer is not.

Remediation

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

const bufferSlots = 8       // a count, in decimal
var stride = 511            // if 511 really was the intent

// If the value is a file mode, say so — then octal is the right notation and is accepted.
var dirPerm os.FileMode = 0o755
perm := 0o640
os.Chmod(path, 0755)
tar.Header{Mode: 0644}

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.

Configuration

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

Property Meaning Default

fileModeFunctions

Qualified function names whose arguments are permissions or umasks. Any octal anywhere in such a call’s argument list is accepted.

os.Chmod, os.Mkdir, os.MkdirAll, os.MkdirTemp, os.OpenFile, os.WriteFile, os.FileMode, os.Chown, os.Lchown, ioutil.WriteFile, fs.FileMode, syscall.Umask, syscall.Chmod, syscall.Mkdir, syscall.Open, unix.Umask, unix.Chmod, unix.Mkdir, unix.Open

fileModeTypes

Declared types that make a literal a file mode, on a const, var or struct field.

os.FileMode, fs.FileMode

fileModeNames

Name words that make a literal a file mode. The identifier the literal is bound to — a const, var or := name, an assignment target, a struct field, or a composite-literal key such as tar.Header{Mode: 0644} — is split on its camel-case and underscore boundaries, so filePermissions and dirPerm 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