Conversation
validate() only checked hash_type, so a non-string salt reached operate() and raised a raw TypeError: object of type 'int' has no len(). Over HTTP that is a 500 instead of the 422 every sibling operator returns, and the batch validator that calls validate() never saw the salt at all. Salt checks move into one helper used by both paths; an explicit salt: null now means the documented random salt.
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.
What this fixes
The
hashoperator validateshash_typebut never validatessalt, so a salt of the wrong type survives validation and crashes insideoperate():from
presidio_anonymizer/operators/hash.py:41(len(params[self.SALT])). Printed behaviour atf251c513, callingHash.validate({"hash_type": "sha256", "salt": v})directly:This is not only an ugly exception type. Every sibling operator (
replace,mask,encrypt) reports a bad parameter asInvalidParamError, and the anonymizer server turns that into a 4xx; a rawTypeErrorturns it into a 500 with no message for the caller. It also defeats the pre-flight check:validate()is the function the batch/EngineUtilpath calls to reject bad configurations before any text is touched, and forhashit silently passed anything as long ashash_typewas fine.Change
The salt rules move into one
_validate_salt()helper that bothoperate()andvalidate()call, so the two can no longer disagree:str/bytes/bytearraysalt →InvalidParamError("Invalid salt type '<type>'. ...")str→ encoded tobytes(unchanged)None/ absent → random per-entity salt, as documentedBehaviour changes this PR declares (per AGENTS.md "Declare behavior changes")
Hash.validate()now rejects a wrong-typed salt where it previously accepted it and letoperate()blow up later. No previously-valid input becomes invalid."salt": nullused to raiseTypeError: object of type 'NoneType' has no len(); it now means "no salt supplied", i.e. the documented random per-entity salt.nullis how JSON expresses an absent value, so this matches the operator's own docstring instead of contradicting it.16is now the constantMIN_SALT_LENGTHinstead of a literal in two places; same value, same semantics.Tests
Added to
presidio-anonymizer/tests/operators/test_hash.py: wrong-type salts (int, float, bool, list, object) throughvalidate()and throughanonymize(... OperatorConfig("hash", {"salt": ...})),salt: nullproducing a random salt, and the two existing length messages still raised for str and bytes inputs.Base control —
operators/hash.pyrestored fromf251c513e8aad6820e9b2a44983ebf3a93637b07, withgit diff -- <that file>printing nothing so the run measures upstream code with the new tests kept:With the patch applied:
29 passed. Whole package:presidio-anonymizer/tests→323 passed(excludingtest_ahds_surrogate.py, which needs the optionalpresidio-ahdsextra that is not installed here; that file is untouched by this diff).Lint:
ruff checkon the two changed files reports the same 29 pre-existing findings at base as at head — this diff adds none. Every changed line is executed by the tests above, which is what theAGENTS.md">= 90% coverage on changed lines" rule asks for.