Skip to content

Commit 4a25ec5

Browse files
committed
Adds fix for integer keys generated by PHP and adds a note to README.md that integer keys should not be used. Closes #10
1 parent 3ca9a24 commit 4a25ec5

File tree

4 files changed

+37
-8
lines changed

4 files changed

+37
-8
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,9 @@ It is an array of key names, for example:
5353
```php
5454
$sensitive_keys = ['api_key'];
5555
```
56-
Will hash the value of the `api_key`.
56+
Will hash the value of the `api_key`. Because of PHP's tendency to automatically add integer indexes to such an array,
57+
integers in sensitive keys will be ignored and might lead to unexpected results. To be on the safe side, only use
58+
sensitive string keys, or a nested tree of strings.
5759

5860
#### 2. Create a Processor using the keys
5961

src/Hasher.php

+29-2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ protected function traverseInputArray(array $inputArray, array $sensitiveKeys):
9696

9797
// If the value is not an array or an object, hash it if it is a sensitive key
9898
if (is_scalar($value)) {
99-
if (in_array($key, $sensitiveKeys) || array_key_exists($key, $sensitiveKeys)) {
99+
if ($this->isSensitiveKey($key, $sensitiveKeys)) {
100100
$inputArray[$key] = $this->hash(print_r($value, true));
101101
}
102102

@@ -105,7 +105,7 @@ protected function traverseInputArray(array $inputArray, array $sensitiveKeys):
105105

106106
// The value is either an array or an object, let traverse handle the specifics
107107
// If the current key is a sensitive key, traverse the subtree.
108-
if ((in_array($key, $sensitiveKeys) || array_key_exists($key, $sensitiveKeys))) {
108+
if ($this->isSensitiveKey($key, $sensitiveKeys)) {
109109
// If the current key doesn't have a subtree of sensitive keys (indicating the entire subtree,
110110
// and not a value somewhere in the subtree should be hashed)
111111
if (!array_key_exists($key, $sensitiveKeys)) {
@@ -191,4 +191,31 @@ protected function traverseObject(object $object, array $sensitiveKeys): object
191191

192192
return $object;
193193
}
194+
195+
/**
196+
* @param int|string $key
197+
*
198+
* @param array<array-key, mixed> $sensitiveKeys Keys to redact
199+
*
200+
* @return bool Whether the key provided is a sensitiveKey
201+
*/
202+
protected function isSensitiveKey(int|string $key, array $sensitiveKeys): bool
203+
{
204+
// Checks the values, if the key is in the value list of sensitive keys (the 'end' of the sensitive key lists)
205+
if (in_array($key, $sensitiveKeys)) {
206+
return true;
207+
}
208+
209+
// When there is a sub array, check whether the key is in the sensitive key key list
210+
if (array_key_exists($key, $sensitiveKeys)) {
211+
if (is_int($key)) {
212+
// If the key is an integer, this is php generated key, when sensitiveKeys should be a value list
213+
return false;
214+
}
215+
216+
return true;
217+
}
218+
219+
return false;
220+
}
194221
}

tests/HashSensitiveArrayTest.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,18 @@
8686

8787
# Prevent bugs from re-appearing
8888
# Issue: https://github.com/Globy-App/hash-sensitive/issues/10
89-
it('does not hash values of integer keys', function (): void {
89+
it('10 - does not hash values of integer keys', function (): void {
9090
$integerKeys = new TestDataEntity([0 => 'foo', 1 => 'bar'], ['other', 'first', 'second']);
9191
$processor = new HashSensitiveProcessor($integerKeys->getSensitiveKeys());
9292

9393
$record = $this->getRecord(context: $integerKeys->getInput());
94-
expect($processor($record)->context)->toBe(['test' => [0 => 'foo', 1 => 'bar']]);
94+
expect($processor($record)->context)->toBe([0 => 'foo', 1 => 'bar']);
9595
});
9696

97-
it('does not throw an exception', function (): void {
97+
it('10 - does not throw an exception', function (): void {
9898
$integerKeys = new TestDataEntity([0 => ['id' => 1, 'value' => 'foo'], 1 => ['id' => 2, 'value' => 'bar']], ['other', 'first', 'second']);
9999
$processor = new HashSensitiveProcessor($integerKeys->getSensitiveKeys());
100100

101101
$record = $this->getRecord(context: $integerKeys->getInput());
102-
expect($processor($record)->context)->toBe(['test' => [0 => ['id' => 1, 'value' => 'foo'], 1 => ['id' => 2, 'value' => 'bar']]]);
102+
expect($processor($record)->context)->toBe([0 => ['id' => 1, 'value' => 'foo'], 1 => ['id' => 2, 'value' => 'bar']]);
103103
});

tests/HashSensitiveObjectTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@
172172

173173
# Prevent bugs from re-appearing
174174
# Issue: https://github.com/Globy-App/hash-sensitive/issues/
175-
it('does not throw an exception', function (): void {
175+
it('10 - does not throw an exception', function (): void {
176176
$nested1 = new \stdClass();
177177
$nested1->id = 1;
178178
$nested1->value = 'foo';

0 commit comments

Comments
 (0)