The report was supposed to run only when the 1st landed on a Friday. The crontab said 0 9 1 * 5, and it also ran on a Friday that was not the 1st. On Vixie cron and cronie, both day fields being set means the job runs when either field matches. It does not wait for the 1st to be a Friday. That line is 09:00 on the 1st, and 09:00 on every Friday. A star in one of those fields turns the choice off. The cron generator can fill the five fields, and it cannot tell you which daemon will read them.

What the five fields actually select

0 9 1 * * is 09:00 on the 1st, and on no other day. The weekday is a star, so Friday never enters the decision.

0 9 * * 5 is 09:00 every Friday. The day of the month is a star, so the 1st matters only when that date is itself a Friday.

The either-day rule starts when both day fields are restricted. A number, a list, a range, or a step such as 1-31/2 counts as restricted. A day field that starts with * does not, and */2 is in that group. The step still picks days. Cron then joins that field to the other day field with AND.

30 4 1,15 * 5 

Read that as 04:30 on the 1st, 04:30 on the 15th, and 04:30 every Friday. When the 1st is a Friday, it is still one line, so the command runs once that morning.

Friday the 1st, on Vixie cron

One standard five-field line cannot say “Friday the 1st only.” Schedule the date, and test the weekday in the command. On GNU date, and in POSIX, %u is 1 for Monday through 7 for Sunday, so Friday is 5. Cron runs the command with sh. The [ test is a POSIX builtin, and the job needs an absolute path.

0 9 1 * * [ "$(date +\%u)" -eq 5 ] && /usr/local/bin/job 

In the crontab, write \%. A bare % is a newline. A terminal keeps %.

Where this rule stops

The rule above is Vixie cron and cronie. This guide does not claim it for every Kubernetes CronJob, for GitHub Actions, or for BusyBox crond.

Quartz, Spring, and EventBridge use a different field shape, with ? in a day field, so a five-field line matches none of them. systemd OnCalendar joins a weekday and a day of the month with AND.

The generator’s sentence for 0 9 1 * 5 is “at minute 0, at hour 9, on day-of-month 1, on Friday.” That list is not the either-day rule. Test the line on the host that will run it.

The full guide, with the one-minute test and the FAQ: https://kepttools.com/guides/cron-both-day-fields