Repository navigation
feat(store): mask credentials before an HTTP record is buffered - #39
Conversation
The HTTP ring buffer is served to AI agents over ext.telescope.requests and MCP, and it stored bearer headers, login passwords and Sanctum tokens as sent. recordHttp now masks hidden request headers and the hidden keys of a JSON request or response body with '********', following Laravel Telescope's hiddenRequestHeaders / hiddenRequestParameters / hiddenResponseParameters model, and emits the masked copy on onHttpRecord. The defaults cover the Fortify, two-factor and OAuth names the magic starter stack sends, including qr_url and qr_svg, which carry the TOTP secret. The walk is depth-capped so recordHttp cannot overflow the stack. TelescopeRedaction exposes the hide* methods (additions merge with the defaults), the lowercased lists, and redactParameters / redactBody for adapters that must mask a body before stringifying or truncating it. HttpRequestRecord gains copyWith.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
Note Kodizm (AI-generated). May contain mistakes; verify before acting. Looks correct and safe to merge. I found no blocking issues, and there is one gap worth considering. I read What I checked:
Minor
TestsNew CI
|
An OAuth password grant or a form login sends grant_type=password& password=...&client_secret=..., which redactBody kept verbatim because it only parsed JSON. A body that reads as a whole form body is now masked pair by pair, with every other pair kept byte for byte. Co-Authored-By: Anılcan Çakır <anilcan.cakir@gmail.com>
|
Round 1 finding, addressed in 1d762e8.
Tests.
Docs. The CHANGELOG (Added and Security), Gates. @kodizm please re-review. |
|
Note Kodizm (AI-generated). May contain mistakes; verify before acting. The fix for the round 1 finding looks correct, and the PR is still safe to merge. Since my last review, 1d762e8 masks form-encoded bodies pair by pair, which settles the earlier Minor. I only reviewed that commit's changes to What I checked:
Minor
TestsNew cases in
CI
|
user[password]=... and codes[]=... were compared whole and kept as sent, while the same key nested in JSON is masked at any depth. Co-Authored-By: Anılcan Çakır <anilcan.cakir@gmail.com>
|
Round 2 Minor, addressed in 20fec47.
Test. Gates. @kodizm please re-review. |
|
Note Kodizm (AI-generated). May contain mistakes; verify before acting. The fix in 20fec47 resolves my round 2 finding, and I found no new issues. This is still safe to merge. This review covers only 20fec47: Round 2 flagged that bracketed form keys went unmasked. They are now masked:
TestsThe new case in
CI
|
Summary
The HTTP ring buffer is served to AI agents over
ext.telescope.*and MCP, and it stored credentials verbatim: the bearer header magic'sAuthInterceptorwrites, the login password in the request body and the token in the login response.TelescopeStore.recordHttpnow masks them before a record is buffered or streamed, following Laravel Telescope's model.TelescopeRedaction: default hidden request headers (authorization,proxy-authorization,cookie,set-cookie,x-api-key), request parameters (passwords, tokens, 2FA and OAuth codes) and response parameters (tokens, secrets, TOTPqr_url/qr_svg, recovery codes), matched case-insensitively and masked as********.hideRequestHeaders,hideRequestParameters,hideResponseParametersextend the defaults, as Laravel's do.redactParameters/redactBodyfor adapters that hold structured data: a body stringified withtoString()is not JSON and cannot be redacted after the fact, so an adapter should redact before it stringifies (magic_devtools does, feat(perf): wire MagicPerfHooks, interaction links and insight rules magic_devtools#22).recordHttpnever throws on odd input; recursion is bounded.Verification
flutter test --exclude-tags=integration: 378 passed, coverage 97.8%;dart analyzeanddart formatclean.Not covered
Credentials in the URL query (
?token=), keyless lists (a bare list of recovery codes) andonErrorbodies of Dio bad-response errors (pre-existing) are left as follow-ups.