Linux kill kept one digit and terminated almost the whole machine
Alan Grow traced several generations of procps argument parsing, then found two practical ways to contain the damage.

Alan Grow wanted to stop a group of rendering processes. The external kill utility took the request considerably more personally: almost every process on the machine went away. An argument intended to name one group had become -1, whose meaning is broad enough to make root privileges an especially unwelcome accessory.
Grow’s September 24 account identifies procps 4.0.4 on Ubuntu 24.04. The command used a negative process-group identifier beginning with 1. A negative group identifier is legitimate input, but its leading hyphen also resembles an option. The collision occurred before the intended number reached the signaling operation.
The option parser reported an unrecognized character through optopt. The error-handling branch then subtracted that one digit from the character zero and treated the result as a PID. It had preserved the first digit while losing the rest of the identifier. A seven-digit address had effectively become a house number with the street ripped off.
For an identifier beginning with 1, that arithmetic produced -1. Grow cites the kernel behavior: the signal reaches processes the caller has permission to signal, with process 1 excluded. Because his command ran with root privileges, the available target set was enormous. The parser provided the mistake; the permission level provided the blast radius.
Grow found four different negative-PID parsing failures across Ubuntu LTS releases. They did not all fail the same way: some did nothing, one path segfaulted, another could signal the caller’s own process group. That history matters because “it worked on the previous box” cannot establish how this external utility parses the same text on the next one.
His immediate workaround inserts the end-of-options separator before the negative identifier. In his example, kill -TERM -- -1490947 preserves the group number through the buggy versions discussed. This is an example to understand, never a command to paste into a running server: the identifier must belong to the processes actually intended for termination.
Grow’s second recommendation is least privilege. Sending the signal as the rendering account would have limited the damage to processes that account could signal. Permission boundaries become particularly valuable when a small, familiar tool develops surprising behavior. “Kill with kindness” has limits; killing with a narrower account at least has a boundary.
This account concerns the external procps implementation, and shells can supply their own kill built-in. Before changing an operational recipe, identify which implementation the actual script invokes and check its documentation. A fix tested against the interactive shell can leave a scheduled command untouched (naturally). The vulnerable path is the one that needs the check.
A durable review of a shutdown script would therefore examine the exact executable, argument boundary and account together. A later package version may repair parsing, but the command still expresses a dangerous operation. Grow had a bug fix on the way when he wrote; the operator still has to establish what version and path a particular machine runs.
Process 1 was excluded.