-
Notifications
You must be signed in to change notification settings - Fork 0
Security: remove hardcoded Django SECRET_KEY from settings.py (projects-hub#56) #2
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鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| if [[ $# -ne 1 ]]; then | ||
| echo "Usage: $0 SETTINGS_FILE" >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| settings_file=$1 | ||
| if [[ ! -f "$settings_file" ]]; then | ||
| echo "Settings file not found: $settings_file" >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| # Flag a Django SECRET_KEY assigned a literal quoted string (a value-shaped | ||
| # secret committed to source control), without ever printing the matching | ||
| # value. An environment-variable lookup such as | ||
| # `SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', '')` or | ||
| # `SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')` is not a violation -- only a | ||
| # non-empty literal assigned directly to SECRET_KEY is. | ||
| readonly literal_secret_key_pattern="^[[:space:]]*SECRET_KEY[[:space:]]*=[[:space:]]*['\"][^'\"]+['\"]" | ||
| readonly env_lookup_pattern='os\.(environ|getenv)' | ||
|
|
||
| line_number=0 | ||
| violations=0 | ||
|
|
||
| while IFS= read -r line || [[ -n "$line" ]]; do | ||
| ((line_number += 1)) | ||
| if [[ "$line" =~ $literal_secret_key_pattern ]] && [[ ! "$line" =~ $env_lookup_pattern ]]; then | ||
| echo "Hardcoded SECRET_KEY violation at $settings_file:$line_number" >&2 | ||
| ((violations += 1)) | ||
| fi | ||
| done < "$settings_file" | ||
|
|
||
| if ((violations > 0)); then | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "No hardcoded SECRET_KEY literal found in $settings_file" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| script_directory=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd) | ||
| scanner="$script_directory/check-no-plaintext-secret-key.sh" | ||
| fixture_directory=$(mktemp -d) | ||
| trap 'rm -rf "$fixture_directory"' EXIT | ||
|
|
||
| negative_fixture="$fixture_directory/negative_settings.py" | ||
| cat > "$negative_fixture" <<'EOF' | ||
| # SECURITY WARNING: keep the secret key used in production secret! | ||
| SECRET_KEY = 'this-is-a-fake-non-functional-fixture-value' | ||
| EOF | ||
|
|
||
| if "$scanner" "$negative_fixture" >"$fixture_directory/negative.stdout" 2>"$fixture_directory/negative.stderr"; then | ||
| echo "Expected the value-shaped SECRET_KEY fixture to fail" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| if ! grep -Fxq "Hardcoded SECRET_KEY violation at $negative_fixture:2" "$fixture_directory/negative.stderr"; then | ||
| echo "Expected a redacted violation location for the negative fixture" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [[ -s "$fixture_directory/negative.stdout" ]] || grep -Fq 'fake-non-functional-fixture-value' "$fixture_directory/negative.stderr"; then | ||
| echo "Scanner output was not redacted" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| reference_fixture="$fixture_directory/reference_settings.py" | ||
| cat > "$reference_fixture" <<'EOF' | ||
| # SECURITY WARNING: keep the secret key used in production secret! | ||
| SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', '') | ||
| EOF | ||
|
|
||
| if ! "$scanner" "$reference_fixture" >"$fixture_directory/reference.stdout" 2>"$fixture_directory/reference.stderr"; then | ||
| echo "Expected the environment-variable reference fixture to pass" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [[ -s "$fixture_directory/reference.stderr" ]]; then | ||
| echo "Expected no scanner stderr for the passing fixture" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "Plaintext SECRET_KEY scanner fixtures passed" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,9 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| ./scripts/test-no-plaintext-secret-key.sh | ||
| ./scripts/check-no-plaintext-secret-key.sh project/settings.py | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
At this commit, a repository-wide search still finds the same non-placeholder key literal in tracked AGENTS.md reference: AGENTS.md:L37-L37 Useful? React with 馃憤聽/ 馃憥. |
||
|
|
||
| node --check Gruntfile.js | ||
| python3 - <<'PY' | ||
| import json | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
DJANGO_SECRET_KEYis absent鈥攁s it is for a fresh clone following the README,make install, orrpmanager.sh, none of which provisions or documents this variable鈥攖he expression resolves to an empty string. Django 1.8 rejects an emptySECRET_KEYwhile initializing settings, so both the installation migration and documented launcher fail before the application can start; add a secure provisioning path before requiring the variable.Useful? React with 馃憤聽/ 馃憥.