security: fix insecure PRNG, pickle RCE, path traversal, and hardcoded secrets#14443
Closed
30678678 wants to merge 1 commit intoTheAlgorithms:masterfrom
Closed
security: fix insecure PRNG, pickle RCE, path traversal, and hardcoded secrets#1444330678678 wants to merge 1 commit intoTheAlgorithms:masterfrom
30678678 wants to merge 1 commit intoTheAlgorithms:masterfrom
Conversation
…d secrets Replace non-CSPRNG random with secrets module in all cryptographic code: - rabin_miller.py: secrets.randbits/randbelow, 40 witness rounds (was 5), guard against num<5 to prevent secrets.randbelow(0) ValueError - rsa_key_generator.py: secrets.randbits for public exponent e - elgamal_key_generator.py: secrets.randbelow for private key d and primitive root g; fix broken primitive_root() filter (pow(g,p,p)==1 is always False by Fermat's Little Theorem; replace with correct Legendre symbol check pow(g,(p-1)//2,p)!=1) - onepad_cipher.py: secrets.randbelow for key generation; update seed-dependent doctests to property-based assertions Replace pickle with json+numpy in CNN model persistence: - convolution_neural_network.py: save_model writes config.json (hyperparameters) and weights.npz (arrays); read_model loads both. Pickle executes arbitrary code on load; neither json nor npz does. Breaking change: existing .pkl model files must be re-saved. Fix path traversal in image downloader: - download_images_from_google_query.py: sanitise query string with re.sub before use as directory name; add Path.resolve() boundary check to reject destinations outside cwd Fix hardcoded secret and plaintext HTTP: - recaptcha_verification.py: read secret key from RECAPTCHA_SECRET_KEY env var instead of hardcoded placeholder - current_weather.py: WEATHERSTACK_URL_BASE was http://, now https:// Replace assert-based validation with proper exceptions: - xor_cipher.py: assert isinstance -> raise TypeError (12 sites) - base64_cipher.py: assert -> raise TypeError/ValueError (3 sites) assert statements are silently removed with python -O/-OO Co-authored-by: Ona <no-reply@ona.com>
Closing this pull request as invalid@30678678, this pull request is being closed as none of the checkboxes have been marked. It is important that you go through the checklist and mark the ones relevant to this pull request. Please read the Contributing guidelines. If you're facing any problem on how to mark a checkbox, please read the following instructions:
NOTE: Only |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Security audit across the codebase. Ten files changed across five vulnerability classes.
1. Insecure PRNG in cryptographic code (
S311)random(Mersenne Twister) is not a CSPRNG — its 19,937-bit state is fully reconstructable after ~624 observed outputs, making generated keys predictable.ciphers/rabin_miller.pyimport random→import secretssecrets.randbelow(num - 3) + 2(range[2, num-2])secrets.randbits(keysize) | (1 << (keysize - 1))(OS entropy, guaranteed bit-length)num < 5raisesValueErrorto preventsecrets.randbelow(0)crashciphers/rsa_key_generator.pyimport random→import secretse:secrets.randbits(key_size) | (1 << (key_size - 1))random.seed(0)doctest; replaced with property-based assertionsciphers/elgamal_key_generator.pyimport random→import secretsd:secrets.randbelow(p - 3) + 3primitive_root()had a dead filter —pow(g, p_val, p_val) == 1is alwaysFalseby Fermat's Little Theorem (gᵖ ≡ g mod p). Replaced with the correct Legendre symbol check:pow(g, (p-1)//2, p) == 1rejects quadratic residues, ensuring the returnedghas orderp-1ciphers/onepad_cipher.pyimport random→import secretssecrets.randbelow(300) + 12. Unsafe pickle deserialization — arbitrary code execution on load
neural_network/convolution_neural_network.pypickleremoved entirelysave_model(path)now writes a directory containing:config.json— hyperparameters (human-readable, no execution risk)weights.npz— weight arrays vianp.savez(numpy's safe binary format)read_model(path)loads both files.pklmodel files must be re-trained and re-saved3. Path traversal via unsanitised query string
web_programming/download_images_from_google_query.pyre.sub(r"[^\w\s-]", "_", query)before use as directory namePath.resolve()boundary check raisesValueErrorif destination escapescwdpathlib.Pathused for all path construction4. Hardcoded secret key and plaintext HTTP
web_programming/recaptcha_verification.pysecret_key = "secretKey"→os.environ.get("RECAPTCHA_SECRET_KEY", "")web_programming/current_weather.pyWEATHERSTACK_URL_BASEwashttp://, nowhttps://5. Security validation via
assert(bypassed withpython -O)assertstatements are silently removed when Python runs with-O/-OOorPYTHONOPTIMIZE=1, making all input validation bypassable.ciphers/xor_cipher.py— 12assert isinstancecalls across 6 methods →raise TypeErrorciphers/base64_cipher.py— 3assertcalls →raise TypeError/raise ValueError