fix: audit cleanup — ReDoS guard, Telegram validation, README accuracy

- form_filler.mjs: reject regex patterns over 200 chars to mitigate ReDoS
- notify.mjs: check res.ok before parsing Telegram API response
- README: update project structure with new lib/apply/ modules, session.mjs,
  keywords.mjs; fix max_applications_per_run docs (no limit by default);
  clarify ATS stub status in roadmap

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 17:20:32 -08:00
parent 33f85c4752
commit ec68e621b8
3 changed files with 19 additions and 5 deletions

View File

@@ -137,7 +137,7 @@ Patterns support regex:
| Key | Default | Description | | Key | Default | Description |
|-----|---------|-------------| |-----|---------|-------------|
| `max_applications_per_run` | `50` | Cap applications per run to avoid rate limits | | `max_applications_per_run` | no limit | Cap applications per run (optional, set to avoid rate limits) |
| `max_retries` | `2` | Times to retry a failed application before marking it permanently failed | | `max_retries` | `2` | Times to retry a failed application before marking it permanently failed |
| `browser.provider` | `"kernel"` | `"kernel"` for stealth browsers, `"local"` for local Playwright | | `browser.provider` | `"kernel"` | `"kernel"` for stealth browsers, `"local"` for local Playwright |
@@ -158,14 +158,26 @@ claw-apply/
├── job_searcher.mjs Search agent ├── job_searcher.mjs Search agent
├── job_applier.mjs Apply agent ├── job_applier.mjs Apply agent
├── setup.mjs Setup wizard ├── setup.mjs Setup wizard
├── status.mjs Queue status report
├── lib/ ├── lib/
│ ├── constants.mjs Shared constants and defaults │ ├── constants.mjs Shared constants and defaults
│ ├── browser.mjs Kernel/Playwright browser factory │ ├── browser.mjs Kernel/Playwright browser factory
│ ├── session.mjs Kernel Managed Auth session refresh
│ ├── form_filler.mjs Generic form filling with pattern matching │ ├── form_filler.mjs Generic form filling with pattern matching
│ ├── linkedin.mjs LinkedIn search + Easy Apply │ ├── keywords.mjs AI-generated search keywords via Claude
│ ├── wellfound.mjs Wellfound search + apply │ ├── linkedin.mjs LinkedIn search + job classification
│ ├── wellfound.mjs Wellfound search
│ ├── queue.mjs Job queue and config management │ ├── queue.mjs Job queue and config management
── notify.mjs Telegram notifications with rate limiting ── notify.mjs Telegram notifications with rate limiting
│ └── apply/
│ ├── index.mjs Apply handler registry
│ ├── easy_apply.mjs LinkedIn Easy Apply
│ ├── wellfound.mjs Wellfound apply
│ ├── greenhouse.mjs Greenhouse ATS (stub)
│ ├── lever.mjs Lever ATS (stub)
│ ├── workday.mjs Workday ATS (stub)
│ ├── ashby.mjs Ashby ATS (stub)
│ └── jobvite.mjs Jobvite ATS (stub)
├── config/ ├── config/
│ ├── *.example.json Templates (committed) │ ├── *.example.json Templates (committed)
│ ├── profile.json Your info (gitignored) │ ├── profile.json Your info (gitignored)
@@ -200,7 +212,7 @@ claw-apply/
- [x] Preview mode (`--preview`) - [x] Preview mode (`--preview`)
- [x] Configurable application caps and retry limits - [x] Configurable application caps and retry limits
- [ ] Indeed support - [ ] Indeed support
- [ ] External ATS support (Greenhouse, Lever) - [ ] External ATS support (Greenhouse, Lever, Workday, Ashby, Jobvite — stubs ready)
- [ ] Job scoring and ranking - [ ] Job scoring and ranking
- [ ] Per-job cover letter generation via LLM - [ ] Per-job cover letter generation via LLM

View File

@@ -23,6 +23,7 @@ export class FormFiller {
// Check custom answers first (user-defined, pattern is substring or regex) // Check custom answers first (user-defined, pattern is substring or regex)
for (const entry of this.answers) { for (const entry of this.answers) {
try { try {
if (entry.pattern.length > 200) throw new Error('pattern too long');
const re = new RegExp(entry.pattern, 'i'); const re = new RegExp(entry.pattern, 'i');
if (re.test(l)) return String(entry.answer); if (re.test(l)) return String(entry.answer);
} catch { } catch {

View File

@@ -32,6 +32,7 @@ export async function sendTelegram(settings, message) {
}), }),
}); });
lastSentAt = Date.now(); lastSentAt = Date.now();
if (!res.ok) { console.error(`[notify] Telegram HTTP error: ${res.status}`); return; }
const data = await res.json(); const data = await res.json();
if (!data.ok) console.error('[notify] Telegram error:', data.description); if (!data.ok) console.error('[notify] Telegram error:', data.description);
} catch (e) { } catch (e) {