Skip to content

Update dependency form-data to v4.0.6 [SECURITY]#28613

Open
tryghost-renovate[bot] wants to merge 1 commit into
mainfrom
renovate/npm-form-data-vulnerability
Open

Update dependency form-data to v4.0.6 [SECURITY]#28613
tryghost-renovate[bot] wants to merge 1 commit into
mainfrom
renovate/npm-form-data-vulnerability

Conversation

@tryghost-renovate

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Change Age Confidence
form-data 4.0.54.0.6 age confidence

Warning

Some dependencies could not be looked up. Check the Dependency Dashboard for more information.


form-data: CRLF injection in form-data via unescaped multipart field names and filenames

CVE-2026-12143 / GHSA-hmw2-7cc7-3qxx

More information

Details

Summary

form-data builds multipart/form-data request bodies. Through v4.0.5, the field name passed to FormData#append and the filename option are concatenated directly into the Content-Disposition header with no escaping of CR (\r), LF (\n), or ". An application that uses untrusted input as a field name or filename therefore lets an attacker terminate the header line and either inject additional headers or smuggle whole additional multipart parts into the request the application forwards to a backend.

This is CWE-93 (CRLF injection). It is a divergence from how browsers and the WHATWG HTML spec serialize form-data (they escape these characters), so the fix is to match that behavior. Severity is conditional: it depends on the consuming application passing attacker-controlled data as a field name or filename. Applications that only use fixed/trusted field names are not affected.

Details

In lib/form_data.js, _multiPartHeader builds the part header as:

'Content-Disposition': ['form-data', 'name="' + field + '"'].concat(contentDisposition || [])

and _getContentDisposition builds filename="' + filename + '"'. Neither escapes control characters, so a \r\n in field/filename ends the header line. The same applies to ", which can break out of the quoted parameter.

Proof of concept
const FormData = require('form-data');
const form = new FormData();
form.append('email"\r\nX-Injected: true\r\nfake="', 'user@example.com');
console.log(form.getBuffer().toString());

Before the fix this emits an injected X-Injected: true header line. A field name that also includes --<boundary> sequences can introduce additional parts (e.g. an extra name="is_admin" field), which a downstream parser accepts as legitimate.

Impact

For an application that uses untrusted field names/filenames:

  • Field injection / override (integrity). Inject or override fields the backend trusts (e.g. is_admin, role) — the primary demonstrated impact.
  • Header injection into the generated multipart part.

Claims of guaranteed privilege escalation, authentication bypass, high confidentiality impact, and availability impact are application-dependent downstream consequences, not properties of form-data itself, and are not demonstrated by the PoC.

Severity

The demonstrated, library-attributable impact is integrity (field/header injection); there is no demonstrated confidentiality disclosure or availability impact in form-data itself, and exploitation requires the consuming app to feed untrusted data into field names/filenames. A Moderate (≈5.3, I:L) rating is also defensible given that precondition.

Patch

Fixed in 4.0.6, 3.0.5, and 2.5.6. Users on older 0.x/1.x/2.x releases should upgrade to 2.5.6 or later.

The fix escapes \r, \n, and " as %0D, %0A, and %22 in field names and filenames, matching the WHATWG HTML multipart/form-data encoding algorithm that browsers implement. This neutralizes the injection while leaving ordinary field names (including name[0], dotted, and unicode names) unchanged.

Workaround

Until upgrading, validate or reject field names/filenames that contain control characters before calling append:

if (/[\r\n]/.test(field)) { throw new Error('invalid field name'); }
Credit

Reported by yueyueL.

Severity

  • CVSS Score: 8.7 / 10 (High)
  • Vector String: CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N

References

This data is provided by the GitHub Advisory Database (CC-BY 4.0).


Release Notes

form-data/form-data (form-data)

v4.0.6

Compare Source

Commits
  • [Fix] escape CR, LF, and " in field names and filenames 8dff42c
  • [Dev Deps] update @ljharb/eslint-config, auto-changelog, tape f31d21e
  • [Deps] update hasown, mime-types 92ae0eb
  • [Dev Deps] update js-randomness-predictor 67b0f65

Configuration

📅 Schedule: (in timezone Etc/UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • Only on Sunday and Saturday (* * * * 0,6)
    • Between 11:00 PM and 11:59 PM, Monday through Friday (* 23 * * 1-5)
    • Between 12:00 AM and 04:59 AM, Monday through Saturday (* 0-4 * * 1-6)

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about these updates again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate.

@tryghost-renovate tryghost-renovate Bot added dependencies Pull requests that update a dependency file security labels Jun 15, 2026
@tryghost-renovate

tryghost-renovate Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

⚠️ Artifact update problem

Renovate failed to update an artifact related to this branch. You probably do not want to merge this PR as-is.

♻ Renovate will retry this branch, including artifacts, only when one of the following happens:

  • any of the package files in this branch needs updating, or
  • the branch becomes conflicted, or
  • you click the rebase/retry checkbox if found above, or
  • you rename this PR's title to start with "rebase!" to trigger it manually

The artifact failure details are included below:

File name: pnpm-lock.yaml

<--- Last few GCs --->

[646:0x85a9000]    25975 ms: Mark-Compact (reduce) 1016.2 (1036.7) -> 1016.2 (1030.2) MB, pooled: 0 MB, 219.36 / 0.00 ms  (average mu = 0.135, current mu = 0.000) last resort; GC in old space requested
[646:0x85a9000]    26209 ms: Mark-Compact (reduce) 1016.2 (1030.2) -> 1016.2 (1030.2) MB, pooled: 0 MB, 234.24 / 0.00 ms  (average mu = 0.067, current mu = 0.000) last resort; GC in old space requested


<--- JS stacktrace --->

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
----- Native stack trace -----

 1: 0xe46bbe node::OOMErrorHandler(char const*, v8::OOMDetails const&) [/opt/containerbase/tools/node/22.22.3/bin/node]
 2: 0x1243640 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [/opt/containerbase/tools/node/22.22.3/bin/node]
 3: 0x1243917 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [/opt/containerbase/tools/node/22.22.3/bin/node]
 4: 0x14618cc v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [/opt/containerbase/tools/node/22.22.3/bin/node]
 5: 0x1439a0e v8::internal::Factory::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [/opt/containerbase/tools/node/22.22.3/bin/node]
 6: 0x1428844 v8::internal::FactoryBase<v8::internal::Factory>::AllocateRawWithImmortalMap(int, v8::internal::AllocationType, v8::internal::Tagged<v8::internal::Map>, v8::internal::AllocationAlignment) [/opt/containerbase/tools/node/22.22.3/bin/node]
 7: 0x1429d0e v8::internal::FactoryBase<v8::internal::Factory>::NewRawOneByteString(int, v8::internal::AllocationType) [/opt/containerbase/tools/node/22.22.3/bin/node]
 8: 0x177ff1d v8::internal::String::SlowFlatten(v8::internal::Isolate*, v8::internal::Handle<v8::internal::ConsString>, v8::internal::AllocationType) [/opt/containerbase/tools/node/22.22.3/bin/node]
 9: 0x125b303 v8::String::Utf8Length(v8::Isolate*) const [/opt/containerbase/tools/node/22.22.3/bin/node]
10: 0xf77a87  [/opt/containerbase/tools/node/22.22.3/bin/node]
11: 0x1d5f5e2  [/opt/containerbase/tools/node/22.22.3/bin/node]
/usr/local/bin/node: line 18:   646 Aborted                 (core dumped) /opt/containerbase/tools/node/22.22.3/bin/node "$@"

@tryghost-renovate tryghost-renovate Bot force-pushed the renovate/npm-form-data-vulnerability branch 4 times, most recently from 5847ea4 to a6e87e6 Compare June 16, 2026 03:32
@tryghost-renovate tryghost-renovate Bot changed the title Update dependency form-data to v4.0.6 [SECURITY] Update dependency form-data to v4.0.6 [SECURITY] - autoclosed Jun 16, 2026
@tryghost-renovate tryghost-renovate Bot deleted the renovate/npm-form-data-vulnerability branch June 16, 2026 03:37
@tryghost-renovate tryghost-renovate Bot changed the title Update dependency form-data to v4.0.6 [SECURITY] - autoclosed Update dependency form-data to v4.0.6 [SECURITY] Jun 16, 2026
@tryghost-renovate tryghost-renovate Bot reopened this Jun 16, 2026
@tryghost-renovate tryghost-renovate Bot force-pushed the renovate/npm-form-data-vulnerability branch 2 times, most recently from a6e87e6 to 573766d Compare June 16, 2026 06:14
@tryghost-renovate tryghost-renovate Bot force-pushed the renovate/npm-form-data-vulnerability branch 3 times, most recently from a6e87e6 to 0a6de43 Compare June 16, 2026 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants