Missing Copyright Or Licence Header
ID |
php.track_lack_copyright_license_headers |
Severity |
high |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Code Smell |
Language |
Php |
Tags |
best-practice, code-style |
Description
Reports a PHP source file whose leading comment block — the comments above the first parsed
token, be that a declare, a namespace clause or the first declaration — does not carry the
project’s copyright or licence notice.
What counts as a header is a project decision, so the notice is supplied as a regular expression
in the headerPattern property. The property is empty by default, and an empty pattern makes
the rule a no-op: a project with no header policy gets no findings at all, because flagging
every one of its files would be pure noise. Configure the pattern to switch the rule on.
All three comment forms count, so a // run, a # run and a block comment or docblock are
equally good places for the notice. Machine-generated files carrying a @generated or
DO NOT EDIT banner are skipped: nobody hand-edits them, and the generator rather than the
project decides what their first lines say.
Rationale
A file with no header leaves its ownership and its redistribution terms undeclared. Source files
travel on their own: they get vendored into another project, copied into a snippet, pasted into an
issue, or shipped inside a container image. Once separated from the repository’s LICENSE file,
an unheaded file carries no evidence of the terms it was released under.
That has concrete consequences. Licence-compliance scans and SPDX inventories read per-file notices, so an unheaded file shows up as unknown-licence and blocks the release. Contributors cannot tell whether a file is safe to reuse. And in a repository that mixes licences — a vendored third-party directory, a dual-licensed module — the absence of a header is genuinely ambiguous rather than merely untidy.
PHP makes the omission easy: the <?php tag opens the file, and the first thing most editors
generate after it is the namespace clause, with nothing in between.
<?php
namespace App\Billing;
class Invoice
{
public function total(int $a, int $b): int
{
return $a + $b;
}
}
Remediation
Add the project’s notice as a comment block immediately after the open tag. A docblock or a
declare(strict_types=1) may sit between the notice and the namespace clause; the pattern is
searched anywhere in the leading block, so any order matches.
<?php
// Copyright 2026 Example Corp.
// SPDX-License-Identifier: Apache-2.0
declare(strict_types=1);
namespace App\Billing;
class Invoice
{
public function total(int $a, int $b): int
{
return $a + $b;
}
}
Adding headers across an existing repository is mechanical and worth automating — reuse and
similar tools insert the block in place. Most IDEs also apply a copyright profile to every new
file, which keeps the problem from coming back.
Configuration
| Property | Default | Description |
|---|---|---|
|
|
Regular expression searched inside the file’s leading comment block. Set it to the notice the
project enforces — |