diff --git a/.gitattributes b/.gitattributes index 27ece9e..0666239 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,6 +4,7 @@ /research/ export-ignore /tests/ export-ignore /.gitattributes export-ignore +/.gitleaks.toml export-ignore /.gitignore export-ignore /.editorconfig export-ignore /BUILD-LOG.md export-ignore diff --git a/.gitguardian.yaml b/.gitguardian.yaml index 800acfb..0a6ecef 100644 --- a/.gitguardian.yaml +++ b/.gitguardian.yaml @@ -31,6 +31,8 @@ version: 2 secret: + ignored_paths: + - "tests/Fixtures/**/*" ignored-matches: # --- Still on `KEY=value` lines in the current tree, so these are the # --- entries actually doing work. diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 0000000..e08482f --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,12 @@ +# gitleaks policy. Written by agent-kit's secret_scan.py; extend it by hand, narrowly. +# Only named fixture and example-env paths are allowlisted; secret_scan.py still +# searches them for live-format keys. A realistic fake elsewhere carries an inline +# `gitleaks:allow` comment instead. +[extend] +useDefault = true + +[[allowlists]] +description = "Named fixture and example-env paths (agent-kit secret_scan.py)" +paths = [ + '''^tests/Fixtures/(?:.*/)?[^/]*$''', +] diff --git a/tests/Feature/EncryptionTest.php b/tests/Feature/EncryptionTest.php index 277c4b4..3f5bbcb 100644 --- a/tests/Feature/EncryptionTest.php +++ b/tests/Feature/EncryptionTest.php @@ -44,23 +44,23 @@ }); it('encrypts a value at rest and decrypts it back', function () { - $path = $this->bindEnv("API_TOKEN=plaintext-secret\n", ['laranail.env-kit.auto_backup' => false]); + $path = $this->bindEnv("API_TOKEN=test-secret-not-real\n", ['laranail.env-kit.auto_backup' => false]); EnvKit::encrypt('API_TOKEN'); // at rest the file holds ciphertext, not the plaintext $raw = (string) file_get_contents($path); - expect($raw)->not->toContain('plaintext-secret') + expect($raw)->not->toContain('test-secret-not-real') ->and($raw)->toContain('envkit:'); // get() returns the at-rest ciphertext; getDecrypted() returns the plaintext - expect(EnvKit::get('API_TOKEN'))->not->toBe('plaintext-secret') - ->and(EnvKit::getDecrypted('API_TOKEN'))->toBe('plaintext-secret'); + expect(EnvKit::get('API_TOKEN'))->not->toBe('test-secret-not-real') + ->and(EnvKit::getDecrypted('API_TOKEN'))->toBe('test-secret-not-real'); // decrypt() restores plaintext at rest EnvKit::decrypt('API_TOKEN'); - expect((string) file_get_contents($path))->toContain('API_TOKEN=plaintext-secret') - ->and(EnvKit::get('API_TOKEN'))->toBe('plaintext-secret'); + expect((string) file_get_contents($path))->toContain('API_TOKEN=test-secret-not-real') + ->and(EnvKit::get('API_TOKEN'))->toBe('test-secret-not-real'); }); it('setEncrypted stores ciphertext that getDecrypted reads back', function () { diff --git a/tests/Unit/SecretLeakTest.php b/tests/Unit/SecretLeakTest.php index 5bdf3fc..cfd2abb 100644 --- a/tests/Unit/SecretLeakTest.php +++ b/tests/Unit/SecretLeakTest.php @@ -22,9 +22,9 @@ }); it('scrubs a secret out of any message via the redactor', function () { - $secret = 'super-secret-token-ABC123'; + $secret = 'test-secret-not-real'; - $scrubbed = (new SecretRedactor)->scrub("dsn=postgres://u:{$secret}@h/db", [$secret]); + $scrubbed = (new SecretRedactor)->scrub('dsn=postgres://u:' . $secret . '@h/db', [$secret]); expect($scrubbed)->not->toContain($secret); });