contrib.nodejsscan.header_cookie.cookie_session_no_httponly

profile photo of returntocorpreturntocorp
Author
99
Download Count*
License

Default session middleware settings: httpOnly not set. It ensures the sensitive cookies cannot be accessed by client side JavaScript and helps to protect against cross-site scripting attacks.

Run Locally

Run in CI

Defintion

rules:
  - id: cookie_session_no_httponly
    patterns:
      - pattern-either:
          - pattern-inside: |
              $SESSION = require('cookie-session');
              ...
          - pattern-inside: |
              $SESSION = require('express-session');
              ...
      - pattern: $SESSION(...)
      - pattern-not-inside: $SESSION(<... {cookie:{httpOnly:true}} ...>,...)
      - pattern-not-inside: |
          $OPTS = <... {cookie:{httpOnly:true}} ...>;
          ...
          $SESSION($OPTS,...);
      - pattern-not-inside: |
          $OPTS = ...;
          ...
          $COOKIE = <... {httpOnly:true} ...>;
          ...
          $SESSION($OPTS,...);
      - pattern-not-inside: |
          $OPTS = ...;
          ...
          $OPTS.cookie = <... {httpOnly:true} ...>;
          ...
          $SESSION($OPTS,...);
      - pattern-not-inside: |
          $OPTS = ...;
          ...
          $COOKIE.httpOnly = true;
          ...
          $SESSION($OPTS,...);
      - pattern-not-inside: |
          $OPTS = ...;
          ...
          $OPTS.cookie.httpOnly = true;
          ...
          $SESSION($OPTS,...);
    message: "Default session middleware settings: `httpOnly` not set. It ensures
      the sensitive cookies cannot be accessed by client side JavaScript and
      helps to protect against cross-site scripting attacks."
    severity: WARNING
    languages:
      - javascript
    metadata:
      cwe: "CWE-522: Insufficiently Protected Credentials"
      owasp: A02:2017 - Broken Authentication
      category: security
      technology:
        - node.js
        - express
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]

Examples

header_cookie.js

var session = require('express-session')
var express = require('express')
var app = express()

function test1() {
    var expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour
    var opts = {
        keys: ['key1', 'key2'],
        cookie: {
            secure: true,
            sameSite: 'strict',
            httpOnly: true,
            domain: 'example.com',
            path: 'foo/bar',
            expires: expiryDate
        }
    }
    // ruleid:cookie_session_default
    app.use(session(opts))
}

function test2() {
    // ruleid:cookie_session_no_secure
    app.use(session(Object.assign({
        keys: ['key1', 'key2'],
        name: 'foo'
    }, {
        cookie: {
            httpOnly: true,
            sameSite: true,
            domain: 'example.com',
            path: 'foo/bar',
            expires: new Date(Date.now() + 60 * 60 * 1000)
        }
    })))
}

function test3() {
    // ruleid:cookie_session_no_httponly
    app.use(session({
        keys: ['key1', 'key2'],
        name: 'foo',
        cookie: {
            secure: true,
            sameSite: 'lax',
            domain: 'example.com',
            path: 'foo/bar',
            expires: new Date(Date.now() + 60 * 60 * 1000)
        }
    }))
}

function test4() {
    var opts = {
        keys: ['key1', 'key2'],
        name: 'foo',
    }

    if (app.get('env') === 'production') {
        app.set('trust proxy', 1) // trust first proxy
        opts.cookie = {
            secure: true,
            sameSite: 'strict',
            httpOnly: true,
            path: 'foo/bar',
            expires: new Date(Date.now() + 60 * 60 * 1000)
        }
    }
    // ruleid:cookie_session_no_domain
    app.use(session(opts))
}

function test5() {
    var expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour
    var opts = {
        keys: ['key1', 'key2'],
        name: 'foo',
        cookie: {
            secure: true,
            sameSite: 'strict',
            httpOnly: true
        }
    }

    if (app.get('env') === 'production') {
        app.set('trust proxy', 1) // trust first proxy
        opts.cookie.domain = 'example.com'
        opts.cookie.expires = expiryDate
    }

    // ruleid:cookie_session_no_path
    app.use(session(opts))
}

function test6() {
    var opts = {
        keys: ['key1', 'key2'],
        name: 'foo',
        cookie: {
            secure: true,
            sameSite: 'strict',
            httpOnly: true,
            domain: 'example.com',
            path: 'foo/bar'
        }
    }

    // ruleid:cookie_session_no_expires
    app.use(session(opts))
}

function samestite() {
    var expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour
    var opts = {
        keys: ['key1', 'key2'],
        name: 'foo',
        cookie: {
            secure: true,
            httpOnly: true,
            sameSite: 'none',
            domain: 'example.com',
            path: 'foo/bar',
            expires: expiryDate
        }
    }

    // ruleid:cookie_session_no_samesite
    app.use(session(opts))
}