swift.lang.storage.sensitive-storage-userdefaults.swift-user-defaults

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Potentially sensitive data was observed to be stored in UserDefaults, which is not adequate protection of sensitive information. For data of a sensitive nature, applications should leverage the Keychain.

Run Locally

Run in CI

Defintion

rules:
  - id: swift-user-defaults
    message: Potentially sensitive data was observed to be stored in UserDefaults,
      which is not adequate protection of sensitive information. For data of a
      sensitive nature, applications should leverage the Keychain.
    severity: WARNING
    metadata:
      likelihood: LOW
      impact: HIGH
      confidence: MEDIUM
      category: security
      cwe:
        - "CWE-311: Missing Encryption of Sensitive Data"
      masvs:
        - "MASVS-STORAGE-1: The app securely stores sensitive data"
      owasp:
        - A03:2017 - Sensitive Data Exposure
        - A04:2021 - Insecure Design
      references:
        - https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/ValidatingInput.html
        - https://mas.owasp.org/MASVS/controls/MASVS-STORAGE-1/
      subcategory:
        - vuln
      technology:
        - ios
        - macos
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - Cryptographic Issues
    languages:
      - swift
    options:
      symbolic_propagation: true
    patterns:
      - pattern-either:
          - patterns:
              - pattern-either:
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: $KEY)
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: $KEY)
              - metavariable-regex:
                  metavariable: $VALUE
                  regex: (?i).*(passcode|password|pass_word|passphrase|pass_code|pass_word|pass_phrase)$
              - focus-metavariable: $VALUE
          - patterns:
              - pattern-either:
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: $KEY)
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: $KEY)
              - metavariable-regex:
                  metavariable: $KEY
                  regex: (?i).*(passcode|password|pass_word|passphrase|pass_code|pass_word|pass_phrase)$
              - focus-metavariable: $KEY
          - patterns:
              - pattern-either:
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: $KEY)
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: $KEY)
              - metavariable-regex:
                  metavariable: $VALUE
                  regex: (?i).*(api_key|apikey)$
              - focus-metavariable: $VALUE
          - patterns:
              - pattern-either:
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: $KEY)
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: $KEY)
              - metavariable-regex:
                  metavariable: $KEY
                  regex: (?i).*(api_key|apikey)$
              - focus-metavariable: $KEY
          - patterns:
              - pattern-either:
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: $KEY)
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: $KEY)
              - metavariable-regex:
                  metavariable: $VALUE
                  regex: (?i).*(secretkey|secret_key|secrettoken|secret_token|clientsecret|client_secret)$
              - focus-metavariable: $VALUE
          - patterns:
              - pattern-either:
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: $KEY)
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: $KEY)
              - metavariable-regex:
                  metavariable: $KEY
                  regex: (?i).*(secretkey|secret_key|secrettoken|secret_token|clientsecret|client_secret)$
              - focus-metavariable: $KEY
          - patterns:
              - pattern-either:
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: $KEY)
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: $KEY)
              - metavariable-regex:
                  metavariable: $VALUE
                  regex: (?i).*(cryptkey|cryptokey|crypto_key|cryptionkey|symmetrickey|privatekey|symmetric_key|private_key)$
              - focus-metavariable: $VALUE
          - patterns:
              - pattern-either:
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set("$VALUE", forKey: $KEY)
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: "$KEY")
                  - pattern: |
                      UserDefaults.standard.set($VALUE, forKey: $KEY)
              - metavariable-regex:
                  metavariable: $KEY
                  regex: (?i).*(cryptkey|cryptokey|crypto_key|cryptionkey|symmetrickey|privatekey|symmetric_key|private_key)$
              - focus-metavariable: $KEY

Examples

sensitive-storage-userdefaults.swift

let username = getUsername()
let passphrase = getPass()


// okid: swift-user-defaults
UserDefaults.standard.set(username, forKey: "userName")
// ruleid: swift-user-defaults
UserDefaults.standard.set(passphrase, forKey: "passphrase")
// ruleid: swift-user-defaults
UserDefaults.standard.set(passWord, forKey: "userPassword")

// ruleid: swift-user-defaults
UserDefaults.standard.set("12717-127163-a71367-127ahc", forKey: "apiKey")

let apiKey = "12717-127163-a71367-127ahc"
// ruleid: swift-user-defaults
UserDefaults.standard.set(apiKey, forKey: "GOOGLE_TOKEN")


let key = "1sdad3SADSD33131"
// ruleid: swift-user-defaults
UserDefaults.standard.set(key, forKey: "cryptoKey")


let key = "foobar"
// ruleid: swift-user-defaults
UserDefaults.standard.set(key, forKey: "clientSecret")


let key = "foobar"
// ruleid: swift-user-defaults
UserDefaults.standard.set(key, forKey: "rsaPrivateKey")

// ruleid: swift-user-defaults
UserDefaults.standard.set(passphrase, forKey: "pass_phrase")