`client-ip` is not an IP address when `x-forwarded-for` holds a list or a port
Maintainers usually reply within 1 day
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- node.js, typescript
Research direction
Start in src/lib/functions/server.ts at createHandler, then compare the surrounding request handling with src/utils/proxy.ts. Run the issue's functions:serve reproduction using both x-forwarded-for examples. Done means client-ip and x-nf-client-connection-ip contain one valid IP for those inputs while netlify dev remains unaffected.
Written by the indexing model from the issue text.
Description
Describe the bug
Under netlify functions:serve, the client-ip and x-nf-client-connection-ip headers that
reach a serverless function are not always an IP address. They can be the whole
x-forwarded-for list, or a port number.
createHandler builds the value like this (src/lib/functions/server.ts):
let remoteAddress = request.header('x-forwarded-for') || request.connection.remoteAddress || ''
remoteAddress = remoteAddress.split(remoteAddress.includes('.') ? ':' : ',').pop()?.trim() ?? ''
The separator is chosen from whether the string contains a dot, so a comma-separated IPv4 list
is never split on the comma.
Steps to reproduce
mkdir -p netlify/functions
cat > netlify/functions/whoami.js <<'EOF'
exports.handler = async (event) => ({
statusCode: 200,
body: JSON.stringify({ clientIp: event.headers['client-ip'] }),
})
EOF
netlify functions:serve --port 9999 &
curl -s -H 'x-forwarded-for: 1.2.3.4, 5.6.7.8' localhost:9999/.netlify/functions/whoami
curl -s -H 'x-forwarded-for: 1.2.3.4:5678' localhost:9999/.netlify/functions/whoami
Expected behavior
One IP address, i.e. net.isIP(clientIp) !== 0.
Actual behavior
{"clientIp":"1.2.3.4, 5.6.7.8"}
{"clientIp":"5678"}
net.isIP() returns 0 for both. A function that parses client-ip, compares it, or
passes it to a geo/rate-limit library gets a value that cannot be an address, and this
only shows up locally — in production Netlify sends a single address.
Note that netlify dev is unaffected: the dev proxy overwrites x-forwarded-for with
req.connection.remoteAddress before the functions server sees it
(src/utils/proxy.ts), so a single address always arrives. functions:serve runs the
functions server without that proxy, so the client's own header is used verbatim.
Environment
- netlify-cli 27.10.0 (
mainat 904515c) - Node 22.23.3
- Dominant language
- TypeScript
- Stars
- 1.9k
- Forks
- 476
- Avg merge
- 1d 18h
- Merged PRs (30d)
- 37
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from netlify/cli
-
netlify dev returns 403 for static files in subdirectories on Windows (backslash in rewritten path)Open
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
`netlify dev` with `--cwd` from outside the project: every function 500s with "module is not defined in ES module scope" (`detectZisiBuilder` passes a string to `readPackageUp`)Possibly taken @bsplatt92 claimed this 49 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
area: command: deploy area: docs type: feature
Difficulty 1/5 Under an hour Newbie friendliness 88/100
netlify/cli#1984 · 19 comments · 3 reactions ·
Maintainers usually reply within 1 day
-
type: bug
Difficulty 4/5 3-5 days Newbie friendliness 15/100
Maintainers usually reply within 1 day
-
type: bug
Difficulty 3/5 1-2 days Newbie friendliness 62/100
netlify/cli#8522 · 1 comment ·
Maintainers usually reply within 1 day
Similar issues
-
bot:ai-assisted status:untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
midnightntwrk/midnight-js#1424 ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
mksglu/context-mode#1268 ·
Maintainers usually reply within 5 days
-
[bug] Setup fails with "Cannot find matching keyid" when an older Node's corepack is on PATHPossibly taken @EyalPoly claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
MystenLabs/MemWal#1124 · 2 comments ·
Maintainers usually reply within 1 day
-
Edit:Opencheck:failed streams:edit
Difficulty 2/5 1-3 hours Newbie friendliness 60/100
iptv-org/iptv#54352 · 1 comment ·
Maintainers usually reply within 1 day