Opraveno v upstreamu 27. 10. 2026  Tři neveřejně nahlášené opravy v ai-job-search

ai-job-search: pomalé pravidlo v robots.txt, volné volání curl a gitignore guard, se kterým git nesouhlasil

ai-job-search je framework pro hledání práce postavený na Claude Code: hodnotí inzeráty, upravuje životopisy a píše motivační dopisy. Uživatelé si ho forkují a ukládají do něj vlastní data. Na GitHubu má asi 67 000 hvězd a 21 000 forků. Sken stromu z 19. 10. 2026 označil tři problémy v jeho pomocných nástrojích a každý jsme neveřejně nahlásili přes GitHub s proof of conceptem a návrhem opravy. Správce Mads Lorentzen (MadsLorentzen) všechny tři 27. 10. potvrdil, ohodnotil je níž než my a týž den je opravil v master; v commitech uvádí nás jako zdroj hlášení. Oprava ReDoS je náš navržený matcher.

1. Pravidlo v robots.txt mohlo kontrolu zdržet na minuty

tools/robots_check.py stáhne robots.txt pracovního portálu dřív, než agent přečte inzerát. Funkce _match převáděla každou * v pravidle na regulární výraz .*:

pat = pattern[:-1] if end_anchor else pattern
rx = '^' + ''.join('.*' if c == '*' else re.escape(c) for c in pat) + ('$' if end_anchor else '')
return len(pattern) if re.match(rx, path) else -1

Soubor dodává kontrolovaný web. Pravidlo s mnoha segmenty se zástupnými znaky, které na cestu nesedí, třeba Disallow: /*a*a*a…*b$, pošle backtrackingový regex engine Pythonu do exponenciálního času. Děje se to v hlavním procesu až po návratu curl, takže časový limit curl nepomůže.

Navrhli jsme matcher, který místo regexu prochází tabulku v čase úměrném délce vzoru krát délce cesty. Mads Lorentzen naměřil na aktuálním master 5,6 sekundy při 14 segmentech a náš matcher převzal v pull requestu #779. Podle jeho commitu nenašel diferenciální fuzzing s 200 000 případy proti starému regexovému matcheru žádnou změnu výsledků a tři nové testy hlídají prefixové, ukotvené a přes lomítka jdoucí případy.

2. Tentýž nástroj předával curl libovolné schéma URL

gate() skládala cíl jako scheme://host/robots.txt bez kontroly schématu a _fetch() spouštěla curl -L bez omezení protokolů. Přímé volání s gopher: nebo ftp: došlo do curl beze změny a přesměrování mohlo protokol přepnout.

Správce ukázal, že dosah je užší, než tvrdilo naše hlášení. Složená URL změní file:///etc/passwd na file:///robots.txt, takže se žádný soubor nepřečte; curl už sám odmítá přesměrování na file, scp a smb; tělo odpovědi se nikdy nevypisuje; a hlavní cesta stahování, fetch_page.py, už povolovala jen http(s). Zbyl slepý požadavek a HTTP status. Naši navrženou opravu přesto převzal ve stejném pull requestu: gate() teď u jiného schématu než http(s) nebo u URL bez hostu bezpečně selže a curl dostává --proto =http,https --proto-redir =http,https.

3. Guard osobních dat četl .gitignore jinak než git

Forky projektu obsahují údaje o platu, životopisy a stažené seznamy nabídek a SECURITY.md projektu slibuje, že CI shodí každou změnu, která pravidla .gitignore pro tato data oslabí. check_gitignore() v tools/security_guards.py to dělala porovnáním řádků kořenového .gitignore po jejich oříznutí:

lines = [line.strip() for line in path.read_text(encoding="utf-8").splitlines()]

Git ignoruje jen neescapované mezery na konci řádku. Mezera na začátku je součástí vzoru, takže  salary_data.json už salary_data.json neignoruje, zatímco guard mezeru ořízl a prošel. Guard navíc četl jen kořenový soubor, takže .gitignore v podsložce s negací ! mohl osobní soubory vrátit do repozitáře a CI zůstalo zelené.

Mads Lorentzen reprodukoval obě části a ohodnotil problém jako nízký, protože obě změny jsou vidět v revidovaném diffu, ale dodal:

„catching exactly that is the guard’s job.“

Oprava v commitu 0bcfd75 čte řádky stejně jako git a kontroluje negace ve všech .gitignore pod kořenem, se seznamem povolených výjimek. SECURITY.md teď obě pravidla uvádí.

Časová osa

Jak to číst

Ani jeden ze tří problémů není díra zneužitelná na dálku. ReDoS zasekne jednu lokální kontrolu, kterou zastaví timeout nebo uživatel. Problém s curl vyžaduje přímé volání a dá jen slepý požadavek. Obejití gitignore vyžaduje změnu sledovaného souboru, kterou by recenzent viděl. Správce každý z nich ohodnotil níž než naše triáž a jeho poznámky hlášení zpřesnily. Hodnota je v nástrojích, které dělají, co bezpečnostní poznámky projektu slibují. Nálezy jsou podněty pro lidi, ne rozsudky.

Zdroje

← Zpět na příběhy úspěchu