Skip to content

Add YAML security rules and tests for insecure secret usage #169

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
285 changes: 285 additions & 0 deletions rules/python/security/hashids-with-django-secret-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
id: hashids-with-django-secret-python
language: python
severity: warning
message: >-
The Django secret key is used as salt in HashIDs. The HashID mechanism
is not secure. By observing sufficient HashIDs, the salt used to construct
them can be recovered. This means the Django secret key can be obtained by
attackers, through the HashIDs.
note: >-
[CWE-327]: Use of a Broken or Risky Cryptographic Algorithm
[OWASP A02:2021]: Cryptographic Failures
[REFERENCES]
https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-SECRET_KEY
http://carnage.github.io/2015/08/cryptanalysis-of-hashids
ast-grep-essentials: true
utils:
Hashids(salt=settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH):
kind: call
all:
- has:
kind: identifier
nthChild: 1
regex: ^Hashids$
- has:
kind: argument_list
nthChild: 2
has:
kind: keyword_argument
all:
- has:
kind: identifier
regex: ^salt$
- has:
kind: attribute
all:
- has:
kind: identifier
regex: ^settings$
nthChild: 1
- has:
kind: identifier
nthChild: 2
regex: ^SECRET_KEY$
- all:
- any:
- inside:
stopBy: end
follows:
stopBy: end
kind: import_from_statement
pattern: from django.conf import settings
- follows:
stopBy: end
kind: import_from_statement
pattern: from django.conf import settings
- any:
- inside:
stopBy: end
follows:
stopBy: end
kind: import_from_statement
pattern: from hashids import Hashids
- follows:
stopBy: end
kind: import_from_statement
pattern: from hashids import Hashids

Hashids(settings.SECRET_KEY, min_length=length, alphabet=alphabet):
kind: call
all:
- has:
kind: identifier
nthChild: 1
regex: ^Hashids$
- has:
kind: argument_list
nthChild: 2
has:
kind: attribute
all:
- has:
kind: identifier
regex: ^settings$
nthChild: 1
- has:
kind: identifier
nthChild: 2
regex: ^SECRET_KEY$
- all:
- any:
- inside:
stopBy: end
follows:
stopBy: end
kind: import_from_statement
pattern: from django.conf import settings
- follows:
stopBy: end
kind: import_from_statement
pattern: from django.conf import settings
- any:
- inside:
stopBy: end
follows:
stopBy: end
kind: import_from_statement
pattern: from hashids import Hashids
- follows:
stopBy: end
kind: import_from_statement
pattern: from hashids import Hashids

hashids.Hashids(salt=settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH):
kind: call
all:
- has:
kind: attribute
regex: ^hashids.Hashids$
- has:
kind: argument_list
nthChild: 2
has:
kind: keyword_argument
all:
- has:
kind: identifier
regex: ^salt$
- has:
kind: attribute
all:
- has:
kind: identifier
regex: ^settings$
nthChild: 1
- has:
kind: identifier
nthChild: 2
regex: ^SECRET_KEY$
- any:
- inside:
stopBy: end
follows:
stopBy: end
kind: import_from_statement
pattern: from django.conf import settings
- follows:
stopBy: end
kind: import_from_statement
pattern: from django.conf import settings

hashids.Hashids(settings.SECRET_KEY, min_length=length, alphabet=alphabet):
kind: call
all:
- has:
kind: attribute
nthChild: 1
regex: ^hashids.Hashids$
- has:
kind: argument_list
nthChild: 2
has:
kind: attribute
all:
- has:
kind: identifier
regex: ^settings$
nthChild: 1
- has:
kind: identifier
nthChild: 2
regex: ^SECRET_KEY$
- all:
- any:
- inside:
stopBy: end
follows:
stopBy: end
kind: import_from_statement
pattern: from django.conf import settings
- follows:
stopBy: end
kind: import_from_statement
pattern: from django.conf import settings

hashids.Hashids(salt=django.conf.settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH):
kind: call
all:
- has:
kind: attribute
nthChild: 1
regex: ^hashids.Hashids$
- has:
kind: argument_list
nthChild: 2
has:
kind: keyword_argument
all:
- has:
kind: identifier
regex: ^salt$
- has:
kind: attribute
regex: ^django.conf.settings.SECRET_KEY$

hashids.Hashids(django.conf.settings.SECRET_KEY, min_length=length, alphabet=alphabet):
kind: call
all:
- has:
kind: attribute
nthChild: 1
regex: ^hashids.Hashids$
- has:
kind: argument_list
nthChild: 2
has:
kind: attribute
regex: ^django.conf.settings.SECRET_KEY$

Hashids(django.conf.settings.SECRET_KEY, min_length=length, alphabet=alphabet):
kind: call
all:
- has:
kind: identifier
nthChild: 1
regex: ^Hashids$
- has:
kind: argument_list
nthChild: 2
has:
kind: attribute
regex: ^django.conf.settings.SECRET_KEY$
- any:
- inside:
stopBy: end
follows:
stopBy: end
kind: import_from_statement
pattern: from hashids import Hashids
- follows:
stopBy: end
kind: import_from_statement
pattern: from hashids import Hashids

Hashids(salt=django.conf.settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH):
kind: call
all:
- has:
kind: identifier
nthChild: 1
regex: ^Hashids$
- has:
kind: argument_list
nthChild: 2
has:
kind: keyword_argument
all:
- has:
kind: identifier
regex: ^salt$
- has:
kind: attribute
regex: ^django.conf.settings.SECRET_KEY$
- any:
- inside:
stopBy: end
follows:
stopBy: end
kind: import_from_statement
pattern: from hashids import Hashids
- follows:
stopBy: end
kind: import_from_statement
pattern: from hashids import Hashids


rule:
any:
- matches: Hashids(salt=settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH)
- matches: Hashids(settings.SECRET_KEY, min_length=length, alphabet=alphabet)
- matches: hashids.Hashids(salt=settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH)
- matches: hashids.Hashids(settings.SECRET_KEY, min_length=length, alphabet=alphabet)
- matches: hashids.Hashids(salt=django.conf.settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH)
- matches: hashids.Hashids(django.conf.settings.SECRET_KEY, min_length=length, alphabet=alphabet)
- matches: Hashids(django.conf.settings.SECRET_KEY, min_length=length, alphabet=alphabet)
- matches: Hashids(salt=django.conf.settings.SECRET_KEY, min_length=settings.ID_HASH_MIN_LENGTH)
Loading