Skip to content

Dev - #31

Merged
csupenn merged 6 commits into
mainfrom
dev
Sep 26, 2026
Merged

Dev#31
csupenn merged 6 commits into
mainfrom
dev

Conversation

@csupenn

@csupenn csupenn commented Sep 26, 2026

Copy link
Copy Markdown
Owner

Description

Promote dev → main.

Testing

Combined dev verified locally: type-check clean, lint 0 errors, test:ci 603 tests +
coverage thresholds, build OK.

Security Impact

Closes an SSRF bypass on the HTTP Request node. Residual: DNS rebinding (documented).

csupenn and others added 6 commits September 26, 2026 16:26
…tor docs

Coverage (H6): the old 75/70/75/75 global threshold was never met (actual
~17%) and CI hid it with continue-on-error.
- jest: per-file thresholds hold the security core (ssrf, rate-limit,
  workflow-graph, urw) and the execute-workflow route near their current
  90-100%; global is a ratchet floor at today's measured level
- ci: single blocking `pnpm test:ci` step replaces test + non-blocking coverage
- verified: dropping ssrf tests fails the ssrf threshold

Docs (H5): CONTRIBUTING project structure / node-type steps / Node 22 now
match the code (builder in app/builder, validation + codegen in
@charliesu/workflow-core, security controls in lib/security); remove link
to a private docs path; TESTING.md, testing-guide.md and ci.md show real
coverage numbers and the enforced policy.

eslint: ignore generated coverage/ and Playwright report dirs.
#28)

  ## Description
H5 + H6: make coverage thresholds honest and blocking; refresh stale
contributor docs.

  ## Type of Change
  - [x] Documentation update
- [x] Security improvement (CI now enforces coverage on
security-critical modules)

  ## Testing
pnpm test:ci passes (538 tests). Dropping ssrf tests fails the ssrf
threshold (enforcement verified).
  Lint 0 errors, type-check clean, build OK.

  ## Security Impact
Regressions in SSRF / rate-limit / cycle-detection / URW / execute-route
test coverage now fail CI.


## Details

Coverage (H6): the old 75/70/75/75 global threshold was never met
(actual ~17%) and CI hid it with continue-on-error.
- jest: per-file thresholds hold the security core (ssrf, rate-limit,
workflow-graph, urw) and the execute-workflow route near their current
90-100%; global is a ratchet floor at today's measured level
- ci: single blocking `pnpm test:ci` step replaces test + non-blocking
coverage
- verified: dropping ssrf tests fails the ssrf threshold

Docs (H5): CONTRIBUTING project structure / node-type steps / Node 22
now match the code (builder in app/builder, validation + codegen in
@charliesu/workflow-core, security controls in lib/security); remove
link to a private docs path; TESTING.md, testing-guide.md and ci.md show
real coverage numbers and the enforced policy.

eslint: ignore generated coverage/ and Playwright report dirs.
…hex form

The WHATWG URL parser rewrites embedded IPv4 in IPv6 hosts to hex before
the guard sees them: http://[::ffff:169.254.169.254]/ arrives as
[::ffff:a9fe:a9fe]. isBlockedIpv6 only matched the dotted ::ffff:a.b.c.d
form, so loopback / private / cloud-metadata targets written this way
passed checkOutboundUrl — an SSRF bypass on the HTTP Request node.

- ssrf.ts: decode hex-embedded IPv4 (::ffff:x:y mapped and deprecated
  ::x:y compatible) and re-apply the IPv4 block rules
- tests: new cases go through checkOutboundUrl (the engine's call path),
  covering hex/expanded IPv6 forms plus decimal/octal/hex IPv4 hosts
  (already safe via parser normalization); red before, green after
- tutorial 01: A5 note + post-release finding + parser-differential lab

Found while pointing the builder validation panel at the same guard.
…ecks

lib/security/validation-engine.ts powers the builder's Validation panel
but had 0% coverage and its own copy of the SSRF/cycle rules, which had
drifted from what the server enforces:
- missed [::1], IPv4-mapped IPv6, CGNAT 100.64/10, 0/8, *.internal,
  *.local, and non-http schemes (file:, gopher: were only "insecure HTTP")
  -> panel reported "SSRF Prevention: passed" for targets the server blocks
- substring matching flagged public hosts like notlocalhost.com

Now checkSSRF delegates to checkOutboundUrl (lib/security/ssrf.ts) and
cycle detection to detectWorkflowCycle (workflow-graph.ts), so the panel
shows exactly what execution enforces. HTTP-not-HTTPS stays a warning;
unparseable URLs stay a warning.

- 46 tests (structure, SSRF parity incl. URL-normalized forms, PII count
  without echoing values, score bounds, API-key requirements)
- coverage: 0% -> 100% lines / 94% branches; per-file threshold added
- TESTING.md: updated numbers (603 tests, ~19% overall)
#29)

  ## Description
  Cover lib/security/validation-engine.ts (0% → 100% lines) and make its SSRF/cycle checks
  delegate to lib/security/ssrf.ts + workflow-graph.ts — the builder panel had drifted from
  what the server enforces (false "passed" on [::1], CGNAT, *.internal, file:; false positive
  on notlocalhost.com).

  ## Type of Change
  - [x] Security improvement

  ## Testing
  46 new tests; per-file coverage threshold added. test:ci 603 tests pass; lint 0 errors;
  type-check clean; build OK.

  ## Security Impact
  Validation panel now shows exactly what execution enforces (single source of truth).
#30)

…ecks

lib/security/validation-engine.ts powers the builder's Validation panel
but had 0% coverage and its own copy of the SSRF/cycle rules, which had
drifted from what the server enforces:
- missed [::1], IPv4-mapped IPv6, CGNAT 100.64/10, 0/8, *.internal,
*.local, and non-http schemes (file:, gopher: were only "insecure HTTP")
-> panel reported "SSRF Prevention: passed" for targets the server
blocks
- substring matching flagged public hosts like notlocalhost.com

Now checkSSRF delegates to checkOutboundUrl (lib/security/ssrf.ts) and
cycle detection to detectWorkflowCycle (workflow-graph.ts), so the panel
shows exactly what execution enforces. HTTP-not-HTTPS stays a warning;
unparseable URLs stay a warning.

- 46 tests (structure, SSRF parity incl. URL-normalized forms, PII count
without echoing values, score bounds, API-key requirements)
- coverage: 0% -> 100% lines / 94% branches; per-file threshold added
- TESTING.md: updated numbers (603 tests, ~19% overall)
@vercel

vercel Bot commented Sep 26, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
top-flow Ready Ready Preview Sep 26, 2026 11:49pm UTC

@csupenn
csupenn merged commit b180e80 into main Sep 26, 2026
8 checks passed

This branch was successfully deployed

1 active deployment
Preview — 0e0250e1 Deployed Sep 26, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant