CVE-2021-21421 (YAML, published 2021-04-01T22:15Z)
Description: value: node-etsy-client is a NodeJs Etsy ReST API Client. Applications that are using node-etsy-client and reporting client error to the end user will offer api key value too This is fixed in node-etsy-client v0.3.0 and later.
Severity: MEDIUM (CVSS v3 base score: 6.5)
Weakness: CWE-209 \u2014 Generation of Error Message Containing Sensitive Information
The product generates an error message that includes sensitive information about its environment, users, or associated data.
Repository: https://github.com/creharmony/node-etsy-client
Files changed:
.github/workflows/main.yml
.github/workflows/minor.yml
.github/workflows/patch.yml
README.md
package.json
src/EtsyClient.js
tests/unauthenticated_client.test.js
Commit message: Fix #17 do not report secret on error, add github action


Vulnerable code:
    "test": "mocha tests/*.test.js"
           .catch(reject);

Fixed code:
# node-etsy-client continuous integration

name: etsy_client_ci

# Controls when the action will run.
on:
  # Triggers the workflow on pull request or push (only for the npmjs branch)
  push:
    branches: [ npmjs ]
  pull_request:

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    env:
      ETSY_SHOP: fakefakefakefake

    strategy:
      matrix:
        # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
        # node-version: [10.x, 12.x, 14.x, 15.x]
        node-version: [12.x]

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}

    - name: Cache dependencies
      uses: actions/cache@v2
      with:
        path: |
          **/node_modules
        key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}

    - name: Install dependencies
      # - run: npm ci # need package.json.lock
      run: npm install

    - name: Run ci-tests with code coverage
      run: npm run ci-test

    - name: Report coverage to the PR
      continue-on-error: true
      uses: romeovs/lcov-reporter-action@v0.2.16
      with:
        github-token: ${{ secrets.GITHUB_TOKEN }}
        lcov-file: ./coverage/lcov.info

    - name: Publish NpmJS package
      if: github.ref == 'refs/heads/npmjs'
      run: |
        echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_DEPLOY_TOKEN }}" > .npmrc
        npm whoami # rely on .npmrc
        npm publish
# WIP - node-etsy-client minor from 'main' branch to 'npmjs' branch
name: etsy_client_minor
on:
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [12.x]

    steps:
      - name: Git checkout
        uses: actions/checkout@v2
        with:
          ref: 'npmjs'
          token: ${{ secrets.GH_ACTIONS_TOKEN }}

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}

      - name: Minor
        run: |
          git config --global user.email  'github-actions[bot]@users.noreply.github.com'
          git config --global user.name 'github-actions[bot]'
          git fetch --all
          git checkout main
          npm version minor
          git branch -f npmjs
          git push origin main npmjs --tags
# WIP - node-etsy-client patch from 'main' branch to 'npmjs' branch
name: etsy_client_patch
on:
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [12.x]

    steps:
      - name: Git checkout
        uses: actions/checkout@v2
        with:
          ref: 'npmjs'
          token: ${{ secrets.GH_ACTIONS_TOKEN }}

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}

      - name: Patch
        run: |
          git config --global user.email  'github-actions[bot]@users.noreply.github.com'
          git config --global user.name 'github-actions[bot]'
          git fetch --all
          git checkout main
          npm version patch
          git branch -f npmjs
          git push origin main npmjs --tags
# play test without etsy endpoint
npm run test
# play test with etsy endpoint
    "test": "mocha tests/*.test.js",
    "cover": "nyc --reporter text --reporter cobertura --reporter html --reporter=lcov --lines 66 mocha --exit --unhandled-rejections=strict tests/*.test.js",
    "ci-test": "echo linux ci-test&& nyc --reporter text --reporter cobertura --reporter html --reporter=lcov --lines 66 mocha --exit --unhandled-rejections=strict tests/*.test.js --timeout 5000"
    "nyc": "^15.1.0",
           .catch((fetchError) => {
             var secureError = {};
             this.secureErrorAttribute(secureError, fetchError, "message");
             this.secureErrorAttribute(secureError, fetchError, "reason");
             this.secureErrorAttribute(secureError, fetchError, "type");
             this.secureErrorAttribute(secureError, fetchError, "errno");
             this.secureErrorAttribute(secureError, fetchError, "code");
             reject(secureError);
           });
  secureErrorAttribute(secureError, sourceError, attribute) {
    if (!Object.keys(sourceError).includes(attribute)) {
      return;
    }
    secureError[attribute] = this.secureAttributeValue(sourceError[attribute]);
  }

  secureAttributeValue(value) {
    return (value === null || value === undefined) ? null : value.replace(new RegExp(this.apiKey,'g'), "**hidden**");
  }
const FAKE_API_KEY = "ultraSecretRightHere";

    it("should not report api key in error case", async function() {
      const client = new EtsyClient({
        apiKey:FAKE_API_KEY,
        apiUrl:"https://IAmNotEtsyEndpoint.com"
      });
      const shops = await client.findAllShops()
        .catch((getShopsError) => {
          expect(""+getShopsError).to.not.include(FAKE_API_KEY);
        })
    });