Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[0.28.1] Node16 on Alpine suffers SIGSEGV error when using argon2 verify #302

Closed
Tallyrald opened this issue Jun 7, 2021 · 26 comments
Closed

Comments

@Tallyrald
Copy link

Steps to reproduce

  1. Call the argon2.verify function on Node v16.X.X on alpine linux using argon2 v0.28.1

Click here for reproduction repository

Expected behaviour

Verify function returns either true or false.

Actual behaviour

Node exits with SIGSEGV signal.

Environment

Operating system: Alpine linux (official node docker container)

Node version: 16.X.X

I'm using Typescript v4.3.2

Issue is specific to Node16 & argon2 v0.28.1. Node14 works fine as well as argon2 v0.27.2 (even on Node16).
I'm not sure whether the verify function is the actual or only culprit, but I've seen in my own application that Node definitely crashes while using this function.

@LoicMatters
Copy link

Hello, any update on this ? Got the same problem today on node 16 running on alpine linux with the 0.28.3 package version.

@Janl1
Copy link

Janl1 commented Feb 9, 2022

Can confirm the issue. Downgrading to v0.27.2 solves it temporarily.

@ranisalt
Copy link
Owner

ranisalt commented Feb 10, 2022

I can reproduce it, but I could not isolate the root cause yet

Edit: just found it. Seems to be related to Blake2 secure memory wipe from Argon2. Will try to work around that.

Backtrace for anyone interested:

#0  0x00000000000020d6 in ?? ()
#1  0x00007f49b017c99a in secure_wipe_memory () from /home/node/node_modules/argon2/lib/binding/napi-v3/argon2.node
#2  0x00007f49b017e2fd in blake2b_final () from /home/node/node_modules/argon2/lib/binding/napi-v3/argon2.node
#3  0x00007f49b017d458 in initialize () from /home/node/node_modules/argon2/lib/binding/napi-v3/argon2.node
#4  0x00007f49b017c656 in argon2_ctx () from /home/node/node_modules/argon2/lib/binding/napi-v3/argon2.node
#5  0x00007f49b017bfd7 in Napi::AsyncWorker::OnAsyncWorkExecute(napi_env__*, void*) () from /home/node/node_modules/argon2/lib/binding/napi-v3/argon2.node
#6  0x0000558df991f29d in worker (arg=0x0) at ../deps/uv/src/threadpool.c:122
#7  0x00007f49b3059160 in ?? () from /lib/ld-musl-x86_64.so.1
#8  0x0000000000000000 in ?? ()

@cateiru
Copy link

cateiru commented Jul 20, 2022

This seems to be a problem that occurs when the version of Node.js is different between build and runtime.

Alpine Linux is built with Node 14, so the error occurs with Node 16.
https://github.com/ranisalt/node-argon2/blob/master/.github/workflows/release.yml#L71

The solution is to run the build in source with the npm_config_build_from_source flag set to true.

ARG NODE_VERSION=16.2.0

###
# 1. Dependencies
###

# Build with alpine linux
FROM node:${NODE_VERSION}-alpine as dependencies

WORKDIR /home/node/

ENV NODE_ENV development

# Add `build from source` flag
ENV npm_config_build_from_source true

# Install the tools needed for the build
RUN apk add make g++ python3 git
RUN npm i -g node-pre-gyp

COPY tsconfig.json package.json *package-lock.json ./
RUN npm ci

COPY ts ./ts
# "prod-build" on production
RUN npm run setup && \
    npm prune --production

###
# 2. Application
###

FROM node:${NODE_VERSION}-alpine
WORKDIR /home/node/

COPY --from=dependencies /home/node/node_modules node_modules
COPY --from=dependencies /home/node/built built

COPY package.json ./

ENV PATH="$PATH:/home/node/node_modules/.bin"

RUN chown -R node:node /home/node
USER node

ENV NODE_ENV production

# "start" on production
CMD ["npm", "run", "start"]

@ranisalt
Copy link
Owner

This seems to be a problem that occurs when the version of Node.js is different between build and runtime.

Interestingly, this seems to be only happening with Alpine. I can understand why it happens, but I was expecting node-addon-api to get around those differences in versions. In this case, it may be related to musl in a corner case that NAA didn't expect.

@9x3l6
Copy link

9x3l6 commented Dec 10, 2022

Getting same error...tried everything I could think of...alpine image fails...node image fails...version 0.27.2 fails...anyone knows why it fails?

Error: /home/node/api/node_modules/argon2/lib/binding/napi-v3/argon2.node: invalid ELF header
    at Object.Module._extensions..node (node:internal/modules/cjs/loader:1239:18)
    at Module.load (node:internal/modules/cjs/loader:1033:32)
    at Function.Module._load (node:internal/modules/cjs/loader:868:12)
    at Module.require (node:internal/modules/cjs/loader:1057:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at Object.<anonymous> (/home/node/api/node_modules/argon2/argon2.js:6:25)
    at Module._compile (node:internal/modules/cjs/loader:1155:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1209:10)
    at Module.load (node:internal/modules/cjs/loader:1033:32)
    at Function.Module._load (node:internal/modules/cjs/loader:868:12)
    at Module.require (node:internal/modules/cjs/loader:1057:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at Object.<anonymous> (/home/node/api/src/app.module.ts:8:1)
    at Module._compile (node:internal/modules/cjs/loader:1155:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1209:10)
    at Module.load (node:internal/modules/cjs/loader:1033:32)
ARG NODE_VERSION=16

###########
# INSTALL #
###########

FROM node:${NODE_VERSION} As install

# 👉 Security: do not use the `root` user.
ENV USER=node

# You can not use `${USER}` here, but reference `/home/node`.
ENV PATH="/home/node/.npm-global/bin:${PATH}"
# 👉 The `--global` install dir
ENV NPM_CONFIG_PREFIX="/home/node/.npm-global"

# All subsequent commands are run as the `node` user.
USER "${USER}"

# Pre-create the target dir for global install.
RUN mkdir -p "${NPM_CONFIG_PREFIX}/lib"

WORKDIR /home/node/api

COPY ./tsconfig*.json ./package*.json ./

# RUN chown -R node:node /home/node

# Install python/pip
# ENV PYTHONUNBUFFERED=1
# RUN apk add --update --no-cache python3 && ln -sf python3 /usr/bin/python
# RUN python3 -m ensurepip
# RUN pip3 install --no-cache --upgrade pip setuptools

# 👉 Configure NPM, so pkg get installed with correct credentials.
# Avoids `chmod u+x $DIR` and other workarounds.
RUN npm --global --quiet --no-progress install \
    && npm cache clean --force

#########
# BUILD #
#########

FROM node:${NODE_VERSION} As build

WORKDIR /home/node/api

COPY ./tsconfig*.json ./package*.json ./

COPY --from=install /home/node/api/node_modules ./node_modules

COPY . .

ENV NODE_ENV=production

RUN npm ci --only=production && npm cache clean --force

RUN npm run setup && npm prune --production

RUN npm run build

##############
# PRODUCTION #
##############

FROM node:${NODE_VERSION} As production

WORKDIR /home/node

COPY --from=build /home/node/api/node_modules ./node_modules
COPY --from=build /home/node/api/dist ./dist

ENV PATH="$PATH:/home/node/api/node_modules/.bin"

RUN chown -R node:node /home/node/api
USER node

ENV NODE_ENV production

CMD [ "node", "dist/src/main.js" ]
version: '3.8'

services:
  db:
    # image: mongo # container image to be used
    # restart: always 
    # ports: # expose ports in “host:container” format
    #   - 27017:27017
    # environment: #env variables to pass into the container
    #    MONGODB_DATABASE: zombies
    image:  postgres
    restart: always 
    ports:
      - "${DATABASE_PORT}:5432"
    environment:
      POSTGRES_DB: ${DATABASE_NAME}
      POSTGRES_USER: ${DATABASE_USERNAME}
      POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
    volumes:
      - ./pgdata:/var/lib/postgresql/data
  dev:
    container_name: zombies_dev
    image: zombies-dev:1.0.0
    build:
      context: .
      target: install
      dockerfile: ./Dockerfile
    working_dir: /home/node/api
    command: npm run start:dev #:debug
    ports:
      - 3000:3000
      # - 9229:9229
    networks:
      - zombies-network
    volumes:
      - .:/home/node/api
      # - /home/node/api/node_modules
    restart: unless-stopped
  prod:
    container_name: zombies_prod
    image: zombies-prod:1.0.0
    build:
      context: .
      target: production
      dockerfile: ./Dockerfile
    working_dir: /home/node/api
    command: npm run start:prod
    ports:
      - 3000:3000
      - 9229:9229
    networks:
      - zombies-network
    volumes:
      - .:/home/node
      - /home/node/api/node_modules
    restart: unless-stopped

networks:
  zombies-network:

project url https://github.com/testtestingtester/zombies-angular-nestjs

@ranisalt
Copy link
Owner

ranisalt commented Dec 10, 2022

@testtestingtester the project you sent does not seem to use this library. Additionally, you are not using Alpine, you are using node:16 which uses Debian Buster. There have been reports in the past of people building in an arch and running in another, so check that you are not mixing Debian with Alpine later on.

With that said, can you check the latest version (0.30.2)?

@9x3l6
Copy link

9x3l6 commented Dec 11, 2022

node:16 in the code I pasted but I tried with alpine different versions also, you want me to copy paste those configs? i think not...I'll try 0.30.2 but I'm thinking it's hopeless and probably won't work like the rest I tried...works on mac though

@9x3l6
Copy link

9x3l6 commented Dec 11, 2022

same error even with 0.30.2, i tried downgrading actually because I saw that was the fix others were saying...the project doesn't have the configs in the repo yet but if you try to add them and run docker-compose up -d you'll see it fails with the same error in docker, works on mac without docker just fine

@9x3l6
Copy link

9x3l6 commented Dec 12, 2022

using bcryptjs instead fixes my issue

@jsjoeio
Copy link

jsjoeio commented Dec 19, 2022

Possibly getting the same error here:

    /home/runner/work/code-server/code-server/node_modules/argon2/lib/binding/napi-v3/argon2.node: invalid ELF header

      at Runtime._loadModule (test/node_modules/jest-runtime/build/index.js:1180:29)
      at Object.<anonymous> (node_modules/argon2/argon2.js:6:25)

Using ubuntu-20.04 in CI with GitHub Actions and 0.30.2

@sknight80
Copy link

Hi,

Do you know if we have any updates here? I have the same problem with the latest version of argon2 @ 0.30.3 with alpine.3.17

@Nantris
Copy link

Nantris commented Mar 29, 2023

I just saw this for the first time I can ever recall using 0.30.3, but we also just upgraded Electron so it could be that? But I wouldn't expect this error from upgrading Electron.

Regrettably my scrollback is too small and the error is already gone so I can't see if it was identical to @jsjoeio.

We're running Ubuntu 22.10.

@Nantris
Copy link

Nantris commented Mar 29, 2023

Just hit it again. We're downgrading to 0.29.x.

If I don't report the issue anymore, it's probably safe to assume the issue is 0.30.x and not the Electron upgrade - although I'll try to loop back more explicitly. @ranisalt

@ranisalt
Copy link
Owner

@slapbox I believe you have a different problem than the one in this issue. This one is caused by/within musl so unless it's happening in Alpine or Void it's not the same thing :P

@Tallyrald
Copy link
Author

Tallyrald commented Sep 1, 2023

It's been some time since I reported this issue and unfortunately it's still a valid issue. Compared to 2021, we're currently using:

The only reason I'm bumping this issue is because of the security update introduced through 0.31.0 which we cannot update to without changing to another underlying linux distro or replacing argon2 entirely (which I'd really want to avoid if possible).

Is there anything I can do to help resolve this issue in the near future?

@ranisalt
Copy link
Owner

ranisalt commented Sep 1, 2023

@Tallyrald it would be good if you can get the Alpine developers' attention on this issue, it's super hard to debug and when I traced the exception, it happens inside musl, so it's not something we can change from node-argon2

A bug report on their tracker should be enough to get the ball rolling.

@nekopsykose
Copy link

this happens because the argon2.node plugin is precompiled. you cannot expect to run it on a non-glibc system (where it was originally compiled) and work. that it happened to sometimes work is just a fluke.

there is nothing alpine (or musl) can do to fix this. it works if you rebuild it:

> argon2-sigsegv-repro@1.0.0 start
> node ./built/index.js

[...]
npm ERR! signal SIGSEGV
[...]

$ npx @mapbox/node-pre-gyp rebuild -C node_modules/argon2
$ npm run start

> argon2-sigsegv-repro@1.0.0 start
> node ./built/index.js

$argon2id$v=19$m=65536,t=8,p=2$4ZxaYfo3wi4uQQcG5Iu+Jg$E/XmpSxdshGcocvDa/DHdcSpHiqvH7o4ckjY1GTUj2+qmPAxjJVIrsh/rWjEB2WAdn8
true

@nekopsykose
Copy link

nekopsykose commented Sep 4, 2023

there is nothing alpine (or musl) can do to fix this.

the reason it sometimes happens to work is because musl has some degree of compatibility with glibc (ABI-wise), but it is neither complete nor guaranteed to work (so the older versions just so happened to only use the C api in such a way as to be compatible with either). and when it doesn't match up, having a different ABI than what you compiled against just crashes. there is nothing to do about that (in either alpine, musl, or this repository; though one could argue npm should better handle precompiled binary files and have easy ways to forbid ones that wouldn't work, like how python wheels only install on matching platforms and require building otherwise).

@ranisalt
Copy link
Owner

ranisalt commented Sep 4, 2023

this happens because the argon2.node plugin is precompiled

The precompiled binary will be linked against musl if you are running Alpine.

The problem with the Dockerfile provided in this issue is that it installs dependencies under Debian, but then copies to Alpine and does not perform the install step again to refetch the precompiled binary.

@nekopsykose
Copy link

The precompiled binary will be linked against musl if you are running Alpine.

in that case it would work fine, indeed this specific way of installing it would be broken :)

@nekopsykose
Copy link

yeah, can confirm changing FROM node:${NODE_VERSION} to FROM node:${NODE_VERSION}-alpine alone works as expected

@Tallyrald
Copy link
Author

Thank you @nekopsykose and @ranisalt for your help. For my specific needs the final solution is to run a 2-step pre-build process before copying everything over to the final image.

  • The first step builds most dependencies of the project that need the Debian-based Node image.
  • The second step installs argon2 on an Alpine Node image.
  • The final step is to copy over all dependencies into the target (Alpine-based) image that is used to run the finalized and prepared application.

For me, the problem is resolved now. If this is satisfactory for others too, please close this issue.
Thank you again for your help.

Just for reference, I asked for help in the Alpine issues board HERE which helped the issue move forward and be solved.

@ranisalt
Copy link
Owner

ranisalt commented Sep 5, 2023

@Tallyrald why do you need to run it on Debian? Doesn't Alpine provide the tools you need to build this project?

@Tallyrald
Copy link
Author

We have at least one 3rd party library that doesn't support building on Alpine. Heck it didn't even use to run on Alpine, but that got solved some years ago. I wish I knew why this is, but I'm in no position to make a change in regards to this. Best I can do is to trigger a re-verification if we still need to be so specific with this library.
If people are able to run the build(install)-phase on Alpine, that is the most straightforward solution.

@ranisalt
Copy link
Owner

ranisalt commented Sep 5, 2023

Alright, since the original problem has been solved, I'm closing the issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants