Who May Cron
Scope: the access rules around cron — who is allowed a crontab at all, whose jobs should run as whom, and the one configuration that turns a crontab into a privilege-escalation machine.
The gate: cron.allow and cron.deny
By default, every user may have a crontab. Two files
in /etc narrow that:
/etc/cron.allow— if it exists, only users listed in it (one per line) may usecrontab./etc/cron.deny— if there's no allow file, users listed in the deny file are refused.
The lab created a user mere and ran the experiment
both ways. With an allow file naming only root:
$ su - mere -c "crontab -l"
You (mere) are not allowed to use this program (crontab)
See crontab(1) for more information
With mere in a deny file instead, the identical
refusal. Exit status 1 both times, and the refusal is
the crontab command's — the files gate the tool,
so a refused user can't install, list, or remove a
crontab at all.
(Leaving both files absent restores the default. One
lab note: on the sandbox, mere's allowed runs then
failed at the spool directory — the sandbox silently
ignores the setgid bit the real crontab binary
uses to reach it, verified with a test binary. That's
this box's quirk, not cron's behaviour; on a stock
system an allowed user's crontab -l answers "no
crontab for mere".)
Root is never gated by these files. And note what the gate doesn't do: it says nothing about the system tables — those are root's files, protected by ordinary file permissions.
Run jobs as the smallest user that works
Every job runs as somebody, and that choice is a security decision:
- A user crontab job runs as that user, with that user's powers. Default to this.
- A system table job runs as the user its user
field names.
rootis the common entry and the lazy one: a backup that only reads your documents doesn't need to be root; name your own account and the job's worst day gets smaller. - Root jobs earn their keep only for genuinely system-level work — and they make the next section load-bearing.
The cardinal sin: a root job running a writable script
If root's crontab runs /home/you/bin/backup.sh, then
anyone who can edit that script is root, on a timer.
The rule, worth stating flatly:
Never schedule, as root (or any other user), a script that a less-privileged user can modify.
Check the whole chain, not just the file: the script,
the directory it sits in, any file it reads commands
or configuration from. Root-owned scripts live in
root-owned directories (/usr/local/sbin is the
customary place). The crontab command protects the
tables themselves — spool files are mode 600 and
system tables are root's — but it cannot protect what
the tables point at.
Two smaller corollaries:
- A user crontab on a shared machine is still that
user's whole authority, on a schedule, unattended.
Treat a surprising crontab the way you'd treat a
surprising shell profile: as something to explain.
(
journalctl -t crontabshows who installed what, when.) - Don't widen the gate casually: adding a service
account to
cron.allowis giving that account a timed, unattended execution path. That's sometimes the point. Do it on purpose.