javascript.argon2.security.unsafe-argon2-config.unsafe-argon2-config

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Prefer Argon2id where possible. Per RFC9016, section 4 IETF recommends selecting Argon2id unless you can guarantee an adversary has no direct access to the computing environment.

Run Locally

Run in CI

Defintion

rules:
  - id: unsafe-argon2-config
    message: Prefer Argon2id where possible. Per RFC9016, section 4 IETF recommends
      selecting Argon2id unless you can guarantee an adversary has no direct
      access to the computing environment.
    metadata:
      references:
        - https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html
        - https://eprint.iacr.org/2016/759.pdf
        - https://www.cs.tau.ac.il/~tromer/papers/cache-joc-20090619.pdf
        - https://datatracker.ietf.org/doc/html/rfc9106#section-4
      category: security
      cwe:
        - "CWE-916: Use of Password Hash With Insufficient Computational Effort"
      technology:
        - argon2
        - cryptography
      owasp:
        - A02:2021 - Cryptographic Failures
      subcategory:
        - vuln
      impact: LOW
      likelihood: HIGH
      confidence: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Insecure Hashing Algorithm
    languages:
      - javascript
      - typescript
    severity: WARNING
    mode: taint
    pattern-sources:
      - patterns:
          - pattern-inside: |
              $ARGON = require('argon2');
              ...
          - pattern: |
              {type: ...}
    pattern-sinks:
      - patterns:
          - pattern: |
              $Y
          - pattern-inside: |
              $ARGON.hash(...,$Y)
    pattern-sanitizers:
      - patterns:
          - pattern: |
              {type: $ARGON.argon2id}
              ...

Examples

unsafe-argon2-config.js

const argon2 = require("argon2");

const hashSettings = {
  type: argon2.argon2i,
  memoryCost: 2 ** 16,
  parallelism: os.cpus().length || 8,
};

const goodHashSettings = {
  type: argon2.argon2id,
  memoryCost: 2 ** 16,
  parallelism: os.cpus().length || 8,
};

const prepareSavingGood = (user) => {
  if (!user.Password) return Promise.resolve(user);


  return argon2
    // ok: unsafe-argon2-config
    .hash(user.Password, goodHashSettings)
    .then((hash) => ({ ...user, Password: hash }))
    .catch((err) => console.error(`Error during hashing: ${err}`));
};

const prepareSavingBad = (user) => {
  if (!user.Password) return Promise.resolve(user);


  return argon2
    // ruleid:unsafe-argon2-config
    .hash(user.Password, hashSettings)
    .then((hash) => ({ ...user, Password: hash }))
    .catch((err) => console.error(`Error during hashing: ${err}`));
};

const bad = (user) => {
  if (!user.Password) return Promise.resolve(user);
  const hashSettings = {
    type: argon2.argon2i,
    memoryCost: 2 ** 16,
    parallelism: os.cpus().length || 8,
  };

  return argon2
    // ruleid:unsafe-argon2-config
    .hash(user.Password, hashSettings)
    .then((hash) => ({ ...user, Password: hash }))
    .catch((err) => console.error(`Error during hashing: ${err}`));
};

function okTest(user) {
  if (!user.Password) return Promise.resolve(user);
  // ok: unsafe-argon2-config
  return argon2
    .hash(user.Password, {
      type: argon2.argon2id,
      memoryCost: 2 ** 16,
      parallelism: os.cpus().length || 8,
    })
    .then((hash) => ({ ...user, Password: hash }))
    .catch((err) => console.error(`Error during hashing: ${err}`));
}