CROSS JOIN pairs every row of one table with every row of another, with no ON. Five categories crossed with six months is 30 rows. It's also what you get by accident when you forget the ON of a join, which is why a runaway row count is worth a second look.
The useful case is a grid of every combination you want to report on, including the ones with no data:
SELECT c.category, m.month
FROM (SELECT DISTINCT category FROM products) AS c
CROSS JOIN (VALUES (1), (2), (3)) AS m(month);
VALUES builds a small table on the spot. Once you have the grid, LEFT JOIN the real numbers onto it and use COALESCE(..., 0), so a category with no sales in a month shows 0 instead of disappearing.